agentlyleads docs
Getting started

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:

ScopeAccess
read:productsRead (list) your product catalog
write:productsCreate and update products
read:contactsRead (list) your contacts
write:contactsCreate and update contacts
read:companiesRead (list) your companies
write:companiesCreate and update companies
read:dealsRead (list) your deals
write:dealsCreate and update deals
read:notesRead (list) your notes
write:notesCreate and update notes
read:emailsRead (list) emails, drafts and replies, the workspace's sending identities, and shared inbox conversations, comments and counts
write:emailsCompose, edit, reply to and delete email drafts (never sends), and triage shared inbox conversations: assign, close, tag, archive, snooze, spam, trash and comment
send:emailsRelease a draft: transmits real email
read:communicationsRead a contact's logged calls, meetings and messages
write:communicationsLog calls, meetings, LinkedIn messages and off-platform emails
read:tasksRead (list) your tasks and calendar appointments
write:tasksCreate, update, and delete tasks and calendar appointments
read:calendarRead the merged calendar (tasks, deal closes, campaign sends, follow-ups, birthdays)
write:calendarPut meetings on the CRM calendar and refresh a user's connected calendars
read:bookingsList and read bookings, meeting types, hours, hosts and open slots
write:bookingsBook, cancel and reschedule meetings; create, change, pause and archive meeting types; change hours and host timezones
read:offeringsRead your offerings' campaign summaries and communication timeline
write:offeringsCreate and update offerings
read:leadsRead (list) your leads
write:leadsCapture and update leads
read:contractsRead your contracts and their renewal dates
write:contractsCreate contracts and change their status or term
read:casesRead your support cases and their resolution clocks
write:casesOpen cases and change their status, severity or assignee
read:quotesRead quotes, their line items and totals
write:quotesCreate quotes and change their status
read:campaignsRead campaigns and their delivery analytics
write:campaignsCreate, edit, delete, launch and cancel campaigns (launching queues drafts; it never sends)
read:sequencesRead sequences, their steps and enrollment stats
write:sequencesCreate sequences and enroll contacts (a SEND-mode sequence also needs send:emails)
read:chatList website chat conversations and read their transcripts
write:chatReply to visitors, take over and hand back chats, and close, assign, tag or mark them as spam
read:filesList the files on a record and download them
write:filesAttach files to records and delete them
read:teamList the workspace's users (read-only)
read:tagsList tags with usage counts
write:tagsCreate, rename and delete tags, and tag or untag records in bulk
read:pipelinesList pipelines and their stages
write:pipelinesCreate, rename and delete pipelines, and add, update, reorder and delete stages
read:custom-fieldsList custom field definitions
write:custom-fieldsCreate, update and delete custom field definitions
read:workflowsList workflows and read their recent runs
write:workflowsCreate, change, pause and delete workflows
read:formsList lead-capture forms and their submissions
read:suppressionsList suppressed email addresses
write:suppressionsSuppress an address, or lift an opt-out
read:reportsRead the Performance report and shared saved views
read:webhooksList webhook endpoints, their event types and delivery history
write:webhooksAdd, change, delete and test webhook endpoints, rotate secrets and resend events
*Full access to all resources and operations

Scope hierarchy

  • write: scopes do NOT grant read: — a key with write:products cannot 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

EndpointMethodRequired Scope
/api/v1/productsGETread:products
/api/v1/productsPOSTwrite:products
/api/v1/contactsPOSTwrite:contacts
/api/v1/companiesPOSTwrite:companies
/api/v1/dealsPOSTwrite:deals
/api/v1/notesPOSTwrite:notes
/api/v1/emailsGETread:emails
/api/v1/emailsPOSTwrite:emails
/api/v1/emails/identitiesGETread:emails
/api/v1/emails/{id}GETread:emails
/api/v1/emails/{id}PATCH, DELETEwrite:emails
/api/v1/emails/{id}/replyPOSTwrite:emails
/api/v1/emails/{id}/sendPOSTsend:emails
/api/v1/communicationsGETread:communications
/api/v1/communicationsPOSTwrite:communications
/api/v1/tasksPOSTwrite:tasks
/api/v1/tasks/{id}DELETEwrite:tasks
/api/v1/calendarGETread:calendar
/api/v1/products/{id}/communicationGETread:offerings
/api/v1/leadsGETread:leads
/api/v1/contractsGETread:contracts
/api/v1/contracts/{id}GETread:contracts
/api/v1/casesGETread:cases
/api/v1/cases/{id}GETread:cases
/api/v1/filesGETread:files
/api/v1/filesPOSTwrite:files
/api/v1/files/upload-urlPOSTwrite:files
/api/v1/files/{id}GETread:files
/api/v1/files/{id}DELETEwrite:files
/api/v1/contacts/duplicatesGETread:contacts
/api/v1/contacts/{id}/mergePOSTwrite:contacts
/api/v1/contacts/{id}/briefPOSTwrite:contacts
/api/v1/leads/{id}/convertPOSTwrite:leads
/api/v1/products/{id}/prospectsGETread:offerings + read:contacts
/api/v1/products/{id}/matchPOSTwrite:offerings + read:contacts
/api/v1/outreach-matches/{id}GETread:offerings + read:contacts
/api/v1/outreach-matches/{id}/candidates/{candidateId}PATCHwrite:offerings
/api/v1/outreach-matches/{id}/draftsPOSTwrite:offerings + write:emails
/api/v1/contractsPOSTwrite:contracts
/api/v1/contracts/{id}/statusPOSTwrite:contracts
/api/v1/casesPOSTwrite:cases (+ read:emails with emailId)
/api/v1/cases/{id}/statusPOSTwrite:cases
/api/v1/quotesGETread:quotes
/api/v1/quotesPOSTwrite:quotes
/api/v1/quotes/{id}GETread:quotes
/api/v1/quotes/{id}/statusPOSTwrite:quotes
/api/v1/campaignsGETread:campaigns
/api/v1/campaignsPOSTwrite:campaigns
/api/v1/campaigns/{id}GETread:campaigns
/api/v1/campaigns/{id}PATCH, DELETEwrite:campaigns
/api/v1/campaigns/{id}/launchPOSTwrite:campaigns
/api/v1/campaigns/{id}/cancelPOSTwrite:campaigns
/api/v1/sequencesGETread:sequences
/api/v1/sequencesPOSTwrite:sequences (+ send:emails for SEND mode)
/api/v1/sequences/{id}GETread:sequences
/api/v1/sequences/{id}/enrollmentsPOSTwrite:sequences (+ send:emails for SEND mode)
/api/v1/inbox/threadsGETread:emails
/api/v1/inbox/threads/{threadKey}GETread:emails
/api/v1/inbox/threads/{threadKey}/commentsGETread:emails
/api/v1/inbox/threads/{threadKey}/commentsPOSTwrite:emails
/api/v1/inbox/threads/assign, /status, /spam, /trash, /archive, /snooze, /tagsPOSTwrite:emails
/api/v1/inbox/summaryGETread:emails
/api/v1/inbox/assigneesGETread:emails
/api/v1/chatsGETread:chat
/api/v1/chats/{id}GETread:chat
/api/v1/chats/{id}/replyPOSTwrite:chat
/api/v1/chats/{id}/take-overPOSTwrite:chat
/api/v1/chats/{id}/hand-backPOSTwrite:chat
/api/v1/chats/{id}/closePOSTwrite:chat
/api/v1/chats/{id}/reopenPOSTwrite:chat
/api/v1/chats/{id}/assignPOSTwrite:chat
/api/v1/chats/{id}/tagsPOST, DELETEwrite:chat
/api/v1/chats/{id}/spamPOSTwrite:chat
/api/v1/calendar/meetingsPOSTwrite:calendar
/api/v1/calendar/refreshPOSTwrite:calendar
/api/v1/bookingsGETread:bookings
/api/v1/bookingsPOSTwrite:bookings
/api/v1/bookings/{id}GETread:bookings
/api/v1/bookings/{id}/cancelPOSTwrite:bookings
/api/v1/bookings/{id}/reschedulePOSTwrite:bookings
/api/v1/bookings/{id}/slotsGETread:bookings
/api/v1/booking-typesGETread:bookings
/api/v1/booking-typesPOSTwrite:bookings
/api/v1/booking-types/{id}GETread:bookings
/api/v1/booking-types/{id}PATCH, DELETEwrite:bookings
/api/v1/booking-types/{id}/slotsGETread:bookings
/api/v1/booking-types/{id}/hoursGETread:bookings
/api/v1/booking-types/{id}/hoursPUTwrite:bookings
/api/v1/booking-types/{id}/date-overrides/{date}PUT, DELETEwrite:bookings
/api/v1/booking-hostsGETread:bookings
/api/v1/booking-hosts/{id}GETread:bookings
/api/v1/booking-hosts/{id}PATCHwrite:bookings
/api/v1/teamGETread:team
/api/v1/tagsGETread:tags
/api/v1/tagsPOSTwrite:tags
/api/v1/tags/{id}PATCH, DELETEwrite:tags
/api/v1/tags/assignPOSTwrite:tags
/api/v1/tags/unassignPOSTwrite:tags
/api/v1/pipelinesGETread:pipelines
/api/v1/pipelinesPOSTwrite:pipelines
/api/v1/pipelines/{id}GETread:pipelines
/api/v1/pipelines/{id}PATCH, DELETEwrite:pipelines
/api/v1/pipelines/{id}/stagesPOSTwrite:pipelines
/api/v1/pipelines/{id}/stages/reorderPOSTwrite:pipelines
/api/v1/stages/{id}PATCH, DELETEwrite:pipelines
/api/v1/custom-fieldsGETread:custom-fields
/api/v1/custom-fieldsPOSTwrite:custom-fields
/api/v1/custom-fields/{id}GETread:custom-fields
/api/v1/custom-fields/{id}PATCH, DELETEwrite:custom-fields
/api/v1/workflowsGETread:workflows
/api/v1/workflowsPOSTwrite:workflows
/api/v1/workflows/{id}GETread:workflows
/api/v1/workflows/{id}PATCH, DELETEwrite:workflows
/api/v1/workflows/{id}/runsGETread:workflows
/api/v1/formsGETread:forms
/api/v1/forms/{id}/submissionsGETread:forms
/api/v1/suppressionsGETread:suppressions
/api/v1/suppressionsPOSTwrite:suppressions
/api/v1/suppressions/{id}DELETEwrite:suppressions
/api/v1/reportsGETread:reports
/api/v1/saved-viewsGETread:reports
/api/v1/webhooksGETread:webhooks
/api/v1/webhooksPOSTwrite:webhooks
/api/v1/webhooks/eventsGETread:webhooks
/api/v1/webhooks/{id}GETread:webhooks
/api/v1/webhooks/{id}PATCH, DELETEwrite:webhooks
/api/v1/webhooks/{id}/rotate-secretPOSTwrite:webhooks
/api/v1/webhooks/{id}/testPOSTwrite:webhooks
/api/v1/webhooks/{id}/deliveriesGETread:webhooks
/api/v1/webhooks/{id}/deliveries/{deliveryId}/redeliverPOSTwrite:webhooks

Minting a key with custom settings

When you issue a key, you can configure:

  1. Name — A memorable label for the key (e.g., "HubSpot Sync", "Shopify Import").
  2. Scopes — Choose specific scopes (e.g., read:products, write:contacts) or * for full access.
  3. 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-After response 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 Authorization header 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:products but endpoint requires write:products.
  • Key has write:contacts but endpoint requires write: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

  1. Use role-based scopes — Issue a key with only the scopes required for the integration. Avoid using * unless necessary.
  2. Set expiry dates — For temporary integrations or third-party services, configure a 30-, 90-, or 365-day expiry.
  3. 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.
  4. Rotate keys regularly — Revoke old keys and issue new ones periodically (e.g., quarterly).
  5. Store securely — Never commit API keys to version control. Use environment variables or a secrets manager.
  6. 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.

On this page