Skip to content

Authentication

Every request is authenticated with an API key sent as a bearer token:

Terminal window
curl https://api.ahoy.ai/rest/v1/objects/ \
-H "Authorization: Bearer $AHOY_API_KEY"

A missing or unrecognised token returns unauthenticated with a WWW-Authenticate: Bearer header.

Keys are created in Settings → API & Service Accounts. When you create one you choose which object types it may read and write.

This is the part most worth understanding, because it is stricter than most APIs.

A key is scoped three ways, and all three apply:

  1. One organisation. The org is baked into the key and resolved server-side.
  2. The object types its grants name. GET /rest/v1/objects/ returns exactly the types this key can see, each with the writable_operations it allows.
  3. Its creator’s own permissions. A key can never see more than the person who minted it.

That third rule is the surprising one.

By default a key has user reach: it is capped at what its creator can see. Because Ahoy records can be private to a user, this means an admin’s key does not automatically read other people’s private emails, meetings, notes, or calls — even though that admin is an administrator.

For integrations that genuinely need to see everything, an org admin can mint a key with org reach. That is a deliberate, separate action, and reach is stamped at creation and immutable afterwards — to change it, mint a new key.

GET /rest/v1/self/ reports which kind you hold:

{ "data": { "org_id": 42, "principal_id": "prn_…", "reach": "user" } }

Read access is decided purely by grants. Write access has a second gate: some object types are read-only or link-only for every credential, regardless of grants, because they are synced from elsewhere or are Ahoy’s own signals.

Object typesAcceptsWhy
ahoy_meetingassociate onlySynced from calendar, but may be linked to records
ahoy_meeting_notes, ahoy_booking, ahoy_email_thread, ahoy_filenothingSynced from the source system
ahoy_web_visit, ahoy_web_visitornothingIngestion facts, not integration records
ahoy_risknothingGenerated by Ahoy, not written by integrations
ahoy_linkedin_conversation, ahoy_call, ahoy_sms_conversationfullLogged interactions are deliberately writable
Everything elsefullContacts, companies, deals, notes, tasks, custom types

A write outside a type’s allowed set returns permission_denied with reason: "type_read_only". This is checked before your grants, so the answer is identical for every credential — don’t treat it as a permissions problem.

Rather than hard-coding this table, read writable_operations from GET /rest/v1/objects/.

  • Send keys only over HTTPS, only in the Authorization header — never in a query string, where they land in logs.
  • Ahoy never logs your raw token. Requests are logged against a short fingerprint of the key instead.
  • Rotate by minting the new key, deploying it, then revoking the old one.
  • Revocation takes effect immediately.