Distru Contact API

The Contact API from Distru — 2 operation(s) for contact.

Operations 4

GET /public/v1/contacts Get contacts #
POST /public/v1/contacts Upsert a contact #
DELETE /public/v1/contacts/{id} Delete a contact #
GET /public/v1/contacts/{id} Get a contact #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/distru:distru-contact-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

distru-contact-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  license:
    name: Proprietary
    url: https://www.distru.com/legal/terms-of-service
  title: Distru Contact API
  version: '1.0'
servers:
- url: https://app.distru.com
security:
- Bearer: []
tags:
- name: Contact
paths:
  /public/v1/contacts:
    get:
      description: 'List the contacts in your CRM, returned oldest-first by creation date. The response is a page envelope: `data` holds the contacts and `next_page` is a ready-to-call URL for the following page (null on the last page).


        This endpoint is eventually consistent — a contact you just created or edited may take up to 1 second to appear or reflect its new values here.


        By default only non-deleted contacts are returned; use the `deleted` filter to include or isolate soft-deleted ones. Results are further scoped to your company and to the contacts the authenticated user may see under their team restrictions, so two users at the same company can get different lists.


        Required permission: `contacts_permissions_view`.'
      operationId: DistruPublic.V1.ContactController.index
      parameters:
      - description: Restrict the result to specific contacts by ID (the same ID returned as each contact's `id`). Repeat the bracketed key once per ID. Unknown IDs simply match nothing; an empty list is treated as no filter. At most 200 IDs may be given.
        in: query
        name: ids
        required: false
        style: form
        explode: false
        schema:
          type: array
          items:
            type: string
      - description: Restrict to contacts employed by specific companies by company ID (the same ID returned as each contact's `company.id`). Repeat the bracketed key once per ID; matches ANY. Unknown IDs match nothing; an empty list is no filter. At most 200 IDs.
        in: query
        name: company_ids
        required: false
        style: form
        explode: false
        schema:
          type: array
          items:
            type: string
      - description: Restrict to contacts owned by any of these Distru users (each contact's `owner.id`). Repeat the bracketed key once per ID; matches ANY. Unknown IDs match nothing; an empty list is no filter. At most 200 IDs.
        in: query
        name: owner_ids
        required: false
        style: form
        explode: false
        schema:
          type: array
          items:
            type: string
      - description: 'Filter to contacts by their creation datetime. The value is a comma-separated `start,end` pair of ISO8601 datetimes and either bound may be omitted: `2022-07-10T00:00:00Z,` returns contacts created on or after that instant, `,2022-07-10T00:00:00Z` returns those created on or before it, and `2022-07-10T00:00:00Z,2022-07-11T00:00:00Z` returns those created between the two (inclusive).'
        in: query
        name: inserted_datetime
        required: false
        example: 2022-07-10T00:00:00Z,
        schema:
          type: string
      - description: Whether soft-deleted contacts are included. `no` (the default) returns only non-deleted contacts, `only` returns only soft-deleted ones, and `include` returns both. Soft-deleted contacts carry a non-null `deleted_at` in the response.
        in: query
        name: deleted
        required: false
        schema:
          type: string
          enum:
          - 'no'
          - include
          - only
          default: 'no'
      - description: Page selector. Page size is fixed by the server; paginate by following the `next_page` URL in each response rather than building page selectors yourself — it is null on the last page. `next_page` uses `page[after]=<cursor>`, an opaque token marking where the next page resumes; pass it back exactly as given, and only to the endpoint that issued it. This is seek-based, so every page stays fast no matter how deep you page.
        in: query
        name: page
        required: false
        example: ?page[after]=cursor
        schema:
          type: string
      - description: 'Filter to contacts by the datetime they were last modified. Same comma-separated `start,end` ISO8601 format as `inserted_datetime`, with either bound optional: `,2022-07-10T00:00:00Z` returns contacts last updated on or before that instant.'
        in: query
        name: updated_datetime
        required: false
        example: ',2022-07-10T00:00:00Z'
        schema:
          type: string
      - description: Filter by custom field values, as `custom_data[{id}]=value` where `{id}` is a custom field's numeric id. Repeat with different ids to filter on several fields at once; a record must match every one (AND). Matching is case-sensitive exact against the value stored on the record. The id must be a filterable custom field defined on this entity — use `GET /public/v1/custom-fields?parent_object=contact` to list the ids, their types, and which are filterable. A non-numeric id, an id not defined on this entity, or an id that isn't filterable returns a 400.
        in: query
        name: custom_data
        required: false
        schema:
          type: object
      responses:
        '200':
          description: A list of contacts
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/Contacts'
        '400':
          description: Invalid parameters
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API token
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: The API token lacks the required permission
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too Many Requests — the account's list rate limit (3000 calls, refilling at 5 per minute, one per page) was exceeded. Retry after the period in the Retry-After header. Calls with an `updated_datetime` lower bound within the last 30 days are free and never refused; see [Incremental Sync](#incremental-sync).
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      summary: Get contacts
      tags:
      - Contact
    post:
      description: 'Upsert a single contact — one POST handles both create and update. Include an existing contact `id` to update that contact, or omit `id` to create a new one. The create path returns 201 and the update path returns 200; either way the response body is the full contact.


        Updates are sparse: only the fields you send are changed, and any field you omit keeps its current value. `custom_data` is the exception in one direction — sending it replaces the contact''s entire custom-field map (it is not merged key-by-key), so include every key you want to keep; omitting `custom_data` leaves the existing values untouched.


        A contact is a person record in your CRM. It is linked to a company relationship (its employer) via `company_id`, to an owning Distru user via `owner_id`, and carries a name/email/phone profile plus optional driver-license details that surface on an order''s shipping manifest when this contact is named as the driver. Writing a contact does not move inventory and does not sync to Metrc or BioTrack; it does record an activity-log entry on the contact and notify the relevant users. New contacts appear in `GET /public/v1/contacts` within about a second (the list is eventually consistent).


        Required permission: `contacts_permissions_create` to create a new contact, `contacts_permissions_edit` (plus access to the contact under your team restrictions) to update an existing one.'
      operationId: DistruPublic.V1.ContactController.upsert
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                  description: ID of the contact. Provide it to update that contact — it must belong to your company, otherwise the request returns 404. Omit it to create a new contact.
                first_name:
                  type: string
                  description: First name of the contact. Required on create; on update, omitting it leaves the current value unchanged. Must be 1-100 characters and cannot be the literal `you`/`You`. Combined with `last_name` to form the response `full_name`.
                last_name:
                  type: string
                  description: Last name of the contact. When provided, must be 1-100 characters. Combined with `first_name` to form the response `full_name`.
                title:
                  type: string
                  description: Job title of the contact.
                email:
                  type: string
                  description: Email address of the contact. When provided, must contain an `@`.
                phone_number:
                  type: string
                  description: Primary phone number of the contact.
                work_phone_number:
                  type: string
                  description: Work phone number of the contact, returned as `work_phone_number`.
                description:
                  type: string
                  description: Free-text note describing the contact.
                company_id:
                  type: string
                  description: ID of the company relationship (the contact's employer) in your network that this contact belongs to. Must reference an existing company relationship you own. Returned as `company.id` in the response. Omit to create the contact without an employer; on update, omitting leaves the current employer unchanged.
                driver_license_number:
                  type: string
                  description: Driver license number recorded on shipping manifests when this contact is assigned as the driver on an order shipment.
                driver_license_issuing_state:
                  type: string
                  description: Two-letter US state or territory abbreviation (e.g. `CA`, `PR`) of the license's issuing state, recorded on shipping manifests when this contact is the driver. Must be one of the recognized US state/territory codes; any other value is rejected.
                owner_id:
                  type: string
                  description: ID of the Distru user who owns this contact. Must be an existing user in your company that is assignable to you under your team restrictions. Omit on create to leave the contact without an owner; on update, omitting leaves the current owner unchanged.
                custom_data:
                  type: object
                  description: 'A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=contact to retrieve the available custom fields, their IDs, and their types; every key you send must be one of those IDs or the request is rejected. The value format depends on the field''s type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. Sending this field replaces the contact''s entire custom-field map, so include every key you want to keep; omit it to leave existing custom values unchanged.'
              required:
              - first_name
        required: true
      responses:
        '200':
          description: An updated contact
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ContactResponse'
        '201':
          description: A new contact
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ContactResponse'
        '400':
          description: Invalid parameters
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API token
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: The API token lacks the required permission
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      summary: Upsert a contact
      tags:
      - Contact
  /public/v1/contacts/{id}:
    delete:
      description: 'Deletes a contact from your CRM. This is a soft delete: the contact stops appearing in `GET /public/v1/contacts` by default (pass the `deleted` filter as `include` or `only` to still see it) and this endpoint returns 404 for it, but the record is retained — `GET /public/v1/contacts/{id}` keeps resolving it with a non-null `deleted_at`, and anything that already references the contact (an order''s sales-rep assignment, a shipping manifest that names it as driver or contact) keeps its reference and continues to render it. The delete cannot be undone through the API; recreating the contact via upsert produces a new contact with a new `id`. Responds 204 with no body on success, or 404 if no non-deleted contact with that `id` exists in your company (including one that was already deleted or belongs to another company).


        A contact can be deleted at any time — no reference blocks it, regardless of the orders, shipping manifests, or company relationships that use it. No inventory is created, consumed, or released, and nothing is synced to Metrc or BioTrack. A successful delete records a `delete` entry in the contact''s activity log and notifies the relevant users.


        Required permission: `contacts_permissions_delete`, plus access to the contact under your team restrictions — a contact the authenticated user cannot access returns 403.'
      operationId: DistruPublic.V1.ContactController.delete
      parameters:
      - description: ID of the contact to delete, as returned by the list, fetch, and upsert endpoints. An ID that doesn't exist for your company (or was already deleted) returns 404.
        in: path
        name: id
        required: true
        schema:
          type: string
      responses:
        '204':
          description: No Content
        '400':
          description: Invalid parameters
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API token
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: The API token lacks the required permission
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      summary: Delete a contact
      tags:
      - Contact
    get:
      description: 'Fetch a single contact by its ID, including its profile, employer, owner, and custom-field values. Returns 404 if no such contact exists in your company or the authenticated user cannot see it under their team restrictions. Like the list endpoint, reads are eventually consistent — a just-written change may take up to 1 second to reflect here.


        Required permission: `contacts_permissions_view`.'
      operationId: DistruPublic.V1.ContactController.show
      parameters:
      - description: ID of the contact to fetch. Must belong to your company; returns 404 otherwise.
        in: path
        name: id
        required: true
        schema:
          type: string
      responses:
        '200':
          description: A single contact
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ContactResponse'
        '400':
          description: Invalid parameters
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API token
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: The API token lacks the required permission
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      summary: Get a contact
      tags:
      - Contact
components:
  schemas:
    User:
      description: A member of your Distru team — the account behind actions like owning or creating records.
      properties:
        banned:
          description: True when this user has been banned and can no longer sign in
          type: boolean
        deleted_at:
          description: ISO 8601 datetime this user was deleted at, or null when the user is not deleted
          type: string
        email:
          description: The email address of this user
          type: string
        full_name:
          description: The full name of this user, or null when not set
          type: string
        id:
          description: ID for this user
          type: string
        inserted_datetime:
          description: ISO 8601 datetime this user was created at
          type: string
        role:
          $ref: '#/components/schemas/Role'
        updated_datetime:
          description: ISO 8601 datetime this user was last updated at. It also moves on changes not shown here, such as the user signing in.
          type: string
      required:
      - updated_datetime
      - inserted_datetime
      - email
      - id
      title: User
      type: object
    TaskCompact:
      description: A compact reference to a task, as it appears in another entity's `tasks` list.
      properties:
        due_datetime:
          description: When the task is due, as a UTC ISO8601 datetime.
          type: string
        id:
          description: ID of the task.
          type: string
        name:
          description: The task's name.
          type: string
        status:
          description: The task's status.
          enum:
          - ACTIVE
          - COMPLETED
          type: string
      required:
      - due_datetime
      - status
      - name
      - id
      title: Task (compact)
      type: object
    ErrorResponse:
      description: The envelope returned by every failed request (400, 401, 403, 404, 429). `errors` always holds at least one entry.
      properties:
        errors:
          description: One or more errors describing why the request failed.
          items:
            $ref: '#/components/schemas/Error'
          type: array
      required:
      - errors
      title: ErrorResponse
      type: object
    Contacts:
      description: A collection of Contacts
      properties:
        data:
          description: Contacts
          items:
            $ref: '#/components/schemas/Contact'
          type: array
        next_page:
          description: URL for the next page of results; null when there is no next page
          type: string
      title: Contacts
      type: object
    CustomField:
      description: A user-defined field attached to a record, with the value set for this particular record. Which custom fields exist is configured in Distru; use `GET /public/v1/custom-fields` to list the definitions and their IDs.
      properties:
        id:
          description: The ID of this custom field's definition (matches an `id` from `GET /public/v1/custom-fields`). An integer.
          type: integer
        name:
          description: The name of this custom field
          type: string
        value:
          description: This record's value for the custom field, as a string, or null when no value has been set for this record
          type: string
      required:
      - name
      - id
      title: CustomField
      type: object
    Role:
      description: A permission role that determines what a [user](#model-user) can do in Distru.
      properties:
        id:
          description: ID for this role
          type: string
        name:
          description: Name of the role (e.g. Admin, Sales)
          type: string
      required:
      - name
      - id
      title: Role
      type: object
    ContactResponse:
      description: A single contact
      properties:
        data:
          $ref: '#/components/schemas/Contact'
      title: Contact Response
      type: object
    Contact:
      description: A person in Distru's CRM, optionally linked to a company. Name, title, and phone/email fields all come from the underlying profile and are individually optional.
      properties:
        company:
          description: The [company](#model-company) this contact belongs to, carrying just its `id`; null when the contact is not linked to a company
          properties:
            id:
              description: The ID of the [company](#model-company) this contact belongs to
              type: string
          type: object
        custom_data:
          description: The custom data for this contact
          items:
            $ref: '#/components/schemas/CustomField'
          type: array
        deleted_at:
          description: ISO 8601 datetime this contact was deleted at, or null when it is not deleted
          type: string
        description:
          description: Free-text description of this contact, or null when none was entered
          type: string
        driver_license_issuing_state:
          description: The state that issued the driver license used on shipping manifests, or null when not set
          type: string
        driver_license_number:
          description: Driver license number used on shipping manifests, or null when not set
          type: string
        email:
          description: The email address of this contact, or null when not set
          type: string
        first_name:
          description: The first name of this contact, or null when not set
          type: string
        full_name:
          description: The full name of this contact, or null when not set
          type: string
        id:
          description: ID for this contact
          type: string
        inserted_datetime:
          description: ISO 8601 datetime this contact was created at
          type: string
        last_name:
          description: The last name of this contact, or null when not set
          type: string
        owner:
          $ref: '#/components/schemas/User'
        phone_number:
          description: The phone number of this contact, or null when not set
          type: string
        tasks:
          description: 'The tasks linked to this contact that the authenticated user can see: none without `tasks_permissions_view`, and only those their team restrictions allow. An empty array when there are none.'
          items:
            $ref: '#/components/schemas/TaskCompact'
          type: array
        title:
          description: The job title of this contact, or null when not set
          type: string
        updated_datetime:
          description: ISO 8601 datetime this contact was last updated at
          type: string
        work_phone_number:
          description: The work phone number of this contact, or null when not set
          type: string
      required:
      - custom_data
      - tasks
      - updated_datetime
      - inserted_datetime
      - id
      title: Contact
      type: object
    Error:
      description: A single error describing one problem with the request.
      properties:
        message:
          description: Human-readable, customer-facing description of what went wrong.
          type: string
        pointer:
          description: 'Path to the offending field in the request: field names and, for items in a list, their integer position — e.g. ["items", 0, "quantity"]. ["base"] means the error applies to the request as a whole rather than one field.'
          items: {}
          type: array
      required:
      - message
      - pointer
      title: Error
      type: object
  securitySchemes:
    Bearer:
      type: http
      scheme: bearer
      description: 'API token generated in Distru (Settings → Distru API). Send it on every request as `Authorization: Bearer YOUR_API_TOKEN`.'