Knak Fields API

Create and list custom contact fields (schema metadata).

OpenAPI Specification

knak-fields-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  description: |
    # Overview
    Welcome to the developer documentation for the Knak Send API.
    We provide a RESTful interface to key resources within Knak Send to enable your own automation workflows.
    This API will allow you to automate processes regarding contact and field management within your Knak Send environment.
    You can download the formal definition of this public interface in OpenAPI 3 (formerly Swagger) format using the link above.

    ## Endpoint
    `https://send.knak.io/api/public/v1`

    ## Authentication
    All requests are authenticated using a Bearer token in the `Authorization` header:
    ```
    curl --location --request GET 'https://send.knak.io/api/public/v1/contacts' \
    --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbG...'
    ```
    A token can be created as a non-expiring token through the Enterprise UI, via the [API Access menu](https://enterprise.knak.io/account/api-access). The account associated with the token must have Knak Send access enabled.

    ## Errors
    Errors in requests made to the API can be viewed directly from the response code that is returned.

    Below are a list of the common error responses returned and an explanation of what they mean.

    | Code | Reason |Description |
    | ----------------| ----------- | ----------- |
    | **400**  | **Bad Request** | The request was rejected (for example, a contact's email domain is not in the account's allow list). |
    | **401**      | **Unauthenticated** | The access token is missing, invalid, or expired. |
    | **403**    | **Forbidden** | The account does not have Knak Send access enabled, or the token lacks the required scope. |
    | **404**  | **Not Found** | The requested resource could not be found. Verify that the resource exists and that you are using the correct identifier. |
    | **409**  | **Conflict** | The resource could not be created because it already exists (for example, a field with the same generated key). |
    | **422**  | **Unprocessable Entity** | One or more request fields failed backend validation. The `meta` object lists the offending fields. |
    | **429**  | **Too Many Requests** | The rate limit for the endpoint has been exceeded. |
    | **503**  | **Service Unavailable** | An upstream authentication service is temporarily unavailable. This can occur on any request; retry after a short delay. |

    Three error response shapes are used. Where an error `code` (or `identifier`) is present, branch on it
    programmatically; the human-readable `message`/`details` text is subject to change.

    Authentication, authorization, bad-request, not-found, conflict and service errors
    (400, 401, 403, 404, 409, 503) return a compact `error` object with a machine-readable `code`:
    ```json
    { "error": { "code": "UNAUTHENTICATED", "message": "Invalid or expired access token." } }
    ```
    Validation errors (422) return an `errors` array:
    ```json
    {
      "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."] }
        }
      ]
    }
    ```
    Rate-limit (429) errors return a `message`/`type` object:
    ```json
    { "message": "Too Many Attempts.", "type": "HttpException" }
    ```

    ## Rate limiting
    Requests are rate limited per API client. Standard endpoints allow up to **1000 requests per minute**.
    Bulk endpoints (such as `POST /contacts/bulk`) are limited to **60 requests per minute**. Exceeding a limit
    returns a `429 Too Many Requests` response.

    ## Pagination
    List endpoints that can return large result sets are paginated using the `page` query parameter:

    - `page[number]` — the page to return (1-based, default `1`).
    - `page[size]` — the number of records per page (default `25`, maximum `100`).

    Paginated responses include a `meta` object describing the result window (`total`, `current_page`,
    `last_page`, `per_page`, `from`, `to`).

    ## Filtering
    List endpoints support filtering on specific fields using the `filter` query parameter, in the form
    `filter[field_name]=value`. The fields that can be filtered are listed on each endpoint.

    For simple equality, pass the value directly: `filter[first_name]=Jane`. For other comparisons, pass an
    `operator` and `value`: `filter[first_name][operator]=startsWith&filter[first_name][value]=Ja`. Supported
    operators include `=`, `!=`, `>`, `<`, `~`, `contains`, `notContains`, `startsWith`, `between`, `exists`
    and `notExists`.

    ## Sorting
    List endpoints support sorting via the `sort` query parameter. Pass one or more field names; prefix a field
    with `-` for descending order. For example `sort[]=last_name&sort[]=-created_at`. The fields that can be
    sorted are listed on each endpoint.
  version: V1
  title: Knak Send Contacts API Reference — Fields
  x-logo:
    url: https://s3.amazonaws.com/assets.knak.io/img/Knak-Logo-Medium.png
servers:
- url: https://send.knak.io/api/public/v1
  description: production
tags:
- name: Fields
  description: Create and list custom contact fields (schema metadata).
paths:
  /fields:
    get:
      tags:
      - Fields
      summary: List fields
      description: |
        Returns all custom contact fields for the authenticated company. Fields are schema metadata sourced
        from connected systems and created via this API; the list is not paginated.
      operationId: listFields
      responses:
        '200':
          description: The list of fields.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Field'
              examples:
                default:
                  value:
                    data:
                    - id: f1e2d3c4-b5a6-7890-abcd-ef1234567890
                      key: department
                      name: Department
                      type: string
                      directory_id: d4c3b2a1-0f9e-8765-abcd-ef1234567890
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    post:
      tags:
      - Fields
      summary: Create a field
      description: |
        Creates a new custom contact field. The field's `key` is generated automatically from its `name`
        (for example `Start Date` becomes `startDate`). Attempting to create a field whose generated key
        already exists returns a `409 Conflict`.
      operationId: createField
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FieldInput'
            examples:
              default:
                value:
                  name: Department
                  type: string
      responses:
        '201':
          description: The field was created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Field'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/FieldConflict'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /fields/{id}/values:
    get:
      tags:
      - Fields
      summary: List a field's values
      description: |
        Returns the distinct values stored for a single field across the company's contacts. Results are
        paginated and sorted alphabetically by value by default.
      operationId: listFieldValues
      parameters:
      - $ref: '#/components/parameters/FieldId'
      - $ref: '#/components/parameters/PageNumber'
      - $ref: '#/components/parameters/PageSize'
      - name: sort[]
        in: query
        required: false
        description: Sort by value, passed as a repeated `sort[]` parameter. Prefix with `-` for descending
          order. Defaults to ascending by value.
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
            enum:
            - value
            - -value
        example:
        - value
      responses:
        '200':
          description: A paginated list of the field's distinct values.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
              examples:
                default:
                  value:
                    data:
                    - Engineering
                    - Marketing
                    - Sales
                    meta:
                      total: 3
                      current_page: 1
                      last_page: 1
                      per_page: 25
                      from: 1
                      to: 3
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/FieldNotFound'
        '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
    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.
    FieldConflict:
      description: A field with the same generated key already exists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: FIELD_ALREADY_EXISTS
              message: A field with the name Department already exists in API directory.
    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.
    FieldNotFound:
      description: No field exists with the given ID.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorObject'
          example:
            error:
              code: FIELD_NOT_FOUND
              message: Field with id f1e2d3c4-b5a6-7890-abcd-ef1234567890 not found.
  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
    FieldId:
      name: id
      in: path
      required: true
      description: The unique identifier of the field.
      schema:
        type: string
      example: f1e2d3c4-b5a6-7890-abcd-ef1234567890
  schemas:
    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.
    Field:
      type: object
      description: A custom contact field (schema metadata).
      properties:
        id:
          type: string
          description: The unique identifier of the field.
        key:
          type: string
          description: The generated key of the field, derived from its name (for example `startDate`).
        name:
          type: string
          description: The human-readable name of the field.
        type:
          $ref: '#/components/schemas/FieldType'
        directory_id:
          type: string
          description: The ID of the directory the field belongs to.
    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.
    FieldInput:
      type: object
      description: The payload used to create a field.
      required:
      - name
      - type
      properties:
        name:
          type: string
          maxLength: 255
          description: The human-readable name of the field. The field key is generated from this value.
        type:
          $ref: '#/components/schemas/FieldType'
    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.
    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.
    FieldType:
      type: string
      description: The data type of a field.
      enum:
      - string
      - number
      - date
      - datetime
      - boolean