API reference - Contacts

API reference · OpenAPI specification

Endpoint definitions below are generated from the API contract. Request and response blocks describe schemas, not example payloads. required lists mandatory fields; $ref refers to a linked model. Send JSON bodies with Content-Type: application/json unless the endpoint specifies binary content.

List or find accessible contacts

GET /v1/contacts

Requires contacts.read. Phone and case-insensitive email filters use exact AND matching against all saved channels, not only the primary channel. Multiple matches are returned; callers must not silently select one. Deleted and inaccessible contacts are excluded. The query filter searches normalized contact names, company, role and primary channels as a literal case-insensitive substring. Filters combine with AND and remain cursor-bound. Workspace contact access includes only workspace-visible contacts. Contacts restricted to shared or personal inboxes retain their audience and are excluded from Workspace contact sync. Personal-inbox connections follow the member's contact ownership and shares through their authorized personal inbox.

Parameters

NameLocationRequiredDescription and constraints
limitqueryNoType: integer default: 50 minimum: 1 maximum: 100
cursorqueryNoOpaque cursor from next_cursor. Reuse the same credentials, endpoint, filters, ordering, and limit. Results may change between requests; pagination does not freeze the dataset. Type: string
created_afterqueryNoInclusive lower time bound. Applies to start_time for calls and created_at for contacts/messages. Include a time zone. Type: string format: "date-time"
created_beforequeryNoExclusive upper time bound; must be later than created_after. Include a time zone. Type: string format: "date-time"
phonequeryNoType: string pattern: "^\+[1-9][0-9]{1,14}$"
emailqueryNoType: string
queryqueryNoLiteral substring of the contact search text; whitespace is trimmed. Wildcards are not interpreted. Type: string minLength: 3 maxLength: 100
orderqueryNooldest (the default) pages forward by ascending stable ID. newest returns the most recent records first and next_cursor continues with older records. The order is bound to the cursor. Type: string default: "oldest" enum: ["oldest","newest"]

Responses

200 — Contacts in the requested order (ascending stable ID by default).

application/json

allOf:
  - $ref: '#/components/schemas/Page'
  - properties:
      data:
        type: array
        items:
          $ref: '#/components/schemas/Contact'

Models: Page, Contact.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Create a contact

POST /v1/contacts

Requires contacts.read and contacts.write. Workspace connections create workspace contacts. Selected-inbox OAuth connections create contacts shared only with those inboxes. Single-inbox connections create contacts shared only with that inbox; personal-inbox contacts are owned by the subject. Clients cannot override the audience. Request ID deduplication lasts seven days. A nonnull valid E.164 phone is required; skip source records without a phone. Missing or null phone returns CONTACT_PHONE_REQUIRED.

Parameters

NameLocationRequiredDescription and constraints
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Request body (required)

application/json

$ref: '#/components/schemas/ContactCreate'

Models: ContactCreate.

Responses

201 — Contact record.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Contact'
  rate_limit:
    $ref: '#/components/schemas/RateLimit'

Models: Contact, RateLimit.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Create or update a contact by external identity

POST /v1/contacts/upsert

Requires contacts.read and contacts.write. The exact case-sensitive external_source and external_id pair is saved within this authorized connection. Use a stable source app/account identifier. A new pair creates an ordinary editable contact in the connection scope; a known pair updates that contact using the same field and audience rules as PATCH. Omitted display_name is derived automatically. A new pair requires a nonnull valid E.164 phone. For a known pair, phone may be omitted when the mapped contact already has a valid saved phone. Setting phone to null follows PATCH promotion rules; it never removes the contact's last usable phone. Missing phone on creation returns CONTACT_PHONE_REQUIRED. No phone/email matching or automatic linking to existing contacts occurs. The mapping persists beyond the seven-day request replay cache. Use a different Idempotency-Key for each source change event. A deleted, merged-away, or inaccessible mapped contact returns 404; source-managed contacts reject writes. A new connection has separate mappings. Source fields never grant additional access.

Parameters

NameLocationRequiredDescription and constraints
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Request body (required)

application/json

$ref: '#/components/schemas/ContactUpsert'

Models: ContactUpsert.

Responses

200 — Contact record.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Contact'
  rate_limit:
    $ref: '#/components/schemas/RateLimit'

Models: Contact, RateLimit.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Get one accessible contact

GET /v1/contacts/{id}

Requires contacts.read. Missing and inaccessible resources return 404.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"

Responses

200 — Contact record.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Contact'
  rate_limit:
    $ref: '#/components/schemas/RateLimit'

Models: Contact, RateLimit.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Update selected fields of an accessible contact

PATCH /v1/contacts/{id}

Requires contacts.read and contacts.write. Omitted fields are unchanged. Nullable fields accept null to clear the value, subject to the phone requirement. Phone/email changes retain other saved channels. The resulting contact must have a valid saved phone: omitted phone preserves it; phone=null promotes another saved phone to primary and retains the previous phone as a secondary number. If no other valid phone remains, the update fails with CONTACT_PHONE_REQUIRED without changing the contact. Email=null clears the primary email designation. display_name cannot be cleared explicitly. When omitted, name or primary-channel edits recompute it from the resulting first/last name, company, phone, or email, falling back to Unknown Contact. Unrelated edits preserve it. Source-managed read-only contacts reject changes. No resource_version or updated_at write is accepted.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Request body (required)

application/json

$ref: '#/components/schemas/ContactWrite'

Models: ContactWrite.

Responses

200 — Contact record.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Contact'
  rate_limit:
    $ref: '#/components/schemas/RateLimit'

Models: Contact, RateLimit.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

List contact notes

GET /v1/contacts/{id}/notes

Requires contacts.read. Missing and inaccessible parent resources return 404.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
limitqueryNoType: integer default: 50 minimum: 1 maximum: 100
cursorqueryNoOpaque cursor from next_cursor. Reuse the same credentials, endpoint, filters, ordering, and limit. Results may change between requests; pagination does not freeze the dataset. Type: string

Responses

200 — Page ordered by ascending ID.

application/json

type: object
required:
  - data
  - next_cursor
properties:
  data:
    type: array
    items:
      $ref: '#/components/schemas/Note'
  next_cursor:
    type:
      - string
      - 'null'

Models: Note.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Add a contact note

POST /v1/contacts/{id}/notes

Requires contacts.read and contacts.write. Idempotency lasts seven days. Source-managed read-only contacts reject writes.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Request body (required)

application/json

type: object
required:
  - body
properties:
  body:
    type: string
    minLength: 1
    maxLength: 10000
additionalProperties: false

Responses

201 — Authorized result.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Note'

Models: Note.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Update a contact note

PATCH /v1/contacts/{id}/notes/{note_id}

Requires contacts.read and contacts.write. Idempotency lasts seven days. Source-managed read-only contacts reject writes.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
note_idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Request body (required)

application/json

type: object
required:
  - body
properties:
  body:
    type: string
    minLength: 1
    maxLength: 10000
additionalProperties: false

Responses

200 — Authorized result.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Note'

Models: Note.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Soft-delete a contact note

DELETE /v1/contacts/{id}/notes/{note_id}

Requires contacts.read and contacts.write. Idempotency lasts seven days. Source-managed read-only contacts reject writes.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
note_idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Responses

200 — Authorized result.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/Note'

Models: Note.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

List existing workspace contact property definitions

GET /v1/contact-properties

Requires contacts.read. Missing and inaccessible parent resources return 404.

Parameters

NameLocationRequiredDescription and constraints
limitqueryNoType: integer default: 50 minimum: 1 maximum: 100
cursorqueryNoOpaque cursor from next_cursor. Reuse the same credentials, endpoint, filters, ordering, and limit. Results may change between requests; pagination does not freeze the dataset. Type: string

Responses

200 — Page ordered by ascending ID.

application/json

type: object
required:
  - data
  - next_cursor
properties:
  data:
    type: array
    items:
      $ref: '#/components/schemas/ContactPropertyDefinition'
  next_cursor:
    type:
      - string
      - 'null'

Models: ContactPropertyDefinition.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

List contact property values

GET /v1/contacts/{id}/properties

Requires contacts.read. Missing and inaccessible parent resources return 404.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
limitqueryNoType: integer default: 50 minimum: 1 maximum: 100
cursorqueryNoOpaque cursor from next_cursor. Reuse the same credentials, endpoint, filters, ordering, and limit. Results may change between requests; pagination does not freeze the dataset. Type: string

Responses

200 — Page ordered by ascending ID.

application/json

type: object
required:
  - data
  - next_cursor
properties:
  data:
    type: array
    items:
      $ref: '#/components/schemas/ContactPropertyValue'
  next_cursor:
    type:
      - string
      - 'null'

Models: ContactPropertyValue.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.

Set a typed value on an existing contact property

PATCH /v1/contacts/{id}/properties/{property_id}

Requires contacts.read and contacts.write. Idempotency lasts seven days. Source-managed read-only contacts reject writes.

Parameters

NameLocationRequiredDescription and constraints
idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
property_idpathYesStable existing Waveline record ID. Keep it as a string; it may exceed JavaScript's safe integer range. Type: string maxLength: 19 pattern: "^[1-9][0-9]*$"
Idempotency-KeyheaderYesUse a stable request identifier. Contact writes replay the saved response for seven days, subject to current resource access. Subscription creation retains its identity for seven days but returns current metadata and signing secret; a disabled/deleted subscription rejects replay. Reusing those keys with a different operation, path or exact JSON body returns 409. Subscription status and delete operations are repeatable state changes. Type: string minLength: 8 maxLength: 128 pattern: "^[!-~]+$"

Request body (required)

application/json

type: object
required:
  - value
properties:
  value:
    description: >-
      Must match the existing definition type. Null clears. Dates use YYYY-MM-DD, phone
      uses E.164, multi-select uses defined choices.
additionalProperties: false

Responses

200 — Authorized result.

application/json

type: object
required:
  - data
properties:
  data:
    $ref: '#/components/schemas/ContactPropertyValue'

Models: ContactPropertyValue.

Errors — 400 invalid input, 401 expired/revoked/missing key, 403 scope or access denied, 404 missing/inaccessible, 409 request/state conflict, 413 oversized request or response, 415 wrong content type, 429 rate limited, or 503 unavailable. 429 includes Retry-After. All responses include X-Request-Id.

Error format, status codes, and retry guidance.