Objects and properties
Ahoy has no fixed set of resources. Instead of /contacts and /companies
endpoints, there is one set of operations that works against any object type
your org has — built-in or custom:
/rest/v1/objects/{object_type}/records/Understanding that shape is most of understanding this API.
The three layers
Section titled “The three layers”Object types are the kinds of thing your org tracks — ahoy_contact,
ahoy_company, ahoy_deal, plus any custom types you’ve created. Ask for the
ones your credential can see:
curl https://api.ahoy.ai/rest/v1/objects/ \ -H "Authorization: Bearer $AHOY_API_KEY"Properties are the fields on an object type. They vary per org, so read them rather than assuming:
curl https://api.ahoy.ai/rest/v1/objects/ahoy_contact/ \ -H "Authorization: Bearer $AHOY_API_KEY"Field types describe what a property can hold and what you can do with it — its value shape, which filter operators apply, which aggregations are available, whether it can be sorted:
curl https://api.ahoy.ai/rest/v1/field_types/ \ -H "Authorization: Bearer $AHOY_API_KEY"Discover, don’t hard-code
Section titled “Discover, don’t hard-code”Because the schema is per-org, a client that hard-codes property names works
against one org and breaks against the next. Read GET /rest/v1/objects/ at
startup and cache it for the process lifetime.
The same response tells you what you’re allowed to do. Each object type carries
writable_operations:
{ "name": "ahoy_meeting", "writable_operations": ["associate"]}That example is a synced type: you may link a meeting to a contact, but you may not create or edit one. Reading this field is more reliable than memorising which types are read-only — see Authentication for why some are.
Records
Section titled “Records”A record is one instance of an object type. Properties arrive under a
properties object, keyed by property name:
{ "id": "rec_01J8Z2K9QW3X4Y5Z6A7B8C9D", "properties": { "ahoy_first_name": "Ada", "ahoy_last_name": "Lovelace", "ahoy_email": ["ada@example.com"] }}Ask for only what you need with ?properties=, which matters on wide types:
GET /rest/v1/objects/ahoy_contact/records/?properties=ahoy_email,ahoy_first_name,ahoy_last_nameAssociations
Section titled “Associations”Records link to each other through association types, which are directional
and named for the pair they join — ahoy_contact_to_company, for example.
List what a type supports:
curl https://api.ahoy.ai/rest/v1/objects/ahoy_contact/associations/ \ -H "Authorization: Bearer $AHOY_API_KEY"One subtlety worth knowing: some association types are defined against a kind
rather than a concrete type — ahoy_contact_to_company is really
person → ahoy_company. The API expands those into one entry per concrete
(source, target) pair, so the same name can appear more than once in the
list. Match on the pair, not the name alone.
Linking and unlinking are single calls:
PUT /rest/v1/objects/{object_type}/records/{id}/associations/{association_type}/{target_id}/DELETE /rest/v1/objects/{object_type}/records/{id}/associations/{association_type}/{target_id}/Two types you will never see
Section titled “Two types you will never see”ahoy_user and ahoy_org are granted read access implicitly, so that
owner-and-org-visibility association targets resolve. They are deliberately
not exposed as resources: not listed, not queryable, not readable by id.
Only types your grants name explicitly appear.