OdyDocs

Contacts

Create, retrieve, update, search and delete the people your business talks to.

A contact is a person or company your business talks to. Ody creates contacts automatically the first time an unknown number texts or calls in. You can also create them yourself, for example to sync a CRM. Every conversation thread is attached to the contact whose phone number it involves.

#The contact object

  • id uuid — Unique identifier.
  • firstName string | null — Given name.
  • lastName string | null — Family name.
  • company string | null — Company or organisation.
  • phones array of {value, label?} — Phone numbers in E.164. The first one is the primary number.
  • emails array of {value, label?} — Email addresses.
  • notes array of strings — Free-text notes, oldest first.
  • properties object — Your own string key/value fields (for example {"crmId": "A-1042"}).
  • tags array of strings — Labels used for filtering in the app.
  • source string | null — How the contact was created: manual (the app or this API), inbound (auto-created from a text or call), or the integration it was synced from (for example hubspot).
  • createdAt timestamp — ISO 8601.

List endpoints return a lighter contact summary: id, firstName, lastName, company, phone (the primary number) and createdAt.

The contact object
{
  "id": "8b1d6f3e-2c4a-4e1b-9f0d-7a5c3e2b1a90",
  "firstName": "Ada",
  "lastName": "Lovelace",
  "company": "Analytical Engines",
  "phones": [{ "value": "+15125550123", "label": "mobile" }],
  "emails": [{ "value": "[email protected]" }],
  "notes": ["Prefers texts after 5pm"],
  "properties": { "crmId": "A-1042" },
  "tags": ["vip"],
  "source": "manual",
  "createdAt": "2026-10-14T18:02:11.000Z"
}

#List contacts

GET/v1/api/contacts

Returns the workspace's contacts, newest first. Pass q to run a full-text search over names, company, phones and emails. Results are cursor-paginated.

Scope: contacts:read

Query parameters

  • q string — Full-text search query.
  • limit integer — 1–200, default 50.
  • cursor string — nextCursor from the previous page.

Returns { contacts: ContactSummary[], nextCursor: string | null }.

curl "https://api.ody.co/v1/api/contacts?q=ada&limit=20" \
  -H "Authorization: Bearer $ODY_API_KEY"
Response
{
  "contacts": [
    {
      "id": "8b1d6f3e-2c4a-4e1b-9f0d-7a5c3e2b1a90",
      "firstName": "Ada",
      "lastName": "Lovelace",
      "company": "Analytical Engines",
      "phone": "+15125550123",
      "createdAt": "2026-10-14T18:02:11.000Z"
    }
  ],
  "nextCursor": null
}

#Create a contact

POST/v1/api/contacts

Creates a contact. You must send at least one identity field: firstName, lastName, company, phone/phones or email/emails.

If the phone matches a contact Ody auto-created from an inbound text or call (one that has no name yet), that contact is adopted and updated instead of duplicated. Its existing threads keep their history.

Scope: contacts:write

Body

  • firstName string
  • lastName string
  • company string
  • phone string — Convenience field, merged into phones. E.164.
  • email string — Convenience field, merged into emails.
  • phones array — Strings, or { "value", "label" } objects.
  • emails array — Strings, or { "value", "label" } objects.
  • notes array of strings
  • properties object — String values only.
  • tags array of strings

Returns 201 with { contact }.

curl https://api.ody.co/v1/api/contacts \
  -H "Authorization: Bearer $ODY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Ada",
    "lastName": "Lovelace",
    "phone": "+15125550123",
    "properties": { "crmId": "A-1042" },
    "tags": ["vip"]
  }'
Response
{
  "contact": {
    "id": "8b1d6f3e-2c4a-4e1b-9f0d-7a5c3e2b1a90",
    "firstName": "Ada",
    "lastName": "Lovelace",
    "company": null,
    "phones": [{ "value": "+15125550123" }],
    "emails": [],
    "notes": [],
    "properties": { "crmId": "A-1042" },
    "tags": ["vip"],
    "source": "manual",
    "createdAt": "2026-10-14T18:02:11.000Z"
  }
}

#Retrieve a contact

GET/v1/api/contacts/:id

Returns the full contact.

Scope: contacts:read

Returns { contact }, or 404 not_found.

curl https://api.ody.co/v1/api/contacts/8b1d6f3e-2c4a-4e1b-9f0d-7a5c3e2b1a90 \
  -H "Authorization: Bearer $ODY_API_KEY"

#Update a contact

PATCH/v1/api/contacts/:id

Changes only the fields you send. Array and object fields (phones, emails, notes, properties, tags) are replaced wholesale. To add a tag, read the contact, append to the array, then send the whole array back.

Scope: contacts:write

Body: any field from Create a contact. Send null to clear firstName, lastName or company.

Returns { contact }.

curl -X PATCH https://api.ody.co/v1/api/contacts/8b1d6f3e-2c4a-4e1b-9f0d-7a5c3e2b1a90 \
  -H "Authorization: Bearer $ODY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"company":"Analytical Engines","tags":["vip","renewal-q4"]}'

#Delete a contact

DELETE/v1/api/contacts/:id

Permanently deletes the contact. Conversation threads are not deleted: they stay in the inbox under the raw phone number, and a new text from that number creates a fresh contact.

Scope: contacts:write

Returns { "deleted": true }.

curl -X DELETE https://api.ody.co/v1/api/contacts/8b1d6f3e-2c4a-4e1b-9f0d-7a5c3e2b1a90 \
  -H "Authorization: Bearer $ODY_API_KEY"
Last updated Wed Oct 14 2026 00:00:00 GMT+0000 (Coordinated Universal Time)Something wrong on this page? Tell us