Object types
Ahoy’s schema is per-organisation, so the authoritative list of what your credential can reach is always:
curl https://api.ahoy.ai/rest/v1/objects/ \ -H "Authorization: Bearer $AHOY_API_KEY"This page is the vocabulary you can expect to meet there. Treat it as a map, not a contract: your org may have custom types, and a type you can see in the app may not be granted to a given key.
Core records
Section titled “Core records”The four you will spend nearly all your time with. All are fully writable.
| Type | Label | What it is |
|---|---|---|
ahoy_contact | Contact | An individual person. Created from inbound email, manual entry, CSV import or enrichment |
ahoy_company | Company | An organisation, identified by domain. The root that groups contacts, deals and risks |
ahoy_deal | Deal | A sales opportunity moving through pipeline stages |
ahoy_note | Note | A note attached to other records — also Ahoy’s task object, see below |
What the core records look like
Section titled “What the core records look like”Below is the default shape of each core record. Your org can add properties (and
rename labels), so treat this as the starting vocabulary, not the full list —
GET /rest/v1/objects/ahoy_contact/ returns the authoritative properties for
a type, including anything your org has added.
Contact — ahoy_contact
Section titled “Contact — ahoy_contact”A person. ahoy_email and ahoy_phone_number hold multiple values, so both
are arrays even when you only have one.
{ "properties": { "ahoy_first_name": "Ada", "ahoy_last_name": "Lovelace", "ahoy_email": ["ada@example.com"], "ahoy_job_title": "VP Engineering", "ahoy_linkedin_url": "https://www.linkedin.com/in/adalovelace", "ahoy_phone_number": [ { "country_code": "GB", "national_number": "2079460123" } ] }}Also available: ahoy_headline, ahoy_summary, ahoy_location,
ahoy_timezone, ahoy_job_start_date, ahoy_lead_score,
ahoy_linkedin_id, ahoy_first_web_source, ahoy_last_web_source.
Read-only: ahoy_created_at, ahoy_updated_at, ahoy_last_activity_at,
ahoy_potential_deal_total, ahoy_weighted_deal_total.
Company — ahoy_company
Section titled “Company — ahoy_company”An organisation, identified by domain. Note that the numeric properties are sent as strings.
{ "properties": { "ahoy_name": "Acme Corp", "ahoy_domain": "acme.com", "ahoy_industry": "Software", "ahoy_city": "Dublin", "ahoy_country": "Ireland", "ahoy_employee_count": "250", "ahoy_annual_revenue": "4200000" }}Also available: ahoy_website, ahoy_description, ahoy_linkedin_url,
ahoy_company_type, ahoy_year_founded, ahoy_headcount_range,
ahoy_region, ahoy_country_code, ahoy_postal_code, ahoy_address.
Read-only: ahoy_created_at, ahoy_updated_at, ahoy_stripe_mrr_total,
ahoy_stripe_subscription_count.
Deal — ahoy_deal
Section titled “Deal — ahoy_deal”A sales opportunity. Deals carry few properties by design — the interesting state lives in the stage association, not in a field.
{ "properties": { "ahoy_name": "Acme Corp — platform rollout", "ahoy_amount": { "amount": "48000", "unit": "USD" }, "ahoy_close_date": "2026-03-31" }}Read-only: ahoy_created_at, ahoy_updated_at, ahoy_last_activity_at.
Value shapes that catch people out
Section titled “Value shapes that catch people out”Sending the right type matters more here than in most CRM APIs, because values are validated against the property’s field type rather than coerced.
| Shape | Example properties | Send |
|---|---|---|
| Multi-valued | ahoy_email, ahoy_phone_number | An array, even for a single value |
| Number | ahoy_employee_count, ahoy_annual_revenue | A numeric string — "250", never 250 |
| Currency | ahoy_amount | { "amount": "48000", "unit": "USD" } |
| Date | ahoy_close_date | "YYYY-MM-DD" |
| Datetime | ahoy_created_at | ISO 8601 with an offset — "2026-03-31T14:30:00Z" |
| Phone | ahoy_phone_number | { "country_code": "GB", "national_number": "2079460123" } |
| Select | ahoy_lead_score | The option’s exact value, not its display label |
GET /rest/v1/field_types/ is the authority on every shape, including which
operators and aggregations each one supports.
Joining them up
Section titled “Joining them up”The records above are independent until you associate them. The three you will reach for most:
| Association | Meaning |
|---|---|
ahoy_contact_to_company | The contact works at the company |
ahoy_deal_to_company | The deal belongs to the company |
ahoy_deal_to_contact | The people on the deal |
A deal’s position in its pipeline is an association too — you move a deal by
pointing ahoy_deal_to_deal_pipeline_stage at a different stage record, not by
writing a “stage” property. The same is true of a contact’s lifecycle
(ahoy_contact_to_lifecycle_stage).
curl -X PUT \ https://api.ahoy.ai/rest/v1/objects/ahoy_deal/records/$DEAL_ID/associations/ahoy_deal_to_deal_pipeline_stage/$STAGE_ID/ \ -H "Authorization: Bearer $AHOY_API_KEY"Pipelines and stages
Section titled “Pipelines and stages”Pipelines are records too, which means you read them over the same endpoints — there is no special “metadata” API. To move a deal, you associate it with the stage record you want.
| Type | Label | What it is |
|---|---|---|
ahoy_deal_pipeline | Deal Pipeline | An ordered sequence of deal stages |
ahoy_deal_pipeline_stage | Deal Pipeline Stage | One stage within a deal pipeline |
ahoy_note_pipeline | Task Statuses | The workflow pipeline for notes |
ahoy_note_pipeline_stage | Task Status | One status — To Do, In Progress, Complete |
ahoy_contact_lifecycle_stage | Contact Lifecycle Stage | Where a contact sits from awareness through to customer |
ahoy_stage_timer | Stage Timer | How long a record spent in a stage. Written automatically |
Activity, synced from elsewhere
Section titled “Activity, synced from elsewhere”These originate in a connected system, so Ahoy owns their content. Most accept
no writes at all; ahoy_meeting accepts associate only, so you can link a
meeting to a contact without editing the meeting itself.
| Type | Label | Accepts |
|---|---|---|
ahoy_meeting | Meeting | associate only |
ahoy_meeting_notes | Meeting Notes | nothing |
ahoy_email_thread | Email Thread | nothing |
ahoy_booking | Booking | nothing |
ahoy_booking_type | Booking Type | nothing |
ahoy_file | File | nothing |
Conversations you can log
Section titled “Conversations you can log”Unlike synced activity, these are deliberately writable — they exist so an integration can record an interaction that happened somewhere Ahoy cannot see.
| Type | Label |
|---|---|
ahoy_call | Call |
ahoy_sms_conversation | SMS Conversation |
ahoy_linkedin_conversation | LinkedIn Conversation |
Signals and ingestion facts
Section titled “Signals and ingestion facts”Generated by Ahoy rather than written by integrations, and read-only on this surface even when your grants would otherwise allow a write.
| Type | Label |
|---|---|
ahoy_risk | Risk |
ahoy_web_visit | Web Visit |
ahoy_web_visitor | Web Visitor |
Everything else
Section titled “Everything else”Your organisation also contains platform records — schema definitions, access control, automation, and operational history. Whether any of them are reachable depends entirely on your credential’s grants, and most integrations neither need nor receive them.
GET /rest/v1/objects/ is the answer, always: it returns exactly the types your
key can see, with the operations each one allows.
Two you will never see
Section titled “Two you will never see”ahoy_user and ahoy_org are granted read access implicitly so that
owner-visibility and org-visibility associations resolve — but they are
deliberately not exposed as resources. They are not listed, not queryable,
and not readable by id.
Custom types
Section titled “Custom types”Anything your org has defined itself appears alongside the built-ins with the
same operations and the same URL shape. That is the point of the design: there
is no separate endpoint for custom objects, so an integration written against
ahoy_contact works unchanged against my_custom_type.