REST API reference
Read and write conversations, messages, contacts and help center articles of your asktrix workspace. JSON over HTTPS, one token per workspace.
The API is available on the Team and Business plans. It works on exactly one workspace: the one the token belongs to. Changes you make through the API behave like clicks in the app. Your team sees them right away, replies reach the visitor, and webhooks fire.
Prefer a machine-readable description? /api/v1/openapi.json is an OpenAPI 3.1 document generated from the same source as this page. Import it into Postman, Insomnia or a client generator.
Base URL
https://asktrix.org/api/v1Requests and responses are JSON in UTF-8. Timestamps are ISO 8601 in UTC.
Authentication
Create a token under Settings → Workspace → API & webhooks → Create token. Only owners and admins can do this. Pick a permission and an expiry:
- Read only tokens can only send
GETrequests. - Read & write tokens can also reply, change status, assignment and labels, and create or change contacts.
- Expiry: never, 30 days, 90 days or one year. A workspace can have up to 50 active tokens.
The token is shown once. We only store a fingerprint, so a lost token can't be recovered. Revoke it and create a new one. Send it in the Authorization header:
curl "https://asktrix.org/api/v1/me" \
-H "Authorization: Bearer atx_XXXXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"Replies sent with "as": "user" (the default) appear under the name of the teammate who created the token. If that person has left the workspace, they're sent on behalf of the workspace. Internal notes need a creator who is still a member, and snoozing needs a creator whose account still exists.
Plans and rate limits
| Plan | Requests per minute, per workspace |
|---|---|
| Free, Start | No API access. Requests answer 402 plan_locked. |
| Team | 60 |
| Business | 300 (can be raised in your contract) |
Every response carries X-RateLimit-Limit and X-RateLimit-Remaining. Over the limit you get 429 rate_limited with Retry-After: 60.
Pagination
List endpoints return up to limit items (default 25, maximum 100), newest first, wrapped in data. If hasMore is true, request the next page with cursor=nextCursor. Cursors are opaque. Don't build them yourself.
{
"data": [ … ],
"hasMore": true,
"nextCursor": "MjAyNi0xMS0wNVQx…"
}Sort order: conversations by their last message, messages and contacts by creation time, articles by their last change. updated_since on conversations filters by the last message, too.
Errors
Errors always have the same shape. For validation errors, field names the field.
{
"error": {
"code": "validation_failed",
"message": "status must be pending, unresolved or resolved.",
"field": "status"
}
}| Status | Code | When |
|---|---|---|
| 400 | invalid_json | The body isn't a JSON object. |
| 400 | invalid_parameter | A query parameter has the wrong format (e.g. a date that isn't ISO 8601). |
| 400 | invalid_cursor | The cursor is malformed. |
| 401 | unauthorized | The token is missing, malformed, unknown or revoked. |
| 401 | token_expired | The token has expired. |
| 402 | plan_locked | The workspace's plan doesn't include the API (Team and up). |
| 403 | insufficient_scope | A read-only token tried to write. |
| 403 | suspended | The workspace is suspended. |
| 404 | not_found | The object doesn't exist in this workspace, or the endpoint doesn't exist. |
| 413 | payload_too_large | The body is larger than 200 KB. |
| 422 | validation_failed | A field is invalid. error.field names it. |
| 429 | rate_limited | Too many requests. Wait for Retry-After seconds. |
| 500 | internal_error | Something went wrong on our side. |
Within v1 we only add fields to responses. We don't rename or remove them, so ignore fields you don't know.
Basics
GET/api/v1/me
Check the workspace and token. Needs a token with read permission.
Request
curl "https://asktrix.org/api/v1/me" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"workspace": {
"id": "cm1w0…",
"slug": "acme",
"name": "Acme"
},
"token": {
"id": "cm9t2…",
"name": "CRM sync",
"prefix": "atx_PmybkW4L",
"scopes": [
"read",
"write"
],
"expiresAt": null
}
}Conversations
GET/api/v1/conversations
List and filter conversations. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
status | query | pending | unresolved | resolved | open | Filter or set the status (open = pending + unresolved) |
mailbox | query | main | spam | automated | <mailboxId> | Mailbox |
label | query | string | Only with this label |
assignee_id | query | userId | none | Assigned person, none = nobody |
contact_id | query | string | Only conversations of this contact |
updated_since | query | ISO 8601 | Only changed since (conversations: last message) |
limit | query | 1–100 (25) | Items per page |
cursor | query | string | nextCursor of the previous page |
Request
curl "https://asktrix.org/api/v1/conversations?status=open&limit=10" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": [
{
"id": "cm4p1…",
"status": "unresolved",
"mailbox": "main",
"channel": "chat",
"subject": null,
"assigneeId": "cm3a9…",
"labels": [
"billing"
],
"customData": {},
"aiActive": false,
"unread": true,
"lastMessage": "Hi, I was charged twice this month.",
"lastFrom": "visitor",
"lastMessageAt": "2026-11-05T10:12:00.000Z",
"snoozedUntil": null,
"resolvedAt": null,
"firstResponseAt": null,
"createdAt": "2026-11-05T10:11:42.000Z",
"contactId": "cm2k7…",
"contact": {
"id": "cm2k7…",
"name": "Lena Fischer",
"email": "[email protected]",
"country": "DE"
}
}
],
"hasMore": true,
"nextCursor": "MjAyNi0xMS0wNVQx…"
}GET/api/v1/conversations/{id}
One conversation with its latest 100 messages. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
Request
curl "https://asktrix.org/api/v1/conversations/CONVERSATION_ID" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": {
"id": "cm4p1…",
"status": "unresolved",
"mailbox": "main",
"channel": "chat",
"subject": null,
"assigneeId": "cm3a9…",
"labels": [
"billing"
],
"customData": {},
"aiActive": false,
"unread": true,
"lastMessage": "Hi, I was charged twice this month.",
"lastFrom": "visitor",
"lastMessageAt": "2026-11-05T10:12:00.000Z",
"snoozedUntil": null,
"resolvedAt": null,
"firstResponseAt": null,
"createdAt": "2026-11-05T10:11:42.000Z",
"contactId": "cm2k7…",
"contact": {
"id": "cm2k7…",
"name": "Lena Fischer",
"email": "[email protected]",
"country": "DE"
},
"messages": [
{
"id": "cm5d3…",
"conversationId": "cm4p1…",
"from": "teammate",
"type": "text",
"content": "Sorry about that. I've refunded the second charge.",
"internal": false,
"author": {
"id": "cm3a9…",
"name": "Jamie Weber"
},
"readAt": null,
"editedAt": null,
"createdAt": "2026-11-05T10:14:08.000Z"
}
]
}
}PATCH/api/v1/conversations/{id}
Change status, assignment, labels or snooze. Needs a token with write permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
status | body | pending | unresolved | resolved | Filter or set the status (open = pending + unresolved) |
assigneeId | body | userId | null | Assign a teammate, null unassigns |
labels | body | string[] | Replace all labels |
addLabels | body | string[] | Add labels |
removeLabels | body | string[] | Remove labels |
snoozedUntil | body | ISO 8601 | null | Snooze until, null ends the snooze |
Request
curl -X PATCH "https://asktrix.org/api/v1/conversations/CONVERSATION_ID" \
-H "Authorization: Bearer $ASKTRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"resolved","addLabels":["billing"]}'Response
{
"data": {
"id": "cm4p1…",
"status": "resolved",
"mailbox": "main",
"channel": "chat",
"subject": null,
"assigneeId": "cm3a9…",
"labels": [
"billing"
],
"customData": {},
"aiActive": false,
"unread": true,
"lastMessage": "Hi, I was charged twice this month.",
"lastFrom": "visitor",
"lastMessageAt": "2026-11-05T10:12:00.000Z",
"snoozedUntil": null,
"resolvedAt": null,
"firstResponseAt": null,
"createdAt": "2026-11-05T10:11:42.000Z",
"contactId": "cm2k7…",
"contact": {
"id": "cm2k7…",
"name": "Lena Fischer",
"email": "[email protected]",
"country": "DE"
}
}
}GET/api/v1/conversations/{id}/messages
All messages of a conversation, page by page. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
limit | query | 1–100 (25) | Items per page |
cursor | query | string | nextCursor of the previous page |
Request
curl "https://asktrix.org/api/v1/conversations/CONVERSATION_ID/messages?limit=10" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": [
{
"id": "cm5d3…",
"conversationId": "cm4p1…",
"from": "teammate",
"type": "text",
"content": "Sorry about that. I've refunded the second charge.",
"internal": false,
"author": {
"id": "cm3a9…",
"name": "Jamie Weber"
},
"readAt": null,
"editedAt": null,
"createdAt": "2026-11-05T10:14:08.000Z"
}
],
"hasMore": true,
"nextCursor": "MjAyNi0xMS0wNVQx…"
}POST/api/v1/conversations/{id}/messages
Reply or write an internal note. Needs a token with write permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
contentrequired | body | string | Message text (Markdown) |
type | body | text | note | note = internal note, visible to the team only |
as | body | user | workspace | user = as the token's creator, workspace = on behalf of the workspace |
Request
curl -X POST "https://asktrix.org/api/v1/conversations/CONVERSATION_ID/messages" \
-H "Authorization: Bearer $ASKTRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content":"Thanks, we found your order.","as":"user"}'Response
{
"data": {
"id": "cm5d3…",
"conversationId": "cm4p1…",
"from": "teammate",
"type": "text",
"content": "Sorry about that. I've refunded the second charge.",
"internal": false,
"author": {
"id": "cm3a9…",
"name": "Jamie Weber"
},
"readAt": null,
"editedAt": null,
"createdAt": "2026-11-05T10:14:08.000Z"
}
}Contacts
GET/api/v1/contacts
List and search contacts. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
email | query | string | E-mail address |
q | query | string | Full-text search |
label | query | string | Only with this label |
identified | query | true | Only contacts with a name, e-mail or phone |
updated_since | query | ISO 8601 | Only changed since (conversations: last message) |
limit | query | 1–100 (25) | Items per page |
cursor | query | string | nextCursor of the previous page |
Request
curl "https://asktrix.org/api/v1/contacts?limit=10" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": [
{
"id": "cm2k7…",
"name": "Lena Fischer",
"displayName": "Lena Fischer",
"email": "[email protected]",
"phone": null,
"avatarUrl": null,
"company": {
"name": "Fischer Design"
},
"labels": [
"vip"
],
"customData": {
"plan": "pro"
},
"city": "Hamburg",
"country": "DE",
"timezone": "Europe/Berlin",
"languages": [
"de",
"en"
],
"blocked": false,
"unsubscribed": false,
"marketingConsent": false,
"consentAt": null,
"consentSource": null,
"lastSeenAt": "2026-11-05T10:11:40.000Z",
"createdAt": "2026-10-02T08:30:00.000Z",
"updatedAt": "2026-11-05T10:11:42.000Z"
}
],
"hasMore": true,
"nextCursor": "MjAyNi0xMS0wNVQx…"
}POST/api/v1/contacts
Create a contact. If the e-mail already exists, the existing contact comes back (200). Needs a token with write permission.
| Parameter | In | Type | Description |
|---|---|---|---|
email | body | string | E-mail address |
name | body | string | Name |
phone | body | string | Phone number |
company | body | string | Company name |
city | body | string | City |
country | body | ISO 3166-1 alpha-2 | Country |
labels | body | string[] | Replace all labels |
customData | body | object | Custom data (text, number, yes/no) |
marketingConsent | body | boolean | Documented consent to marketing emails (source "api"). Only contacts with consent receive email campaigns. |
consentText | body | string | Wording the contact agreed to (proof) |
Request
curl -X POST "https://asktrix.org/api/v1/contacts" \
-H "Authorization: Bearer $ASKTRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","name":"Lena Fischer","labels":["vip"],"customData":{"plan":"pro"}}'Response (201 when created, 200 when the email already existed)
{
"data": {
"id": "cm2k7…",
"name": "Lena Fischer",
"displayName": "Lena Fischer",
"email": "[email protected]",
"phone": null,
"avatarUrl": null,
"company": {
"name": "Fischer Design"
},
"labels": [
"vip"
],
"customData": {
"plan": "pro"
},
"city": "Hamburg",
"country": "DE",
"timezone": "Europe/Berlin",
"languages": [
"de",
"en"
],
"blocked": false,
"unsubscribed": false,
"marketingConsent": false,
"consentAt": null,
"consentSource": null,
"lastSeenAt": "2026-11-05T10:11:40.000Z",
"createdAt": "2026-10-02T08:30:00.000Z",
"updatedAt": "2026-11-05T10:11:42.000Z"
},
"existed": false
}GET/api/v1/contacts/{id}
Get one contact. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
Request
curl "https://asktrix.org/api/v1/contacts/CONTACT_ID" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": {
"id": "cm2k7…",
"name": "Lena Fischer",
"displayName": "Lena Fischer",
"email": "[email protected]",
"phone": null,
"avatarUrl": null,
"company": {
"name": "Fischer Design"
},
"labels": [
"vip"
],
"customData": {
"plan": "pro"
},
"city": "Hamburg",
"country": "DE",
"timezone": "Europe/Berlin",
"languages": [
"de",
"en"
],
"blocked": false,
"unsubscribed": false,
"marketingConsent": false,
"consentAt": null,
"consentSource": null,
"lastSeenAt": "2026-11-05T10:11:40.000Z",
"createdAt": "2026-10-02T08:30:00.000Z",
"updatedAt": "2026-11-05T10:11:42.000Z"
}
}PATCH/api/v1/contacts/{id}
Change a contact. customData is merged, null removes a key. Needs a token with write permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
name | body | string | null | Name |
email | body | string | null | E-mail address |
phone | body | string | null | Phone number |
city | body | string | null | City |
country | body | string | null | Country |
company | body | string | object | null | Company name |
labels | body | string[] | Replace all labels |
customData | body | object | Custom data (text, number, yes/no) |
blocked | body | boolean | Block the contact |
marketingConsent | body | boolean | Documented consent to marketing emails (source "api"). Only contacts with consent receive email campaigns. |
consentText | body | string | Wording the contact agreed to (proof) |
Request
curl -X PATCH "https://asktrix.org/api/v1/contacts/CONTACT_ID" \
-H "Authorization: Bearer $ASKTRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"labels":["vip","newsletter"],"customData":{"plan":"business","trial":null}}'Response
{
"data": {
"id": "cm2k7…",
"name": "Lena Fischer",
"displayName": "Lena Fischer",
"email": "[email protected]",
"phone": null,
"avatarUrl": null,
"company": {
"name": "Fischer Design"
},
"labels": [
"vip",
"newsletter"
],
"customData": {
"plan": "business"
},
"city": "Hamburg",
"country": "DE",
"timezone": "Europe/Berlin",
"languages": [
"de",
"en"
],
"blocked": false,
"unsubscribed": false,
"marketingConsent": false,
"consentAt": null,
"consentSource": null,
"lastSeenAt": "2026-11-05T10:11:40.000Z",
"createdAt": "2026-10-02T08:30:00.000Z",
"updatedAt": "2026-11-05T10:11:42.000Z"
}
}Help center
GET/api/v1/help-center/articles
Help center articles, published ones by default. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
status | query | published | draft | all | Filter or set the status (open = pending + unresolved) |
locale | query | en, de, … | Language |
category_id | query | string | Category |
q | query | string | Full-text search |
updated_since | query | ISO 8601 | Only changed since (conversations: last message) |
limit | query | 1–100 (25) | Items per page |
cursor | query | string | nextCursor of the previous page |
Request
curl "https://asktrix.org/api/v1/help-center/articles?limit=10" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": [
{
"id": "cm6b8…",
"locale": "en",
"slug": "reset-your-password",
"title": "Reset your password",
"description": "Get a new password if you can't sign in.",
"status": "published",
"hidden": false,
"featured": false,
"category": {
"id": "cm6a1…",
"name": "Account"
},
"url": "https://asktrix.org/help/acme/en/reset-your-password",
"views": 412,
"helpful": 37,
"unhelpful": 2,
"publishedAt": "2026-09-14T12:00:00.000Z",
"createdAt": "2026-09-14T11:40:00.000Z",
"updatedAt": "2026-10-28T09:05:00.000Z"
}
],
"hasMore": true,
"nextCursor": "MjAyNi0xMS0wNVQx…"
}GET/api/v1/help-center/articles/{id}
One article with its content as HTML and text. Needs a token with read permission.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | ID from the URL |
Request
curl "https://asktrix.org/api/v1/help-center/articles/ARTICLE_ID" \
-H "Authorization: Bearer $ASKTRIX_TOKEN"Response
{
"data": {
"id": "cm6b8…",
"locale": "en",
"slug": "reset-your-password",
"title": "Reset your password",
"description": "Get a new password if you can't sign in.",
"status": "published",
"hidden": false,
"featured": false,
"category": {
"id": "cm6a1…",
"name": "Account"
},
"url": "https://asktrix.org/help/acme/en/reset-your-password",
"views": 412,
"helpful": 37,
"unhelpful": 2,
"publishedAt": "2026-09-14T12:00:00.000Z",
"createdAt": "2026-09-14T11:40:00.000Z",
"updatedAt": "2026-10-28T09:05:00.000Z",
"contentHtml": "<p>…</p>",
"contentText": "…"
}
}