Knak Contacts API

Create, retrieve and list contacts in Knak Send.

OpenAPI Specification

knak-contacts-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  description: '## Overview

    An API specification to provide a Custom Sync Location in Knak.


    By implementing a service conforming to this API specification, you will be able to send asset data to your own service and have that service specify a sync location based on that data.


    ## Authentication

    Knak provides two options for authentication:

    - **Basic Authentication**: Knak will use Basic Authentication to authenticate with your API. You will just need to provide a username and password when configuring the integration.

    - **OAuth2**: Knak will use OAuth2 to authenticate with your API. You will need to implement endpoints under a specified authorization path to support this. The default path will be `/oauth/token` but you can provide a separate path when configuring the integration if you so choose. The flow used is the standard [Authorization Code Grant](https://tools.ietf.org/html/rfc6749#section-4.1).



    Knak will use the tokens generated to make requests from your service.


    ## Custom Sync Location

    When a user has a custom sync location configured and they have set up a sync restriction that leverages the custom sync location.

    Knak will call the `/knak-sync-location` (or your own specified path) endpoint with the asset data when an asset is synced. Your service should return a response with the sync location for the asset.


    When your service provides a sync location, Knak will use that location to display only the available sync location to the user.

    '
  version: V1
  title: Custom Sync Location API Reference Asset Custom Fieldsets Contacts API
  x-logo:
    url: https://s3.amazonaws.com/assets.knak.io/img/Knak-Logo-Medium.png
servers:
- url: https://yourService.com/your-sync-location-api
tags:
- name: Contacts
  description: Create, retrieve and list contacts in Knak Send.
paths:
  /contacts:
    get:
      tags:
      - Contacts
      summary: List contacts
      description: 'Returns a paginated list of contacts. Supports pagination, sorting and filtering.


        - **Sortable fields:** `email`, `first_name`, `last_name`, `created_at`

        - **Filterable fields:** `email`, `first_name`, `last_name`

        '
      operationId: listContacts
      parameters:
      - $ref: '#/components/parameters/PageNumber'
      - $ref: '#/components/parameters/PageSize'
      - name: sort[]
        in: query
        required: false
        description: 'Fields to sort by, passed as a repeated `sort[]` parameter. Prefix a field with `-` for descending order. Allowed fields: `email`, `first_name`, `last_name`, `created_at`.'
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
            enum:
            - email
            - first_name
            - last_name
            - created_at
            - -email
            - -first_name
            - -last_name
            - -created_at
        example:
        - -created_at
      - name: filter[email]
        in: query
        required: false
        description: Filter by email address.
        schema:
          type: string
        example: jane.doe@example.com
      - name: filter[first_name]
        in: query
        required: false
        description: Filter by first name.
        schema:
          type: string
      - name: filter[last_name]
        in: query
        required: false
        description: Filter by last name.
        schema:
          type: string
      responses:
        '200':
          description: A paginated list of contacts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
              examples:
                default:
                  value:
                    data:
                    - id: 9b1c2d3e-4f56-7890-abcd-ef1234567890
                      first_name: Jane
                      last_name: Doe
                      email: jane.doe@example.com
                      avatar_url: https://cdn.example.com/avatars/jane.png
                      supervisor_id: 1a2b3c4d-5e6f-7890-abcd-ef0987654321
                      created_at: '2026-05-01T12:00:00+00:00'
                      updated_at: '2026-05-20T09:30:00+00:00'
                    meta:
                      total: 1
                      current_page: 1
                      last_page: 1
                      per_page: 25
                      from: 1
                      to: 1
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    post:
      tags:
      - Contacts
      summary: Create a contact
      description: Creates a single contact. To create or update many contacts at once, use `POST /contacts/bulk`.
      operationId: createContact
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactInput'
            examples:
              default:
                value:
                  email: jane.doe@example.com
                  first_name: Jane
                  last_name: Doe
                  avatar_url: https://cdn.example.com/avatars/jane.png
                  field_values:
                    department: Engineering
                    startDate: '2026-01-15'
      responses:
        '201':
          description: The contact was created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Contact'
        '400':
          $ref: '#/components/responses/EmailDomainNotAllowed'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/ContactConflict'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /contacts/{id}:
    get:
      tags:
      - Contacts
      summary: Retrieve a contact
      description: Returns a single contact by ID, including its field values.
      operationId: getContact
      parameters:
      - $ref: '#/components/parameters/ContactId'
      responses:
        '200':
          description: The requested contact.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ContactDetail'
              examples:
                default:
                  value:
                    data:
                      id: 9b1c2d3e-4f56-7890-abcd-ef1234567890
                      first_name: Jane
                      last_name: Doe
                      email: jane.doe@example.com
                      avatar_url: https://cdn.example.com/avatars/jane.png
                      supervisor_id: 1a2b3c4d-5e6f-7890-abcd-ef0987654321
                      created_at: '2026-05-01T12:00:00+00:00'
                      updated_at: '2026-05-20T09:30:00+00:00'
                      field_values:
                      - field_id: f1e2d3c4-b5a6-7890-abcd-ef1234567890
                        key: department
                        name: Department
                        type: string
                        value: Engineering
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Contacts
      summary: Delete a contact
      description: Soft-deletes a contact by ID. The contact is removed from listings but retained internally.
      operationId: deleteContact
      parameters:
      - $ref: '#/components/parameters/ContactId'
      responses:
        '204':
          description: The contact was deleted. The response body is empty.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /contacts/{id}/field-values:
    get:
      tags:
      - Contacts
      summary: List a contact's field values
      description: Returns the field values associated with a single contact.
      operationId: getContactFieldValues
      parameters:
      - $ref: '#/components/parameters/ContactId'
      responses:
        '200':
          description: The contact's field values.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/FieldValue'
              examples:
                default:
                  value:
                    data:
                    - field_id: f1e2d3c4-b5a6-7890-abcd-ef1234567890
                      key: department
                      name: Department
                      type: string
                      value: Engineering
                    - field_id: a9b8c7d6-e5f4-3210-abcd-ef0987654321
                      key: startDate
                      name: Start Date
                      type: date
                      value: '2026-01-15'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    put:
      tags:
      - Contacts
      summary: Replace a contact's field values
      description: 'Replaces the field values for a single contact. Each key in `field_values` must match the `key` of an

        existing field (see `GET /fields`) and its value is validated against the field''s type. Between 1 and 20

        field values may be provided.

        '
      operationId: replaceContactFieldValues
      parameters:
      - $ref: '#/components/parameters/ContactId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FieldValuesInput'
            examples:
              default:
                value:
                  field_values:
                    department: Engineering
                    startDate: '2026-01-15'
      responses:
        '200':
          description: The contact's updated field values.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/FieldValue'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /contacts/bulk:
    post:
      tags:
      - Contacts
      summary: Bulk upsert contacts
      description: 'Creates or updates up to 1000 contacts in a single request, matching existing contacts by email.


        Validation is performed per contact. The request as a whole succeeds with a `200` response even when

        some individual contacts fail; the response body reports counts of `created`, `updated` and `failed`

        contacts, along with an `errors` array describing each failure by its index in the submitted array.


        This endpoint is subject to the stricter bulk rate limit (60 requests per minute).

        '
      operationId: bulkUpsertContacts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - contacts
              properties:
                contacts:
                  type: array
                  minItems: 1
                  maxItems: 1000
                  items:
                    $ref: '#/components/schemas/ContactInput'
            examples:
              default:
                value:
                  contacts:
                  - email: jane.doe@example.com
                    first_name: Jane
                    last_name: Doe
                    field_values:
                      department: Engineering
                  - email: john@notallowed.com
                    first_name: John
                    last_name: Smith
      responses:
        '200':
          description: 'The bulk operation was processed. Inspect `created`, `updated`, `failed` and `errors` to determine

            the outcome of each contact.

            '
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/BulkUpsertResult'
              examples:
                default:
                  value:
                    data:
                      created: 1
                      updated: 0
                      failed: 1
                      errors:
                      - index: 1
                        email: john@notallowed.com
                        details:
                          email:
                          - Domain is not allowed
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Contacts
      summary: Bulk delete contacts
      description: 'Deletes up to 1000 contacts in a single request, identified by their IDs. The response reports the

        number of contacts actually deleted; IDs that do not match an existing contact are ignored rather than

        causing the request to fail.


        This endpoint is subject to the stricter bulk rate limit (60 requests per minute).

        '
      operationId: bulkDeleteContacts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - ids
              properties:
                ids:
                  type: array
                  minItems: 1
                  maxItems: 1000
                  items:
                    type: string
                    maxLength: 255
            examples:
              default:
                value:
                  ids:
                  - 9b1c2d3e-4f56-7890-abcd-ef1234567890
                  - 1a2b3c4d-5e6f-7890-abcd-ef0987654321
      responses:
        '200':
          description: The bulk delete was processed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                        description: The number of contacts that were deleted.
              examples:
                default:
                  value:
                    data:
                      deleted: 2
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  responses:
    Forbidden:
      description: Knak Send access is not enabled for the account, or the token lacks the required scope.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: ACCESS_DENIED
              message: Knak Send access is not enabled for this account.
    TooManyRequests:
      description: 'The rate limit for the endpoint has been exceeded. A `Retry-After` header indicates how many seconds

        to wait before retrying.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/HttpError'
          example:
            message: Too Many Attempts.
            type: HttpException
    NotFound:
      description: The requested resource could not be found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: CONTACT_NOT_FOUND
              message: Contact not found.
    EmailDomainNotAllowed:
      description: The contact's email domain is not in the account's allow list.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: EMAIL_DOMAIN_NOT_ALLOWED
              message: The address john@notallowed.com has a domain that is not in your allow list.
    ValidationError:
      description: One or more request fields failed backend validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorList'
          example:
            error_at: '2026-06-02T13:56:31+00:00'
            errors:
            - identifier: ValidationError
              details: One or more of the given request fields failed backend validation.
              meta:
                email:
                - The email field is required.
    Unauthenticated:
      description: The access token is missing, invalid or expired.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: UNAUTHENTICATED
              message: Invalid or expired access token.
    ContactConflict:
      description: A contact with the given email already exists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: CONTACT_ALREADY_EXISTS
              message: A contact with this email already exists.
  schemas:
    BulkUpsertResult:
      type: object
      description: The outcome of a bulk upsert operation.
      properties:
        created:
          type: integer
          description: The number of contacts created.
        updated:
          type: integer
          description: The number of existing contacts updated.
        failed:
          type: integer
          description: The number of contacts that failed validation or processing.
        errors:
          type: array
          description: One entry per failed contact.
          items:
            type: object
            properties:
              index:
                type: integer
                description: The 0-based position of the contact in the submitted `contacts` array.
              email:
                type:
                - string
                - 'null'
                description: The email of the failed contact, if available.
              details:
                type: object
                description: A map of field name to an array of validation messages.
                additionalProperties:
                  type: array
                  items:
                    type: string
    ErrorObject:
      type: object
      description: The compact error shape returned for authentication, authorization and conflict errors.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: A machine-readable error code.
            message:
              type: string
              description: A human-readable description of the error.
    FieldValue:
      type: object
      description: A single field value belonging to a contact.
      properties:
        field_id:
          type: string
          description: The ID of the field this value belongs to.
        key:
          type:
          - string
          - 'null'
          description: The generated key of the field.
        name:
          type:
          - string
          - 'null'
          description: The human-readable name of the field.
        type:
          description: The data type of the field. May be `null` if the field's metadata is unavailable.
          oneOf:
          - $ref: '#/components/schemas/FieldType'
          - type: 'null'
        value:
          type: string
          description: The field value, represented as a string.
    PaginationMeta:
      type: object
      description: Pagination metadata describing the current result window.
      properties:
        total:
          type: integer
          description: The total number of matching records.
        current_page:
          type: integer
        last_page:
          type: integer
        per_page:
          type: integer
        from:
          type:
          - integer
          - 'null'
          description: The index of the first record on the current page.
        to:
          type:
          - integer
          - 'null'
          description: The index of the last record on the current page.
    ContactDetail:
      type: object
      description: A contact with its associated field values, returned when retrieving a single contact.
      allOf:
      - $ref: '#/components/schemas/Contact'
      - type: object
        properties:
          field_values:
            type: array
            items:
              $ref: '#/components/schemas/FieldValue'
    FieldValuesInput:
      type: object
      description: The payload used to replace a contact's field values.
      required:
      - field_values
      properties:
        field_values:
          type: object
          minProperties: 1
          maxProperties: 20
          description: 'A map of field key to scalar value. Each key must match the `key` of an existing field

            (see `GET /fields`). Between 1 and 20 entries may be provided. Replaces the contact''s existing

            field values.

            '
          additionalProperties:
            type:
            - string
            - number
            - boolean
          example:
            department: Engineering
            startDate: '2026-01-15'
    ContactInput:
      type: object
      description: The payload used to create or upsert a contact.
      required:
      - email
      - first_name
      - last_name
      properties:
        email:
          type: string
          format: email
          maxLength: 255
          description: The contact's email address. Used as the match key for bulk upserts.
        first_name:
          type: string
          maxLength: 255
        last_name:
          type: string
          maxLength: 255
        avatar_url:
          type:
          - string
          - 'null'
          format: uri
          description: 'URL of the contact''s avatar image. For `POST /contacts` this must be a valid HTTP(S) URL.

            For bulk upserts (`POST /contacts/bulk`) the value is accepted as any string and is not validated

            as a URL.

            '
        field_values:
          type: object
          description: 'A map of field key to scalar value. Each key must match the `key` of an existing field

            (see `GET /fields`). Values are validated against the field''s type.

            '
          additionalProperties:
            type:
            - string
            - number
            - boolean
          example:
            department: Engineering
            startDate: '2026-01-15'
    HttpError:
      type: object
      description: The error shape returned for rate-limit (429) errors.
      properties:
        message:
          type: string
          description: A human-readable description of the error.
        type:
          type: string
          description: The error type. Always `HttpException` for this shape.
    FieldType:
      type: string
      description: The data type of a field.
      enum:
      - string
      - number
      - date
      - datetime
      - boolean
    Contact:
      type: object
      description: A contact as returned in list and create responses.
      properties:
        id:
          type: string
          description: The unique identifier of the contact.
        first_name:
          type: string
        last_name:
          type: string
        email:
          type: string
          format: email
        avatar_url:
          type:
          - string
          - 'null'
          format: uri
          description: URL of the contact's avatar image, if set.
        supervisor_id:
          type:
          - string
          - 'null'
          description: The ID of this contact's supervisor, if one is assigned.
        created_at:
          type:
          - string
          - 'null'
          format: date-time
          description: ISO 8601 creation timestamp.
        updated_at:
          type:
          - string
          - 'null'
          format: date-time
          description: ISO 8601 last-updated timestamp.
    ErrorList:
      type: object
      description: The error shape returned for validation and not-found errors.
      properties:
        error_at:
          type: string
          format: date-time
          description: ISO 8601 timestamp of when the error occurred.
        errors:
          type: array
          items:
            type: object
            properties:
              identifier:
                type: string
                description: A machine-readable identifier for the error type.
              details:
                type: string
                description: A human-readable description of the error.
              meta:
                type: object
                description: Additional context. For validation errors, a map of field name to validation messages.
  parameters:
    PageNumber:
      name: page[number]
      in: query
      required: false
      description: The page of results to return (1-based).
      schema:
        type: integer
        minimum: 1
        default: 1
    PageSize:
      name: page[size]
      in: query
      required: false
      description: The number of records per page.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 25
    ContactId:
      name: id
      in: path
      required: true
      description: The unique identifier of the contact.
      schema:
        type: string
      example: 9b1c2d3e-4f56-7890-abcd-ef1234567890