Mint this company's complaint book, or return the one it already has
Idempotent WITHOUT an Idempotency-Key, and that is a property of the schema rather than a convention: one ACTIVE book per company is a partial unique index, so a repeat returns the same book instead of minting a second. It is deliberately NOT a rotation — rotating retires an identifier the client may already have published, and a verb that could do that as a side effect is how somebody breaks a working form by calling it twice. Use POST /api/v2/complaint-books/rotation for that, where you have to name what you are replacing.
Idempotent WITHOUT an Idempotency-Key, and that is a property of the schema rather than a convention: one ACTIVE book per company is a partial unique index, so a repeat returns the same book instead of minting a second. It is deliberately NOT a rotation — rotating retires an identifier the client may already have published, and a verb that could do that as a side effect is how somebody breaks a working form by calling it twice. Use POST /api/v2/complaint-books/rotation for that, where you have to name what you are replacing.
Authorization
bearerAuth Tenant-bound, scoped and expiring Apifact credential. Migrated legacy credentials are accepted only on deprecated v1 writes and tenant-scoped v2 read, poll and download routes. Each operation names the single scope it requires in x-required-scope; the scope array of the security requirement itself is empty because OpenAPI 3.0 requires it to be for a non-oauth2 scheme.
In: header
Response Body
application/json
application/json
application/json
curl -X POST "https://example.com/api/v2/complaint-books" \ -H "Authorization: Bearer apf_v2_tu_credencial"{ "schemaVersion": "2.0", "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6", "bookId": "710266f4-0087-48f9-97e1-4b13ac48f353", "createdAt": "2019-08-24T14:15:22Z", "intakeUrl": "string"}Read this company's live complaint book identifier GET GET
Returns the opaque identifier your consumers post to, and the intake path built from it. Requires complaints:manage rather than a read scope because the identifier IS the write capability for the public door: handing it to a credential is handing out the ability to publish a form against this book. A company that has never minted one answers 404 COMPLAINT_BOOK_NOT_MINTED, which is not an error state — it is the answer before you POST to this same path.
Require a Turnstile token on this book's public door POST POST
The humanity check, and YOU turn it on. The widget lives on your page and we never see it; all this platform can do is verify the token it produces. IT IS OFF BY DEFAULT AND THAT IS DELIBERATE. Switching it on for everybody at deploy time would break every complaint form that exists, because none of them sends a token yet — and the failure would land on a consumer in the middle of filing a complaint. So it is off until you say your form is ready. ONCE ON, IT FAILS CLOSED. A door that demands the check and a deployment with no Turnstile secret bound answers 503 rather than accepting the complaint unchecked: you asked for protection, and serving a promise nobody is keeping is worse than saying so. A ROTATION CARRIES IT FORWARD. A fresh identifier with the check switched off would open the door at exactly the moment somebody rotated it, which is almost always the moment it was receiving spam. Turning it back off is allowed and easy on purpose: a company whose site key was rotated needs their legal complaint form to keep working while they fix it. Requires complaints:manage, the same capability as rotating, because the consequence is the same class — a form that stops working.