For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Records that a contact granted one type of consent (`voice_call`, `email` or `data_processing`).
The contact's previous `granted` record of the same type, if any, is marked `revoked` in the same
transaction, so a contact has at most one active grant per type. The history is kept: read it with
`GET /api/compliance/consent/{contactId}` and test it with
`GET /api/compliance/consent/check/{contactId}/{consentType}`.
`contactId` is **not** checked against existing contacts, so a mistyped id records consent for a
contact that does not exist. The request's source IP is stored in `ip_address`. For a server-to-server
API call, that is your server's IP, not the end customer's. Put the customer's proof in `evidence`.
A `voice_call` grant matters when the workspace setting *require consent before calling* is on. The
campaign dialer then skips any contact without an active, unexpired `voice_call` grant.
**Side effects.** Writes a consent record. Evicts the contact's cached consent check and history.
Writes an audit entry (`grant_consent`, with `consentType` and `source`). No provider calls, no messages.
**Idempotency.** Safe to retry in effect: each retry revokes the previous grant and inserts a new one,
so one active grant remains. Each retry does add one more `revoked` row to the history.
**Access**
- **Required scope:** `full`. Signed-in users need the `owner` or `admin` role.
- **Rate limit:** General API — 120 (Starter), 200 (Growth), 300 (Business) or 600 (Enterprise) requests/min per workspace. See [Rate limits](/rate-limits).
- **Plan:** Available on every plan.
Authentication
AuthorizationBearer
Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the
dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once,
at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys.
| Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes |
| --- | --- | --- | --- |
| `read` | Yes | No | No |
| `write` | Yes | Yes | No |
| `full` | Yes | Yes | Yes |
Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in
their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret —
that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds.
See [Authentication](/authentication).
Request
This endpoint expects an object.
contactIdstringRequiredformat: "uuid"
The contact the consent belongs to. Not checked for existence.
consentTypeenumRequired
What the contact agreed to.
- `voice_call`: being called by phone, including by an AI voice agent.
- `email`: receiving commercial email.
- `data_processing`: having personal data stored and processed at all.
Allowed values:
sourcestringRequired1-255 characters
Where the consent was captured, as free text, e.g. web_form, ivr, verbal, whatsapp_optin.
evidencestringOptional<=2000 characters
A reference to the proof, e.g. a form submission id, a recording URL or a signed-document id.
expiresAtdatetimeOptional
When the consent stops counting, as an ISO 8601 UTC datetime with the Z suffix. Offsets such
as -05:00 fail validation. Omit it for consent that does not expire.
Response
Consent recorded.
dataobject
Errors
400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
429
Too Many Requests Error
Records that a contact granted one type of consent (voice_call, email or data_processing).
The contact’s previous granted record of the same type, if any, is marked revoked in the same
transaction, so a contact has at most one active grant per type. The history is kept: read it with
GET /api/compliance/consent/{contactId} and test it with
GET /api/compliance/consent/check/{contactId}/{consentType}.
contactId is not checked against existing contacts, so a mistyped id records consent for a
contact that does not exist. The request’s source IP is stored in ip_address. For a server-to-server
API call, that is your server’s IP, not the end customer’s. Put the customer’s proof in evidence.
A voice_call grant matters when the workspace setting require consent before calling is on. The
campaign dialer then skips any contact without an active, unexpired voice_call grant.
Side effects. Writes a consent record. Evicts the contact’s cached consent check and history.
Writes an audit entry (grant_consent, with consentType and source). No provider calls, no messages.
Idempotency. Safe to retry in effect: each retry revokes the previous grant and inserts a new one,
so one active grant remains. Each retry does add one more revoked row to the history.
Access
Required scope:full. Signed-in users need the owner or admin role.
Rate limit: General API — 120 (Starter), 200 (Growth), 300 (Business) or 600 (Enterprise) requests/min per workspace. See Rate limits.
Plan: Available on every plan.
Workspace API key: jl_ followed by 64 lowercase hex characters, created by the workspace owner in the
dashboard (Settings → API Keys) and sent as Authorization: Bearer jl_.... The plaintext is shown once,
at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys.
Scope
GET / HEAD
POST / PUT / PATCH / DELETE
Admin-only routes
read
Yes
No
No
write
Yes
Yes
No
full
Yes
Yes
Yes
Operations restricted to admins or owners reject keys without the full scope with 403, and say so in
their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret —
that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds.
See Authentication.
What the contact agreed to.
voice_call: being called by phone, including by an AI voice agent.
email: receiving commercial email.
data_processing: having personal data stored and processed at all.