API for developers: keys, scopes and examples

Create a key and read or write forms, responses and reports from your own software.

Go to API & integrations

🔑 Creating a key

  1. 1 Go to "Settings → API & integrations" From the side menu, "Settings", tab "API & integrations".
  2. 2 Click "New key" and give it a name For example "Main website" or "CRM"; create a separate key for each application.
  3. 3 Tick only the scopes you need The three read scopes are enough for reading responses.
  4. 4 Set the rate limit and expiry Default: 120 requests per minute and no expiry.
  5. 5 Copy the key right away The full key starts with ff_live_ and is shown only once; we don't keep a copy either.
Creating keys and webhooks is available from the "Pro" plan up.
Don't put the key in browser-side code (your site's JavaScript) or a public repository; anyone who sees it can access your data. If it leaks, click "Rotate" or "Revoke" right there.

🧩 Scopes

forms:read — list forms and exams, their structure, settings and links.

forms:write — create, edit, publish and delete forms.

responses:read — list and view responses, and CSV / Excel export.

responses:write — tag, annotate, edit and delete responses.

reports:read — reports, statistics, dashboards and report exports.

Account management, the keys themselves and the admin panel never open with an API key.

📡 Base URL, header and first request

The base URL is https://porsino.com/api/v1 and every request needs the Authorization: Bearer header with your key. No cookies or CSRF token are needed.

FORM_ID is the form's id in the forms list output. Each page of responses has up to 100 rows; move on with page.

curl examples
curl -s "https://porsino.com/api/v1/forms?page_size=20" \
  -H "Authorization: Bearer $PORSINO_API_KEY"

curl -s "https://porsino.com/api/v1/forms/FORM_ID/responses?page=1&page_size=50" \
  -H "Authorization: Bearer $PORSINO_API_KEY"

curl -s -o responses.csv "https://porsino.com/api/v1/forms/FORM_ID/responses/export?format=csv" \
  -H "Authorization: Bearer $PORSINO_API_KEY"
The full list of endpoints, parameters and response shapes is at https://porsino.com/api/docs (Swagger), where you can run them too; machine-readable version: https://porsino.com/api/v1/openapi.json

🚦 Rate limits and errors

Each key has its own per-minute limit (default 120); beyond it you get 429 with a Retry-After header.

401 means the key is invalid, revoked or expired; 403 with the code insufficient_scope means the key's scope isn't enough for that action, and fields.scope says which one is needed.

Errors always have the same shape: error with three parts — code, message and fields. With the header Accept-Language: en the message is in English.

🪝 Webhooks: instant updates instead of polling

To notify your system on every new response, open the form → "Integrations" tab and enter your own address. Retries are automatic and every delivery is logged there.

Every delivery carries the X-FlowForm-Event, X-FlowForm-Delivery, X-FlowForm-Timestamp and X-FlowForm-Signature headers. The signature is sha256=HMAC-SHA256 over "timestamp.body" with that webhook's signing key; reject deliveries older than 5 minutes.

Verifying the signature on your server (Python)
import hmac, hashlib

msg = request.headers["X-FlowForm-Timestamp"].encode() + b"." + raw_body
expected = "sha256=" + hmac.new(secret.encode(), msg, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-FlowForm-Signature"])
Delivery is "at least once"; ignore duplicate events using the id in the body.

🌐 Custom domain

Forms and exams can open on a Porsino subdomain or your own domain; connect it under “Settings › Custom domain” (the security certificate is issued automatically).

To bring participants in from your site, add a button or a menu item (see the guide "Exam on your own site, with entry for authorized people only").

Want to set this up on your own form? Creating an account and using Porsino is Free .

Start for free