Skip to content

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.

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:

Terminal window
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:

Terminal window
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:

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

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.

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_name

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:

Terminal window
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}/

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.