{"openapi":"3.1.0","info":{"title":"Snapfritz API","version":"1.0.0","description":"Upload a PDF form, read the extracted fields, confirm them, sign, download the filled PDF. Requires the Platin plan. Every key acts for exactly one account and is limited to the scopes it was created with. It counts finished forms (a successful sign) and, at twice that number, uploaded PDFs. When either allowance of the period is used up, the call fails with 402 `quota_exceeded`; `quota.kind` says which. Nothing is billed beyond the plan unless an owner has turned on additional forms under Settings → Billing (where offered): a sign beyond the allowance is then charged at the plan's net price per form, up to the owner's monthly cap. `extraForms` in /usage and in a forms `quota_exceeded` shows that state."},"servers":[{"url":"https://snapfritz.com/api/v1"}],"security":[{"bearerAuth":[]}],"paths":{"/usage":{"get":{"operationId":"getUsage","summary":"Allowances for the current period","description":"Scope: documents:read. The top level counts finished forms; `uploads` counts uploaded PDFs; `extraForms` says whether forms beyond the allowance can still be finished, and at what price.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}}}}},"/documents":{"get":{"operationId":"listDocuments","summary":"List documents, newest first","description":"Scope: documents:read","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/DocumentStatus"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Document"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}}}},"post":{"operationId":"uploadDocument","summary":"Upload a PDF and extract its fields","description":"Scope: documents:write. Extraction runs synchronously (typically 10–60 s); the response is the finished document. Either multipart/form-data with a `file` part, or the raw PDF as `application/pdf` (name via `X-Filename`). Max 20 MB and 20 pages. Every upload counts against the upload allowance; unreadable scans end as status `failed` and don't count.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}},"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentWithFields"}}}},"402":{"description":"Upload allowance used up (`quota_exceeded`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Not a PDF","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"More pages than a form may have (`too_many_pages`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (10 uploads/min per key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents/{id}":{"get":{"operationId":"getDocument","summary":"A document with its fields","description":"Scope: documents:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentWithFields"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents/{id}/fields/{fieldId}/confirm":{"post":{"operationId":"confirmField","summary":"Confirm a field, optionally overriding its value","description":"Scope: documents:write. Omit `value` to accept the suggestion as is; `null` or an empty string clears it.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"fieldId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"field":{"$ref":"#/components/schemas/Field"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents/{id}/checkbox-groups/select":{"post":{"operationId":"selectCheckboxOption","summary":"Pick one option of a mutually-exclusive checkbox group","description":"Scope: documents:write. The other options of the group become `not_applicable`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fieldId"],"properties":{"fieldId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Field is not part of a checkbox group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents/{id}/sign":{"post":{"operationId":"signDocument","summary":"Fill the PDF and apply the profile signature","description":"Scope: documents:sign (off by default). Fails with 409 while fields are unconfirmed, 422 if the document needs a stronger signature than we can provide or the profile has no signature. Finishing counts one form against the allowance (a reopened copy doesn't). Once it is used up, the finish is charged as an additional form if an owner turned those on and the cap allows it; otherwise it fails with 402. 403 `plan_required` for a form signed on behalf of the organisation on a plan without that. Idempotent on an already signed document.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}}},"402":{"description":"Allowance of finished forms used up, and additional forms off or at their cap (`quota_exceeded`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan doesn't include signing for the organisation (`plan_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not ready to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Cannot be signed automatically","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents/{id}/download":{"get":{"operationId":"downloadDocument","summary":"The filled, signed PDF","description":"Scope: documents:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"409":{"description":"Not signed yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"`sf_live_…` key from Settings → Developer. Scopes: documents:read, documents:write, documents:sign"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}},"additionalProperties":true}}},"Usage":{"type":"object","properties":{"plan":{"type":"string"},"used":{"type":"integer","description":"Forms finished this period"},"limit":{"type":"integer","description":"Finished forms the plan includes per period"},"remaining":{"type":"integer"},"uploads":{"type":"object","description":"PDFs uploaded this period (twice the forms)","properties":{"used":{"type":"integer"},"limit":{"type":"integer"},"remaining":{"type":"integer"}}},"extraForms":{"type":["object","null"],"description":"Forms beyond the allowance (null where not offered for this plan). Each is charged `unitCents` net, billed monthly in arrears, up to the monthly cap `capCents`; `max` is how many the cap allows this period.","properties":{"enabled":{"type":"boolean","description":"Turned on by an owner"},"used":{"type":"integer","description":"Additional forms finished (and charged) this period"},"max":{"type":"integer"},"remaining":{"type":"integer","description":"0 while turned off"},"unitCents":{"type":"integer"},"capCents":{"type":"integer"},"currency":{"type":"string","enum":["eur"]}}},"resetsAt":{"type":"string","format":"date-time"}}},"DocumentStatus":{"type":"string","enum":["received","understanding","extracting","ready_for_review","in_review","signed","sent","revoked","failed"]},"Field":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"page":{"type":"integer"},"type":{"type":"string","enum":["text","date","checkbox","signature"]},"label":{"type":"string"},"semanticKey":{"type":["string","null"]},"state":{"type":"string","enum":["ok","unsure","missing","hand","not_applicable","out_of_scope"]},"value":{"type":["string","null"]},"source":{"type":"string"},"confirmed":{"type":"boolean"},"checkboxGroup":{"type":["string","null"]}}},"Document":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":"string"},"title":{"type":["string","null"]},"documentType":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/DocumentStatus"},"pageCount":{"type":["integer","null"]},"requiresStrongerSignature":{"type":"boolean"},"requiresStrongerSignatureReason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"signedAt":{"type":["string","null"],"format":"date-time"},"sentAt":{"type":["string","null"],"format":"date-time"},"downloadable":{"type":"boolean"},"reviewUrl":{"type":"string","format":"uri","description":"Open-this-document link for the human (valid 7 days, works without signing in, reaches only this document). Hand over here when a human must decide. Keys without documents:write get the plain page URL (needs a sign-in) instead."}}},"DocumentWithFields":{"allOf":[{"$ref":"#/components/schemas/Document"},{"type":"object","properties":{"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"}}}}]}}}}