API keys and scopes
Issue a key that can do exactly one thing, send it as a bearer token, and read the one error shape.
An API key lets your own software read or write your workspace through https://<your-workspace>.monody.app/api/v1/integrations/*. Issue it under Settings → Forms and API → API keys, pick what it may do, and copy it: the key is shown once.
Sending the key
Send it on every request:
Authorization: Bearer monody_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxScopes
Scopes are the vocabulary of what a key may do. Pick the least the integration needs: a tool that creates leads needs leads:write and nothing else.
leads:read— list leads and read their statusleads:write— create a leadmembers:read,bookings:read,webhooks:manage— reserved: a key can carry them today, and the form says no endpoint reads them yet*— everything, present and future; for a tool you trust with all of it
A scope outside this list cannot be issued, and an old key carrying free text grants nothing for it.
Creating a lead with a key
POST /api/v1/integrations/leads with a JSON body: firstName, lastName (up to 120 characters each), email (stored lower-cased), phone (as typed, normalised to E.164 when it parses), source (defaults to campaign) and consent ({ marketing_email, marketing_sms } booleans, recorded as granted through the API). At least a name, an email or a phone is required.
The answer is 201 with the lead: id, firstName, lastName, email, phone, source, status, score, duplicateOfId (the open lead this one matches, when it does) and createdAt. A lead.created webhook goes out for it. A lead created this way is not assigned to a rep or sent the instant reply; a page that wants both posts to the Lead capture API instead.
Reading leads
GET /api/v1/integrations/leads with leads:read lists leads newest first: limit (1 to 200, default 50), status to filter, and cursor set to the next_cursor of the page before. The answer is { data, next_cursor }.
Errors
Every refusal is one shape, whatever went wrong:
{ "error": { "code": "missing_scope", "message": "This key does not have the leads:read scope. Issue a key with it under Settings → Forms and API → API keys." } }| Code | Status | When |
|---|---|---|
missing_api_key | 401 | No bearer token was sent. |
invalid_api_key | 401 | The key is revoked, expired or not this workspace's. |
missing_scope | 403 | The key does not carry the scope the call needs. |
invalid_json | 400 | The body is not a JSON object. |
validation_failed | 400 | A field is wrong; field names it. |
tenant_not_found | 404 | No workspace at that address. |
| Code | Status | When | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| missing_api_key | 401 | No bearer token was sent. | missing_api_key 401 No bearer token was sent. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invalid_api_key | 401 | The key is revoked, expired or not this workspace's. | invalid_api_key 401 The key is revoked, expired or not this workspace's. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| missing_scope | 403 | The key does not carry the scope the call needs. | missing_scope 403 The key does not carry the scope the call needs. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invalid_json | 400 | The body is not a JSON object. | invalid_json 400 The body is not a JSON object. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| validation_failed | 400 | A field is wrong; field names it. | validation_failed 400 A field is wrong; field names it. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tenant_not_found | 404 | No workspace at that address. | tenant_not_found 404 No workspace at that address. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The message is written to be shown; code is what your code branches on.
Revoking
Revoke a key from its row; every request with it answers invalid_api_key from that moment. The row shows when the key was last used, so a key nothing has used in months is easy to spot and retire.
A question these pages do not answer? Write to support@monody.app.