API Keys, Scopes & Rate Limits
Once you have issued an API key (see Authentication for basic setup), you can configure its scope and expiry to match your security requirements. Rate limiting is enforced by the platform and is not configurable per key.
Scopes
Each API key is assigned one or more scopes that determine which resources and operations it can access. Scopes follow a verb:resource pattern:
| Scope | Access |
|---|---|
read:products | Read (list) your product catalog |
write:products | Create and update products |
read:contacts | Read (list) your contacts |
write:contacts | Create and update contacts |
read:companies | Read (list) your companies |
write:companies | Create and update companies |
read:deals | Read (list) your deals |
write:deals | Create and update deals |
read:notes | Read (list) your notes |
write:notes | Create and update notes |
read:emails | Read (list) emails, drafts and replies, the workspace's sending identities, and shared inbox conversations, comments and counts |
write:emails | Compose, edit, reply to and delete email drafts (never sends), and triage shared inbox conversations: assign, close, tag, archive, snooze, spam, trash and comment |
send:emails | Release a draft: transmits real email |
read:communications | Read a contact's logged calls, meetings and messages |
write:communications | Log calls, meetings, LinkedIn messages and off-platform emails |
read:tasks | Read (list) your tasks and calendar appointments |
write:tasks | Create, update, and delete tasks and calendar appointments |
read:calendar | Read the merged calendar (tasks, deal closes, campaign sends, follow-ups, birthdays) |
write:calendar | Put meetings on the CRM calendar and refresh a user's connected calendars |
read:bookings | List and read bookings, meeting types, hours, hosts and open slots |
write:bookings | Book, cancel and reschedule meetings; create, change, pause and archive meeting types; change hours and host timezones |
read:offerings | Read your offerings' campaign summaries and communication timeline |
write:offerings | Create and update offerings |
read:leads | Read (list) your leads |
write:leads | Capture and update leads |
read:contracts | Read your contracts and their renewal dates |
write:contracts | Create contracts and change their status or term |
read:cases | Read your support cases and their resolution clocks |
write:cases | Open cases and change their status, severity or assignee |
read:quotes | Read quotes, their line items and totals |
write:quotes | Create quotes and change their status |
read:campaigns | Read campaigns and their delivery analytics |
write:campaigns | Create, edit, delete, launch and cancel campaigns (launching queues drafts; it never sends) |
read:sequences | Read sequences, their steps and enrollment stats |
write:sequences | Create sequences and enroll contacts (a SEND-mode sequence also needs send:emails) |
read:chat | List website chat conversations and read their transcripts |
write:chat | Reply to visitors, take over and hand back chats, and close, assign, tag or mark them as spam |
read:files | List the files on a record and download them |
write:files | Attach files to records and delete them |
read:team | List the workspace's users (read-only) |
read:tags | List tags with usage counts |
write:tags | Create, rename and delete tags, and tag or untag records in bulk |
read:pipelines | List pipelines and their stages |
write:pipelines | Create, rename and delete pipelines, and add, update, reorder and delete stages |
read:custom-fields | List custom field definitions |
write:custom-fields | Create, update and delete custom field definitions |
read:workflows | List workflows and read their recent runs |
write:workflows | Create, change, pause and delete workflows |
read:forms | List lead-capture forms and their submissions |
read:suppressions | List suppressed email addresses |
write:suppressions | Suppress an address, or lift an opt-out |
read:reports | Read the Performance report and shared saved views |
read:webhooks | List webhook endpoints, their event types and delivery history |
write:webhooks | Add, change, delete and test webhook endpoints, rotate secrets and resend events |
* | Full access to all resources and operations |
Scope hierarchy
write:scopes do NOT grantread:— a key withwrite:productscannot list products. You must issue separate read and write scopes if both are needed.*(full access) grants all scopes and operations.- No scope = no access (default behavior if no scope is selected).
Per-endpoint scopes
| Endpoint | Method | Required Scope |
|---|---|---|
/api/v1/products | GET | read:products |
/api/v1/products | POST | write:products |
/api/v1/contacts | POST | write:contacts |
/api/v1/companies | POST | write:companies |
/api/v1/deals | POST | write:deals |
/api/v1/notes | POST | write:notes |
/api/v1/emails | GET | read:emails |
/api/v1/emails | POST | write:emails |
/api/v1/emails/identities | GET | read:emails |
/api/v1/emails/{id} | GET | read:emails |
/api/v1/emails/{id} | PATCH, DELETE | write:emails |
/api/v1/emails/{id}/reply | POST | write:emails |
/api/v1/emails/{id}/send | POST | send:emails |
/api/v1/communications | GET | read:communications |
/api/v1/communications | POST | write:communications |
/api/v1/tasks | POST | write:tasks |
/api/v1/tasks/{id} | DELETE | write:tasks |
/api/v1/calendar | GET | read:calendar |
/api/v1/products/{id}/communication | GET | read:offerings |
/api/v1/leads | GET | read:leads |
/api/v1/contracts | GET | read:contracts |
/api/v1/contracts/{id} | GET | read:contracts |
/api/v1/cases | GET | read:cases |
/api/v1/cases/{id} | GET | read:cases |
/api/v1/files | GET | read:files |
/api/v1/files | POST | write:files |
/api/v1/files/upload-url | POST | write:files |
/api/v1/files/{id} | GET | read:files |
/api/v1/files/{id} | DELETE | write:files |
/api/v1/contacts/duplicates | GET | read:contacts |
/api/v1/contacts/{id}/merge | POST | write:contacts |
/api/v1/contacts/{id}/brief | POST | write:contacts |
/api/v1/leads/{id}/convert | POST | write:leads |
/api/v1/products/{id}/prospects | GET | read:offerings + read:contacts |
/api/v1/products/{id}/match | POST | write:offerings + read:contacts |
/api/v1/outreach-matches/{id} | GET | read:offerings + read:contacts |
/api/v1/outreach-matches/{id}/candidates/{candidateId} | PATCH | write:offerings |
/api/v1/outreach-matches/{id}/drafts | POST | write:offerings + write:emails |
/api/v1/contracts | POST | write:contracts |
/api/v1/contracts/{id}/status | POST | write:contracts |
/api/v1/cases | POST | write:cases (+ read:emails with emailId) |
/api/v1/cases/{id}/status | POST | write:cases |
/api/v1/quotes | GET | read:quotes |
/api/v1/quotes | POST | write:quotes |
/api/v1/quotes/{id} | GET | read:quotes |
/api/v1/quotes/{id}/status | POST | write:quotes |
/api/v1/campaigns | GET | read:campaigns |
/api/v1/campaigns | POST | write:campaigns |
/api/v1/campaigns/{id} | GET | read:campaigns |
/api/v1/campaigns/{id} | PATCH, DELETE | write:campaigns |
/api/v1/campaigns/{id}/launch | POST | write:campaigns |
/api/v1/campaigns/{id}/cancel | POST | write:campaigns |
/api/v1/sequences | GET | read:sequences |
/api/v1/sequences | POST | write:sequences (+ send:emails for SEND mode) |
/api/v1/sequences/{id} | GET | read:sequences |
/api/v1/sequences/{id}/enrollments | POST | write:sequences (+ send:emails for SEND mode) |
/api/v1/inbox/threads | GET | read:emails |
/api/v1/inbox/threads/{threadKey} | GET | read:emails |
/api/v1/inbox/threads/{threadKey}/comments | GET | read:emails |
/api/v1/inbox/threads/{threadKey}/comments | POST | write:emails |
/api/v1/inbox/threads/assign, /status, /spam, /trash, /archive, /snooze, /tags | POST | write:emails |
/api/v1/inbox/summary | GET | read:emails |
/api/v1/inbox/assignees | GET | read:emails |
/api/v1/chats | GET | read:chat |
/api/v1/chats/{id} | GET | read:chat |
/api/v1/chats/{id}/reply | POST | write:chat |
/api/v1/chats/{id}/take-over | POST | write:chat |
/api/v1/chats/{id}/hand-back | POST | write:chat |
/api/v1/chats/{id}/close | POST | write:chat |
/api/v1/chats/{id}/reopen | POST | write:chat |
/api/v1/chats/{id}/assign | POST | write:chat |
/api/v1/chats/{id}/tags | POST, DELETE | write:chat |
/api/v1/chats/{id}/spam | POST | write:chat |
/api/v1/calendar/meetings | POST | write:calendar |
/api/v1/calendar/refresh | POST | write:calendar |
/api/v1/bookings | GET | read:bookings |
/api/v1/bookings | POST | write:bookings |
/api/v1/bookings/{id} | GET | read:bookings |
/api/v1/bookings/{id}/cancel | POST | write:bookings |
/api/v1/bookings/{id}/reschedule | POST | write:bookings |
/api/v1/bookings/{id}/slots | GET | read:bookings |
/api/v1/booking-types | GET | read:bookings |
/api/v1/booking-types | POST | write:bookings |
/api/v1/booking-types/{id} | GET | read:bookings |
/api/v1/booking-types/{id} | PATCH, DELETE | write:bookings |
/api/v1/booking-types/{id}/slots | GET | read:bookings |
/api/v1/booking-types/{id}/hours | GET | read:bookings |
/api/v1/booking-types/{id}/hours | PUT | write:bookings |
/api/v1/booking-types/{id}/date-overrides/{date} | PUT, DELETE | write:bookings |
/api/v1/booking-hosts | GET | read:bookings |
/api/v1/booking-hosts/{id} | GET | read:bookings |
/api/v1/booking-hosts/{id} | PATCH | write:bookings |
/api/v1/team | GET | read:team |
/api/v1/tags | GET | read:tags |
/api/v1/tags | POST | write:tags |
/api/v1/tags/{id} | PATCH, DELETE | write:tags |
/api/v1/tags/assign | POST | write:tags |
/api/v1/tags/unassign | POST | write:tags |
/api/v1/pipelines | GET | read:pipelines |
/api/v1/pipelines | POST | write:pipelines |
/api/v1/pipelines/{id} | GET | read:pipelines |
/api/v1/pipelines/{id} | PATCH, DELETE | write:pipelines |
/api/v1/pipelines/{id}/stages | POST | write:pipelines |
/api/v1/pipelines/{id}/stages/reorder | POST | write:pipelines |
/api/v1/stages/{id} | PATCH, DELETE | write:pipelines |
/api/v1/custom-fields | GET | read:custom-fields |
/api/v1/custom-fields | POST | write:custom-fields |
/api/v1/custom-fields/{id} | GET | read:custom-fields |
/api/v1/custom-fields/{id} | PATCH, DELETE | write:custom-fields |
/api/v1/workflows | GET | read:workflows |
/api/v1/workflows | POST | write:workflows |
/api/v1/workflows/{id} | GET | read:workflows |
/api/v1/workflows/{id} | PATCH, DELETE | write:workflows |
/api/v1/workflows/{id}/runs | GET | read:workflows |
/api/v1/forms | GET | read:forms |
/api/v1/forms/{id}/submissions | GET | read:forms |
/api/v1/suppressions | GET | read:suppressions |
/api/v1/suppressions | POST | write:suppressions |
/api/v1/suppressions/{id} | DELETE | write:suppressions |
/api/v1/reports | GET | read:reports |
/api/v1/saved-views | GET | read:reports |
/api/v1/webhooks | GET | read:webhooks |
/api/v1/webhooks | POST | write:webhooks |
/api/v1/webhooks/events | GET | read:webhooks |
/api/v1/webhooks/{id} | GET | read:webhooks |
/api/v1/webhooks/{id} | PATCH, DELETE | write:webhooks |
/api/v1/webhooks/{id}/rotate-secret | POST | write:webhooks |
/api/v1/webhooks/{id}/test | POST | write:webhooks |
/api/v1/webhooks/{id}/deliveries | GET | read:webhooks |
/api/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver | POST | write:webhooks |
Minting a key with custom settings
When you issue a key, you can configure:
- Name — A memorable label for the key (e.g., "HubSpot Sync", "Shopify Import").
- Scopes — Choose specific scopes (e.g.,
read:products,write:contacts) or*for full access. - Expiry — Optional. Set the key to expire after N days (e.g., 30, 90, 365). If left blank, the key never expires.
Every key is limited to 120 requests/minute, enforced by the platform (not configurable).
Keys are shown once after creation and then hashed at rest. Copy the full key immediately and store it in a secure location (environment variable or secrets manager).
Expiry behavior
- No expiry set — The key is valid indefinitely (until revoked).
- Expiry set — The key expires at the end of the configured date. After expiration, the key returns a 401 on every request.
- Revoked — You can revoke a key anytime from Settings → API keys. It returns a 401 immediately.
Rate limits
Each key is limited to 120 requests/minute, enforced by the platform (not configurable). The limit applies across all operations for that key.
- Within limit — Request succeeds (200, 207, etc.).
- Limit exceeded — Request fails with 429 Too Many Requests. Retry after the
Retry-Afterresponse header.
Example: rate limit response
HTTP/1.1 429 Too Many Requests
Retry-After: 35
Content-Type: application/json
{
"error": "Rate limit exceeded."
}429 Too Many Requests
Retry-After: 35
{"error":"Rate limit exceeded."}In this example, wait 35 seconds before retrying.
Error responses
401 Unauthorized
Returned when the API key is missing, invalid, malformed, expired, or revoked.
{
"error": "Invalid or missing API key."
}Causes:
- No
Authorizationheader sent. - Key is malformed (not
alk_live_...format). - Key is expired or revoked.
Action: Check your key, confirm it has not expired or been revoked, and ensure it matches your workspace.
403 Forbidden
Returned when the API key lacks the required scope for the operation.
{
"error": "API key missing required scope: write:products."
}Causes:
- Key has
read:productsbut endpoint requireswrite:products. - Key has
write:contactsbut endpoint requireswrite:deals.
Action: Verify the endpoint's required scope (see Per-endpoint scopes). If needed, issue a new key with the required scope.
429 Too Many Requests
Returned when the key's per-minute rate limit is exceeded.
{
"error": "Rate limit exceeded."
}Header: Retry-After: <seconds> indicates how long to wait before retrying.
Causes:
- The key has exceeded its rate limit (120 req/min, platform-enforced).
Action: Wait the number of seconds indicated by the Retry-After header, then retry. Consider implementing exponential backoff for resilience.
Best practices
- Use role-based scopes — Issue a key with only the scopes required for the integration. Avoid using
*unless necessary. - Set expiry dates — For temporary integrations or third-party services, configure a 30-, 90-, or 365-day expiry.
- Monitor rate limits — If your integration regularly hits 429, add backoff/retry logic or spread requests over time; the 120 req/min limit is platform-enforced and cannot be raised per key.
- Rotate keys regularly — Revoke old keys and issue new ones periodically (e.g., quarterly).
- Store securely — Never commit API keys to version control. Use environment variables or a secrets manager.
- Alert on 401/403 — If an integration starts returning 401 or 403, the key may have expired or been revoked. Set up monitoring to detect these errors.