DocsFor developers
Record consent from your app or website
When people give or change consent in your own app, on your website after they sign in, or in a system your team uses, that system can send each choice straight to Consent Hub. It joins the same record per person as your forms and QR codes, and your systems can check before they message anyone.
Before you start
- Your plan. Consent from your own systems comes with the Governance Suite when your plan includes API access.
- Your purposes. Publish the purposes you'll ask about first. See Set up your purposes.
- Who can create the key. Creating a key needs the Manage security permission, which the Owner and Administrators have.
- The banner inside an app is different. To show your website's consent banner inside a mobile app, add the app under Website Consent, Website Settings, Apps allowed to show this banner. That records the visitor's device choice, like the banner on your website. This page is about choices your own system records against a person it knows.
Add your app or website as a collection
Each system that sends consent is its own collection in Consent Hub, with its own key, so every choice says where it came from.
Create the collection
In the sidebar, under Consent Hub, select Collections, then New collection. Type a name people in your team will recognise, such as Mobile app or Member portal. Under How people reach the form, choose Your app or website (API), then select Save collection.
Create its key
On the collection's page, under Keys, select Create key. You may be asked to sign in again. Choose the Websites the key may use (all of them, or only some), and if you like an expiry date and the IP addresses it may be used from. Select Create key.
Copy the key
Under Shown once: Copy this key now, select Copy key and hand it to your developer securely. It can't be shown again. If it's lost, replace it (see below).
Give your developer the details
Purposes and Options lists each published purpose with its Purpose ID, and the Option IDs of its email, SMS or WhatsApp options, each with a copy button. Sample Request shows a ready-to-run request using your first purpose. Your developer needs both, and the section For your developer below.
Check it's working
Under each key, the collection's page shows:
- Waiting for the first consent until your system's first successful call, then Last successful consent call with its date and time.
- No failed consent calls in the last 24 hours, or how many failed, with the latest one's time and status code.
These lines describe requests, not consents. A batch of up to 100 choices is one request, and it counts as successful even when some choices in it were refused, so check each item's answer in your system. Requests refused before the key is accepted, for example with a wrong or revoked key, don't appear here.
Replace a key
Replace a key when someone who had it leaves, when it may have been exposed, or on your own schedule. The new key works beside the old one, so your system switches over without a gap.
Create the replacement
On the collection's page, select Replace key. The form starts with the current key's Websites and IP addresses. Choose an expiry if you like, select Create replacement key, and copy the new key.
Switch your system over
Give your developer the new key. Both keys are listed, each with its own connection lines, so you can see when your system has moved to the new one.
Revoke the old key
When the old key's last successful call is older than the new key's first one, select Revoke on the old key. The new key keeps working. Nothing is revoked for you.
A collection can have two active keys at a time, so revoke the old key before you replace the new one.
Where the choices show up
- People: each person's history names the collection a choice came from, for example Mobile app (API).
- Exports: a People export, from the Evidence Vault or a person's Records tab, can be limited to one collection.
- Settings, API keys: the key is listed as the collection's consent key, with a link back to it. Consent keys are only made from Consent Hub.
For your developer
This part is for the developer who connects your system. The full API reference is the OpenAPI document. Every path below is relative to https://api.complyzero.com/api/v1/external/consent.
Send the key
Send the key as Authorization: Bearer <key> or X-API-Key: <key>, from your server only, never from a browser or a mobile app's code. Every request is checked against the key's current state, so a revoked key stops working on its next request.
A key limited to some Websites reads and writes organisation-wide purposes and its own Websites' purposes, and nothing of another Website. It may create a new record with its contact details and name, but on a record that already exists it may not add a contact detail, remove one or change the name (403 scope), because those details are shared by every Website's choices. It may link references. A key with no Website limit may do all of this.
Find or create the person
POST /people with your reference (patient_id, membership_id and the other kinds, plus an optional namespace naming your system) finds your record or creates it, and answers the id of every contact detail you sent. Use those ids in your decisions. An email address or phone number never finds or merges records: two family members sharing an inbox stay two records. If someone typed your reference into a public form before you created the record, you still get your own record; to adopt a record you found by email, link your reference to it with POST /people/{personId}/references.
Phone numbers are always E.164 with the country code and its +, for example +919812345678. A number without it is refused naming the field; we never guess a country code. In the GET /people query string, a + in a phone number or an email address may be sent as is (value=+919812345678) or as %2B.
Record a choice
POST /receipts records what the person decided in your app or with your staff:
evidence.collectedAtis when the person acted, never later than now (400 invalid_time). ComplyZero records the purpose version that was published at that moment and counts validity from it.customerNoticerecords what you say you showed; we keep it as your statement.attestationsays how you verified the person for this choice:customer_account(signed in to your app or website),customer_phone_otp,customer_email_otp,staff_in_person, ornone. A first yes needs no particular method (withnoneit is recorded as asserted rather than attested). Turning a choice back on, after the person said no, withdrew or stopped it, or after it expired or the purpose changed, needs a method other thannone; turning messages back on at a contact detail the person stopped also needsattestation.contactnaming that detail, otherwise that option answersnot_saved (attestation_required)and the rest of the request applies. An attested contact must be one of the record's contact details (400 invalid_attestation). Adding or removing contact details needs no attestation.- A choice collected before the latest change to what it targets is recorded as
historyand changes nothing; at an equal time a no wins. So a withdrawal your system collected yesterday never undoes a renewal the person made today.
Choices collected before a purpose was published
If collectedAt is earlier than the purpose's first publication in ComplyZero, no published version can supply a validity the person was told. Send evidence.validUntil with the date you told the person; the grant then applies until that date. Without it the grant is recorded as history (terms_unavailable) and nothing changes.
Check before you message
POST /permissions/query answers each record's current permission and its sequence. With purposes it answers the purposes you name; ids that are not person purposes this key can read are left out of the answer. If you show the person their choices and then send what they change, send that value as basedOnSequence: a yes made on a read that is no longer current answers stale, so you can read again and ask the person to confirm. Withdrawals and declines are never refused as stale. The permissions query is the one place to read the sequence; a receipt's acknowledgement doesn't carry it.
Retries and batches
Every receipt carries a clientEventId you choose: a fresh UUID v4 per choice, never personal data. If a response is lost, send the same request again with the same clientEventId and the same body: you get the original result with duplicate: true, however much later you retry, for as long as the receipt is kept (its retention period). The same clientEventId with a different body is refused (409 idempotency_conflict). GET /receipts/{clientEventId} reads the original result without writing.
After the receipt's retention period has ended, ComplyZero no longer knows the event: GET /receipts/{clientEventId} answers 404 unknown_event, and the same request sent again is recorded as a new choice. So before you resend a request older than the retention period, check it with GET /receipts/{clientEventId} first.
POST /receipts/batch takes up to 100 receipts. Each is recorded on its own, in order, and answered exactly as a single request would be, with its own status; one item's failure never blocks another, and retrying a batch replays the items that were already recorded. An item that failed unexpectedly answers status 500 with internal; send it again with the same clientEventId. A batch holds at most 100 items and counts once against the key's rate limit.
Errors
Every refusal is a problem document whose type ends in a code, for example https://complyzero.com/errors/scope. A body that doesn't fit answers validation with errors naming each field by its path (destinations.1.value). invalid_choices lists the purposes it refers to in purposeIds.
A key without the permission an operation needs answers 403 forbidden, and the detail names it. A key over its own per-minute request limit also answers 403 forbidden. Too many requests from one address answer 429 too-many-requests with a Retry-After header giving the seconds to wait before you send the request again.