Knak Contacts API
Create, retrieve and list contacts in Knak Send.
Create, retrieve and list contacts in Knak Send.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
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.curl "https://apis.io/api/v1/apis/knak:knak-contacts-api"
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.
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: 3.2.0
info:
title: Knak Send API Reference Contacts API
version: V1
x-logo:
url: https://s3.amazonaws.com/assets.knak.io/img/Knak-Logo-Medium.png
contact:
email: support@knak.com
description: '# Overview
Welcome to the developer documentation for the Knak Send API.'
servers:
- url: https://send.knak.io/api/public/v1
description: production
security:
- bearerAuth: []
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:
schemas:
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'
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
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'
FieldType:
type: string
description: The data type of a field.
enum:
- string
- number
- date
- datetime
- boolean
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.
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.
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.
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.
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.
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'
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.
responses:
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.
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.
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.
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.
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.
parameters:
ContactId:
name: id
in: path
required: true
description: The unique identifier of the contact.
schema:
type: string
example: 9b1c2d3e-4f56-7890-abcd-ef1234567890
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
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: A bearer token generated through the Enterprise API Access menu.
x-provenance:
method: harvested
publisher: Knak
source: https://developer.knak.com/openapi/send/send-api.yml
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)