API Guide
Collect your team's form submissions — every answer and the finished PDF — automatically, straight into your own systems.
- What the API does
- Before you start
- Quick start: your first test in 5 minutes
- How collecting new submissions works
- The two API addresses
- What you get back
- Ready-to-use examples (PowerShell, Python, Node.js, PHP)
- Without writing code (Power Automate and similar)
- Running it automatically
- Error messages and what to do
- Keeping your login safe
- Troubleshooting and FAQs
1. What the API does
Every time someone on your team fills in a form in Straight2PDF, we store their answers and create a PDF. Normally you look at these on the Submissions page. The API lets another program — your job management system, CRM, accounts software, a shared drive, or a simple script — fetch them automatically, so nobody has to download and re-type anything.
In plain terms, your program asks us “anything new since last time?” and we hand over each new submission: who sent it, when, every answer, and the PDF itself.
2. Before you start
- You need the Pro plan and the API access add-on (£10/month + VAT). The account owner turns it on in the admin area under Settings → Billing → Add-ons → Add API access.
- Copy your username and password straight away. They are shown once, just after you add the add-on (or reset them). We only store a scrambled copy of the password, so we can't show it again — if it's lost, use Reset username & password on the Billing page to get a new one.
- Your username looks like
s2p_followed by 16 letters and numbers. The password is 32 characters. Both are generated for you so they are always strong. - Only your company's submissions are ever returned — your login is tied to your company.
- If someone else (a developer or IT company) is setting this up, send them a link to this page and give them the username and password securely (not in the same email as the link, and never in a shared spreadsheet).
3. Quick start: your first test in 5 minutes
You can check your login works without any programming, using your web browser.
- Open this address in your browser:
https://api.straight2pdf.co.uk/v1/new-submissions/?peek=1&limit=1 - Your browser asks for a username and password. Paste in the ones from the Billing page.
- You'll see some text starting with
{"submissions":[. That's the oldest submission you haven't collected yet (on your first test, your very first submission), in JSON — a standard format programs understand. (If you have no submissions yet, you'll see"submissions":[]— send a test form from the app and try again.)
peek=1? Normally, once a submission has been handed over it counts as “collected” and won't be sent again (see the next section). peek=1 lets you look without marking anything as collected, so testing never uses up real submissions.
Prefer a command line? On Windows 10/11, macOS or Linux, the same test is:
curl -u "YOUR_USERNAME:YOUR_PASSWORD" "https://api.straight2pdf.co.uk/v1/new-submissions/?peek=1&limit=1"On Windows, run this in Command Prompt, or type curl.exe instead of curl in PowerShell.
4. How collecting new submissions works
Think of it like a bookmark. We remember the last submission we gave you. Each time your program asks for new submissions:
- we send the next batch after the bookmark (oldest first, up to 20 at a time),
- then move the bookmark past them, so they aren't sent again.
If the reply says "has_more": true, there are more waiting — ask again straight away until it says false. Then wait a while (for example 15 minutes) and ask again. The examples below do all of this for you.
"waiting_for_processing": true) and send it on your next check, rather than sending it without its PDF.
since_id — for example ?since_id=1000 sends everything after submission 1000 again and moves the bookmark to the end of that batch. Use since_id=0 to start from the very beginning.
5. The two API addresses
Every request uses HTTPS, the GET method, and your username and password (see Basic authentication). Replies are JSON.
New submissions
GET https://api.straight2pdf.co.uk/v1/new-submissions/
| Option | What it does |
|---|---|
limit | How many to send in one go, 1–20 (default 10). PDFs are included, so smaller batches mean smaller, faster replies. |
since_id | Send submissions after this submission ID instead of after the bookmark (to fetch again after a problem). |
peek=1 | Look without moving the bookmark — for testing. |
One submission
GET https://api.straight2pdf.co.uk/v1/submission/?id=123
Returns a single submission by its ID — useful to fetch one again, or to look up a submission someone mentions. You'll find a submission's ID on its page in the admin area (Submission ID at the top) and in every API reply. It doesn't move the bookmark.
curl -u "YOUR_USERNAME:YOUR_PASSWORD" "https://api.straight2pdf.co.uk/v1/submission/?id=123"You'll get a “not found” reply if the ID doesn't exist, belongs to another company, was deleted, or is older than your plan's submission history.
6. What you get back
A reply from new-submissions looks like this (the PDF is shortened here):
{
"submissions": [
{
"submission_id": 1042,
"form_id": 57,
"form_name": "Site Inspection",
"submitted_at": "2026-09-28T14:05:12+01:00",
"status": "submitted",
"submitted_by": { "name": "Sam Jones", "email": "sam@example.co.uk", "guest": false },
"answers": [
{ "field": "site_name", "label": "Site name", "value": "Unit 4, Mill Lane" },
{ "field": "inspection_date", "label": "Inspection date", "value": "28/09/2026" },
{ "field": "passed", "label": "Passed?", "value": "Yes" },
{ "field": "_gps_submit", "label": "Submit location", "value": "51.5072,-0.1276" }
],
"pdf": {
"filename": "submission_1042.pdf",
"content_type": "application/pdf",
"content_base64": "JVBERi0xLjcKJcOkw7zDtsOf... (the whole PDF)"
}
}
],
"cursor": 1042,
"has_more": false,
"waiting_for_processing": false,
"peek": false
}| Field | Meaning |
|---|---|
submission_id | The submission's unique number. Use it to avoid saving the same one twice. |
form_id, form_name | Which of your forms it was. |
submitted_at | Date and time it was sent, in standard ISO 8601 format including the time-zone offset (e.g. +01:00 in British Summer Time). |
status | Where it is in any review process, e.g. submitted or approved. |
submitted_by | Name and email of the person who sent it. guest: true means it came through a guest form link. |
answers | Every answer: field is the form field's fixed code (best for programs — it doesn't change if you rename the question), label is the question as shown on the form, value is the answer. Signatures and photos are sent as image data. Locations look like "51.5072,-0.1276". |
pdf | The finished PDF: filename and content_base64 (the file written as text — turn it back into a PDF as in the examples). null if the form has no PDF. |
cursor | Where the bookmark is now (the last submission ID handed over). |
has_more | true if more submissions are ready now — ask again straight away. |
waiting_for_processing | true if the next one is still generating its PDF; it'll come on your next check. |
The submission address returns {"submission": { ... }} with the same fields for one submission.
7. Ready-to-use examples
Each example collects everything new and saves every submission as a PDF and a .json file of its answers, then stops. Replace YOUR_USERNAME and YOUR_PASSWORD with your login. Run it on a schedule (see section 9) and new submissions keep arriving.
Windows PowerShell (no installing needed)
Save as collect-straight2pdf.ps1, then right-click → Run with PowerShell. Files are saved to C:\Straight2PDF Submissions.
# Collects new Straight2PDF submissions and saves each one as a PDF plus a
# .json file of its answers. Safe to run as often as you like.
$username = "YOUR_USERNAME"
$password = "YOUR_PASSWORD"
$saveTo = "C:\Straight2PDF Submissions"
$pair = "{0}:{1}" -f $username, $password
$headers = @{ Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($pair)) }
New-Item -ItemType Directory -Force -Path $saveTo | Out-Null
do {
$result = Invoke-RestMethod -Uri "https://api.straight2pdf.co.uk/v1/new-submissions/?limit=20" -Headers $headers
foreach ($s in $result.submissions) {
$name = "submission_{0}" -f $s.submission_id
if ($s.pdf) {
[IO.File]::WriteAllBytes((Join-Path $saveTo "$name.pdf"), [Convert]::FromBase64String($s.pdf.content_base64))
}
$s | Select-Object -Property * -ExcludeProperty pdf | ConvertTo-Json -Depth 10 |
Set-Content -Encoding UTF8 (Join-Path $saveTo "$name.json")
Write-Host "Saved $name ($($s.form_name))"
}
} while ($result.has_more)
Python
# Collects new Straight2PDF submissions and saves each one as a PDF plus a
# .json file of its answers. Needs: pip install requests
import base64, json, pathlib, requests
USERNAME = "YOUR_USERNAME"
PASSWORD = "YOUR_PASSWORD"
save_to = pathlib.Path("straight2pdf_submissions")
save_to.mkdir(exist_ok=True)
while True:
response = requests.get(
"https://api.straight2pdf.co.uk/v1/new-submissions/",
params={"limit": 20},
auth=(USERNAME, PASSWORD),
timeout=120,
)
response.raise_for_status()
data = response.json()
for s in data["submissions"]:
name = f"submission_{s['submission_id']}"
if s["pdf"]:
(save_to / f"{name}.pdf").write_bytes(base64.b64decode(s["pdf"]["content_base64"]))
s.pop("pdf", None)
(save_to / f"{name}.json").write_text(json.dumps(s, indent=2))
print("Saved", name, s["form_name"])
if not data["has_more"]:
break
Node.js
Save as collect.mjs and run node collect.mjs.
// Collects new Straight2PDF submissions (Node.js 18 or newer, no packages needed).
import { writeFile, mkdir } from "node:fs/promises";
const USERNAME = "YOUR_USERNAME";
const PASSWORD = "YOUR_PASSWORD";
const auth = "Basic " + Buffer.from(`${USERNAME}:${PASSWORD}`).toString("base64");
await mkdir("straight2pdf_submissions", { recursive: true });
let data;
do {
const response = await fetch("https://api.straight2pdf.co.uk/v1/new-submissions/?limit=20", {
headers: { Authorization: auth },
});
if (!response.ok) throw new Error(`API error ${response.status}: ${await response.text()}`);
data = await response.json();
for (const s of data.submissions) {
const name = `straight2pdf_submissions/submission_${s.submission_id}`;
if (s.pdf) await writeFile(`${name}.pdf`, Buffer.from(s.pdf.content_base64, "base64"));
const { pdf, ...answers } = s;
await writeFile(`${name}.json`, JSON.stringify(answers, null, 2));
console.log("Saved", name, s.form_name);
}
} while (data.has_more);
PHP
<?php
// Collects new Straight2PDF submissions (PHP with the curl extension).
$username = 'YOUR_USERNAME';
$password = 'YOUR_PASSWORD';
$saveTo = __DIR__ . '/straight2pdf_submissions';
@mkdir($saveTo);
do {
$ch = curl_init('https://api.straight2pdf.co.uk/v1/new-submissions/?limit=20');
curl_setopt_array($ch, [
CURLOPT_USERPWD => $username . ':' . $password,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
exit("API error $status: $body\n");
}
$data = json_decode($body, true);
foreach ($data['submissions'] as $s) {
$name = $saveTo . '/submission_' . $s['submission_id'];
if ($s['pdf']) {
file_put_contents($name . '.pdf', base64_decode($s['pdf']['content_base64']));
}
unset($s['pdf']);
file_put_contents($name . '.json', json_encode($s, JSON_PRETTY_PRINT));
echo "Saved {$name} ({$s['form_name']})\n";
}
} while ($data['has_more']);
8. Without writing code (Power Automate and similar)
Any automation tool that can make an HTTP GET request with Basic authentication can use the API — for example Microsoft Power Automate, Make or Zapier (“Webhooks”). As an example, to save every new PDF to OneDrive or SharePoint with Power Automate:
- Create a Scheduled cloud flow that repeats every 15 minutes.
- Add an HTTP action: Method
GET, URIhttps://api.straight2pdf.co.uk/v1/new-submissions/?limit=20, Authentication Basic, with your username and password. (The HTTP action needs a Power Automate premium licence.) - Add Parse JSON on the HTTP body, using the example reply in section 6 to “Generate from sample”.
- Add Apply to each over
submissions, and inside it Create file with File namesubmission_+submission_id+.pdfand File content set to this expression:
base64ToBinary(items('Apply_to_each')?['pdf']?['content_base64'])To catch busy periods, wrap steps 2–4 in a Do until that stops when has_more is false.
9. Running it automatically
Windows (Task Scheduler): open Task Scheduler → Create Basic Task → name it “Collect Straight2PDF submissions” → Trigger Daily → Action Start a program: Program powershell.exe, Arguments -ExecutionPolicy Bypass -File "C:\Scripts\collect-straight2pdf.ps1". Then open the task's properties → Triggers → Edit → tick Repeat task every 15 minutes for a duration of 1 day.
Linux or Mac (cron): run crontab -e and add a line like:
*/15 * * * * /usr/bin/python3 /home/you/collect_straight2pdf.py >> /home/you/straight2pdf.log 2>&1Every 5–30 minutes is plenty. Checking more often than once a minute doesn't get submissions any faster and may hit the rate limit.
10. Error messages and what to do
Errors come back as JSON like {"error": "unauthorised", "message": "..."} with one of these HTTP status codes:
| Code | Meaning | What to do |
|---|---|---|
| 200 | OK | All good. |
| 401 | Wrong username or password, or API access isn't active | Check for spaces when pasting. Has the login been reset (the old one stops working)? Is the API access add-on still on, and is the company still on Pro? |
| 403 | Blocked address, or plain http:// | Your company has set allowed IP addresses and this request came from somewhere else — contact us to add the address (the message tells you which address we saw). Or the address starts with http:// — always use https://. |
| 404 | Submission not found | Check the ID. It may have been deleted, belong to another company, or be older than your plan's history. |
| 405 | Wrong method | Use GET. |
| 429 | Too many requests | Slow down and try again in a minute. Limits: 60 requests a minute; 10 failed logins in 10 minutes from one address blocks that address for a while. |
| 500 / 503 | A problem on our side | Try again in a few minutes. If you are not sure a batch arrived safely, fetch it again with since_id (see section 4). |
11. Keeping your login safe
- The API uses Basic authentication over HTTPS: your program sends the username and password with every request, encrypted in transit. Most tools have a “Basic auth” option; if you build the header yourself it is
Authorization: Basicfollowed byusername:passwordencoded in Base64, for example:
Authorization: Basic czJwX2FiYzEyMzpleGFtcGxlLXBhc3N3b3Jk- Treat the password like a bank password: store it in your program's settings or a password manager, not in emails, chat messages or shared documents.
- HTTPS only. Requests to
http://are refused, never redirected, so a mistyped address fails straight away instead of sending your password unencrypted. - Only the account owner can reset the login. If you think it has been seen by someone who shouldn't have it, reset it straight away on the Billing page — the old one stops working immediately — and put the new one into your program.
- Email alerts: the account owner(s) get an email whenever a new login is issued or reset, saying who did it, when and from where. If you didn't expect one, reset the login and change your own password.
- Allowed IP addresses (recommended): we can restrict your login to the address(es) your system connects from — single addresses or ranges such as
203.0.113.0/24. The login is then refused from anywhere else, so a leaked password is useless on its own. Contact us with the addresses (the recent activity list on the Billing page shows which one your system uses); the Billing page shows the current list. If your system's address changes (some home and cloud connections do), let us know or calls will fail with 403. - Recent activity: the Billing page lists the last 20 API calls — when, from which address, which endpoint, whether it worked, and how many submissions were sent — including failed logins with your username. Calls are kept for 90 days.
- Removing the API access add-on turns the login off.
12. Troubleshooting and FAQs
I get an empty list, but I know there are submissions.
They've probably already been collected (the bookmark has moved past them) — perhaps by an earlier test without peek=1. Fetch them again with ?since_id=0 (everything) or ?since_id= a submission ID just before the ones you want.
A submission has "pdf": null.
That form doesn't produce a PDF (for example some HR forms), or the PDF couldn't be created. You still get all the answers. You can check the submission's page in the admin area.
Some older submissions aren't available.
The API follows your plan's submission history (6 months on Pro, 18 months on Business).
Can I send data into Straight2PDF, or change submissions?
Not at the moment — the API is read-only.
Can we have more than one login?
There's one login per company. If several systems need the data, collect it once and share it internally, or ask us.
Where's my username?
On the Billing page, under API access. The password is never shown again after it's issued — reset it to get a new one.
Still stuck?
Contact us with the time you made the request and the error message you saw (never send us your password).
