> ## Documentation Index
> Fetch the complete documentation index at: https://docs.askassembly.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Interactions

> Send events from your own integrations to Wavelength. This is a great way to track how your customers are interacting with your product. 

#### API Key

You must first create an API Key in Wavelength. It is located under "Manage Integrations", then scroll to the bottom and click "Manage API Keys".

Here, you can see your existing keys, their names and expiration. You can delete existing ones.

When creating a new API key, the name must be unique in your organization. Once the key has been created, you will be shown a one-time dialog box with your new API key. You should copy this down somewhere safe -- we will not show this again.

If you lose your API key, you will need to make a new one.

For these endpoints, set the `Authorization` header to your API key value directly (for example `Authorization: <API_KEY>`). Do **not** add a `Bearer` prefix; the full header value is validated as the key.

***

#### List Interactions

## GET /interactions

Returns a paginated list of interactions (top-level tickets) for your organization.

### Query Parameters

| Parameter | Type | Required | Default | Description |
| - | - | - | - | - |
| `limit` | integer | No | 50 | Number of interactions to return. Must be between 1 and 200. |
| `offset` | integer | No | 0 | Number of interactions to skip (for pagination). |
| `status` | string | No | — | Filter by ticket status. Repeatable for multiple values. Valid values: `Open`, `NeedsResponse`, `Breaching`, `Escalated`, `Closed`. Case-sensitive. |
| `assignee_id` | string | No | — | Filter by assignee user ID. Repeatable for multiple values. |
| `company_id` | string | No | — | Filter by company ID. Repeatable for multiple values. |
| `customer_id` | string | No | — | Filter by customer/contact ID. Repeatable for multiple values. |
| `source` | string | No | — | Filter by source channel. Repeatable for multiple values. Valid values: `Slack`, `Gmail`, `Web`, `API`, `Zendesk`, `Intercom`, `Discord`, `GitHubTicket`. |
| `category_id` | string (UUID) | No | — | Filter by category ID. Repeatable for multiple values. Use `GET /categories` to list available IDs. |
| `tag_id` | string (UUID) | No | — | Filter by tag ID. Repeatable for multiple values. Use `GET /tags` to list available IDs. |
| `team_owner_id` | string (UUID) | No | — | Filter by the owning team's ID. Use `GET /teams` to list available IDs. |
| `updated_after` | string | No | — | Return only interactions updated at or after this time. Accepts RFC3339 (`2026-06-01T00:00:00Z`) or bare date (`2026-06-01`). |
| `updated_before` | string | No | — | Return only interactions updated before this time. Same format as `updated_after`. |

### Example: List all interactions

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?limit=50&offset=0" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by status

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?status=Open&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by multiple statuses

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?status=Open&status=NeedsResponse&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by source

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?source=Slack&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by source (multiple)

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?source=Slack&source=Gmail&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by category

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?category_id=<CATEGORY_UUID>&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by tag

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?tag_id=<TAG_UUID>&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Filter by team owner

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?team_owner_id=<TEAM_UUID>&limit=50" \
  -H "Authorization: <API_KEY>"
```

### Example: Incremental sync (interactions updated in the last 24 hours)

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions?updated_after=2026-07-16T00:00:00Z&limit=200" \
  -H "Authorization: <API_KEY>"
```

### Response

```json theme={null}
{
  "data": [
    {
      "id": "01KXNWCA9Y6E2QRB9FSHDQZKGS",
      "ticket_identifier": "ASM",
      "ticket_number": 6579,
      "title": "Support request title",
      "query": "The original message content",
      "ticket_status": "Open",
      "source": "API",
      "url": "https://mail.google.com/...",
      "wavelength_url": "http://dashboard.askassembly.app/issue/ASM-6579",
      "created_at": "2026-07-16T16:32:57Z",
      "updated_at": "2026-07-16T16:37:59Z",
      "assignee_user_id": "user-uuid",
      "company_id": "company-uuid",
      "customer_id": "customer-uuid",
      "owner_replies": 1,
      "customer_replies": 2,
      "attributes": { "my_custom_attr": "value" },
      "user_info": { "id": "user@example.com", "name": "Jane Doe", "email": "user@example.com" },
      "company_info": { "id": "company-uuid", "name": "Acme Corp" }
    }
  ],
  "has_next_page": true,
  "next_cursor": 50
}
```

| Field | Description |
| - | - |
| `url` | Source URL (Slack thread link, Gmail email link, etc.) |
| `wavelength_url` | Direct link to the ticket in the Wavelength dashboard |
| `attributes` | Custom account attributes cached on the interaction |

````

To fetch the next page, pass `next_cursor` as the `offset` in your next request:

```bash
curl -X GET "https://api.wavelength.cx/interactions?limit=50&offset=50" \
  -H "Authorization: <API_KEY>"
````

### Error Responses

| Code | Meaning |
| - | - |
| 400 | Invalid `limit` (must be 1–200), invalid `offset` (must be ≥ 0), or missing auth |
| 429 | Rate limit exceeded |

***

#### Get Interaction with History

## GET /interactions/:id

Returns a single interaction and its full reply/message thread.

### Path Parameters

| Parameter | Type | Description |
| - | - | - |
| `id` | string | Wavelength ULID of the interaction |

### Example

```bash theme={null}
curl -X GET "https://api.wavelength.cx/interactions/01KXNWCA9Y6E2QRB9FSHDQZKGS" \
  -H "Authorization: <API_KEY>"
```

### Response

```json theme={null}
{
  "interaction": {
    "id": "01KXNWCA9Y6E2QRB9FSHDQZKGS",
    "ticket_identifier": "ASM",
    "ticket_number": 6579,
    "title": "Support request title",
    "query": "The original message content",
    "ticket_status": "Open",
    "source": "API",
    "url": "https://mail.google.com/...",
    "wavelength_url": "http://dashboard.askassembly.app/issue/ASM-6579",
    "created_at": "2026-07-16T16:32:57Z",
    "updated_at": "2026-07-16T16:37:59Z",
    "owner_replies": 1,
    "customer_replies": 2,
    "attributes": { "my_custom_attr": "value" },
    "company_info": { "id": "company-uuid", "name": "Acme Corp" },
    "user_info": { "id": "user@example.com", "name": "Jane Doe", "email": "user@example.com" }
  },
  "history": [
    {
      "id": "01KXNWCA9Y6E2QRB9FSHDQZKGT",
      "parent_id": "01KXNWCA9Y6E2QRB9FSHDQZKGS",
      "type": "Message",
      "content": "The original message content",
      "source": "Gmail",
      "created_at": "2026-07-16T16:32:57Z",
      "from": "customer@example.com",
      "to": ["support@company.com"],
      "cc": ["manager@company.com"]
    },
    {
      "id": "01KXNWCA9Y6E2QRB9FSHDQZKGU",
      "parent_id": "01KXNWCA9Y6E2QRB9FSHDQZKGS",
      "type": "Message",
      "content": "Thanks for reaching out! Looking into this now.",
      "source": "Web",
      "created_at": "2026-07-16T16:35:00Z",
      "from": "agent@company.com"
    }
  ]
}
```

The `history` array contains all messages, replies, and internal notes for the interaction in chronological order. The `from` field identifies the message author. For Gmail interactions, `to` and `cc` are included when available.

### Error Responses

| Code | Meaning |
| - | - |
| 400 | Missing or invalid auth |
| 404 | Interaction not found (wrong ID or belongs to a different org) |
| 429 | Rate limit exceeded |

***

#### List Teams

## GET /teams

Returns all teams in your organization. Use team IDs with the `team_owner_id` filter on `GET /interactions`.

### Example

```bash theme={null}
curl -X GET "https://api.wavelength.cx/teams" \
  -H "Authorization: <API_KEY>"
```

### Response

```json theme={null}
{
  "data": [
    {
      "id": "fc12e902-f8ee-4176-947b-7f716469d1d6",
      "name": "Support",
      "description": "Customer support team"
    }
  ]
}
```

### Error Responses

| Code | Meaning |
| - | - |
| 400 | Missing or invalid auth |
| 429 | Rate limit exceeded |

***

#### List Categories

## GET /categories

Returns all categories in your organization. Use category IDs with the `category_id` filter on `GET /interactions`.

### Example

```bash theme={null}
curl -X GET "https://api.wavelength.cx/categories" \
  -H "Authorization: <API_KEY>"
```

### Response

```json theme={null}
{
  "data": [
    {
      "id": "0199868a-ec2d-7d36-bd94-749a4db30dfe",
      "name": "Bug Report"
    }
  ]
}
```

### Error Responses

| Code | Meaning |
| - | - |
| 400 | Missing or invalid auth |
| 429 | Rate limit exceeded |

***

#### List Tags

## GET /tags

Returns all account tags in your organization. Use tag IDs with the `tag_id` filter on `GET /interactions`.

### Example

```bash theme={null}
curl -X GET "https://api.wavelength.cx/tags" \
  -H "Authorization: <API_KEY>"
```

### Response

```json theme={null}
{
  "data": [
    {
      "id": "0195af0e-3213-78fc-a3cf-cb8c192abeaf",
      "name": "VIP",
      "description": "High-priority customer",
      "color": "#7695ff"
    }
  ]
}
```

### Error Responses

| Code | Meaning |
| - | - |
| 400 | Missing or invalid auth |
| 429 | Rate limit exceeded |

***

#### Create Interaction

## POST /interactions

Creates a new interaction (a top-level ticket) in Wavelength from your own integration. This is the endpoint to use for tracking how your customers interact with your product.

The interaction is created with source `API`, attributed to the integration linked to the API key you authenticate with.

### Headers

* `Content-Type: multipart/form-data` (required)
* `Authorization: <API_KEY>` (required; raw key, no `Bearer` prefix)

### Request Body (multipart/form-data)

| Field | Type | Required | Description |
| - | - | - | - |
| `query` | string | Yes | The body of the interaction — the customer's message or event text. |
| `title` | string | No | Title of the ticket. Defaults to empty. |
| `source_specific_id` | string | No | Your own unique identifier for this ticket. Used for deduplication and for replying later via `POST /interactions/reply`. If omitted, Wavelength generates a UUID. |
| `user` | object (JSON string) | No | Who created the interaction. If omitted, the interaction is attributed to `Anonymous`. See the User Object table below. |
| `company_id` | string (UUID) | No | Wavelength ID of the company account to attach this interaction to. Must exist in your organization. |
| `company_source_specific_id` | string | No | Source-specific ID of the company account to attach this interaction to. Must already be mapped to a company in your organization. |
| `additional_properties` | object (JSON string) | No | Arbitrary key/value pairs stored as custom properties on the ticket. Values may be strings, numbers, or booleans. |
| `original_timestamp` | string | No | When the event actually occurred, in RFC3339 format (e.g. `2024-06-10T18:34:00Z`). Defaults to receipt time. |
| `files` | file\[] | No | File attachments (multipart). Repeat the field to attach multiple files. |
| `files_image_url` | string | No | Comma-separated URLs of images to fetch and attach. |

`user`, `additional_properties`, and any other object field are sent as JSON-encoded strings inside the multipart form.

#### User Object

| Field | Type | Required | Description |
| - | - | - | - |
| `email` | string | No\* | User's email address. |
| `id` | string (UUID) | No\* | Wavelength ID of an existing customer. |
| `source_specific_id` | string | No\* | The user's source-specific ID, as already mapped in Wavelength. |
| `name` | string | No | Display name. Falls back to `email` if omitted. |
| `username` | string | No | Username. Falls back to `email` if omitted. |
| `image_url` | string | No | Avatar URL. |

\*If you include a `user` object at all, it must contain at least one of `email`, `id`, or `source_specific_id`. Omit `user` entirely to create the interaction as `Anonymous`.

How the user is resolved:

* **`id`** and **`source_specific_id`** must match a customer that already exists in your organization. If no match is found, the request fails with a 400.
* **`email`** alone does not require a pre-existing customer — if no matching Wavelength contact exists, one is created.

### Example: Minimal request

`query` is the only required field.

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "query=Sample query text"
```

### Example: With a user and a source-specific ID

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "title=Sample title" \
 -F "query=Sample query text" \
 -F "source_specific_id=my_ticket_123" \
 -F 'user={"email": "user@example.com", "name": "John Doe"}' \
 -F "original_timestamp=2024-06-10T18:34:00Z"
```

You can then add replies to this ticket using the same `source_specific_id`:

```bash theme={null}
curl -X POST "https://api.wavelength.cx/interactions/reply?source_specific_id=my_ticket_123" \
  -H "Authorization: <API_KEY>" \
  -F "content=This is a reply to the ticket" \
  -F 'user={"email":"agent@example.com","name":"Support Agent"}'
```

### Example: Attaching to a company by source-specific ID

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "title=Sample title" \
 -F "query=Sample query text" \
 -F "source_specific_id=unique_ticket_id" \
 -F 'user={"email": "user@example.com", "name": "John Doe", "source_specific_id": "userSSID"}' \
 -F "company_source_specific_id=companySSID" \
 -F 'additional_properties={"key1": "value1", "key2": 123, "key3": "value3"}' \
 -F "original_timestamp=2024-06-10T18:34:00Z"
```

### Example: Attaching to a company by Wavelength ID

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "title=Sample title" \
 -F "query=Sample query text" \
 -F 'user={"email": "user@example.com", "name": "John Doe"}' \
 -F "company_id=01945162-52fc-739b-98de-e2ac9f2eec49" \
 -F 'additional_properties={"key1": "value1", "key2": 123, "key3": "value3"}' \
 -F "original_timestamp=2024-06-10T18:34:00Z"
```

### Example: Attaching files

Upload files directly with `files`:

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "query=Sample query text" \
 -F "files=@screenshot.png"
```

Attach multiple files by repeating the field:

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "query=Sample query text" \
 -F "files=@screenshot_1.png" \
 -F "files=@screenshot_2.png"
```

Or have Wavelength fetch images from URLs (comma-separated):

```bash theme={null}
curl -X POST https://api.wavelength.cx/interactions \
 -H "Authorization: <API_KEY>" \
 -H "Content-Type: multipart/form-data" \
 -F "query=Sample query text" \
 -F "files_image_url=https://example.com/img1.jpg,https://example.com/img2.jpg"
```

### Response

```json theme={null}
{
  "created_ticket_number": "ASM-111"
}
```

| Field | Type | Description |
| - | - | - |
| `created_ticket_number` | string | The ticket number of the newly created interaction. |

### Error Responses

Errors take the following format in JSON:

```json theme={null}
{"error": "message"}
```

| Status | Meaning |
| - | - |
| 400 | Invalid request — malformed form data, missing/invalid `query`, a `user` object with none of `email`/`id`/`source_specific_id`, an unresolvable user or company ID, a file that is too large or could not be opened, or an `original_timestamp` that is not valid RFC3339. |
| 400 | Missing or invalid `Authorization` header, or an expired API key. |
| 429 | Rate limit exceeded. |
| 503 | Wavelength server error. It has been logged and our team has been notified. |

### Important Notes

* **File Size Limit**: 4MB per file.
* **Supported Image Types**: JPG and PNG.
* **Rate Limiting**: 30 events per second. Exceeding this returns a 429. If you need a higher rate, please let us know.
* **Anonymous Interactions**: Unlike `POST /interactions/reply`, the `user` field is optional here — omit it and the interaction is attributed to `Anonymous`.

***

#### Create Interaction Reply

## POST /interactions/reply

Creates a new reply/message for an existing ticket. Supports multiple ticket identification methods and file attachments.

### Query Parameters

Exactly one of the following is required:

| Parameter | Type | Description |
| - | - | - |
| `id` | string | Wavelength ULID of the ticket to reply to |
| `source_specific_id` | string | Source-specific ID of the ticket to reply to |

### Headers

* `Content-Type: multipart/form-data` (required for file uploads)
* `Authorization: <API_KEY>` (required; raw key, no `Bearer` prefix)

### Request Body (multipart/form-data)

| Field | Type | Required | Description |
| - | - | - | - |
| `content` | string | Yes | The reply message content |
| `source_specific_id` | string | No | Unique identifier for this reply (for deduplication) |
| `original_timestamp` | string | No | Original timestamp in RFC3339 format |
| `user` | object | Yes | User information object |
| `files` | file\[] | No | File attachments (multipart) |
| `files_image_url` | string | No | Comma-separated URLs of images to attach |

#### User Object

| Field | Type | Required | Description |
| - | - | - | - |
| `id` | string | No\* | User ID |
| `name` | string | No | User name |
| `email` | string | No\* | User email |
| `source_specific_id` | string | No | User's source-specific ID |

\*At least one of `id` or `email` is required. If only `email` is provided, it will be used as the user identifier.

### Ticket Identification

The endpoint requires exactly one query parameter for ticket identification:

* **`id`** - Wavelength ULID of the ticket
* **`source_specific_id`** - Source-specific ID of the ticket

Both parameters cannot be provided simultaneously, and at least one is required.

### Example Request (with Wavelength ULID)

```bash theme={null}
curl -X POST "https://api.wavelength.cx/interactions/reply?id=01KKXRZM9PJRKJ488ZK3PB6JPX" \
  -H "Authorization: <API_KEY>" \
  -F "content=This is my reply to the ticket" \
  -F 'user={"name":"John Doe","email":"john@example.com"}' \
  -F "source_specific_id=reply_12345"
```

### Example Request (with source\_specific\_id)

```bash theme={null}
curl -X POST "https://api.wavelength.cx/interactions/reply?source_specific_id=ticket_ss_123" \
  -H "Authorization: <API_KEY>" \
  -F "content=Reply via source specific ID" \
  -F "files=@attachment.pdf" \
  -F 'user={"name":"Jane Doe","email":"jane@example.com"}'
```

### Example Request (with file uploads)

```bash theme={null}
curl -X POST "https://api.wavelength.cx/interactions/reply?source_specific_id=ticket_abc123" \
  -H "Authorization: <API_KEY>" \
  -F "content=Here are the files you requested" \
  -F "files=@document1.pdf" \
  -F "files=@image.png" \
  -F "files_image_url=https://example.com/image1.jpg,https://example.com/image2.jpg" \
  -F 'user={"name":"Alice","email":"alice@example.com"}'
```

### Response

```json theme={null}
{
  "created_history_id": "01H8X9Z7Y2W3R4T5U6V7W8X9Y"
}
```

| Field | Type | Description |
| - | - | - |
| `created_history_id` | string | ULID of the created history record |

### Error Responses

#### 400 Bad Request

```json theme={null}
{
  "error": "content is required"
}
```

```json theme={null}
{
  "error": "user is required"
}
```

```json theme={null}
{
  "error": "user.id or user.email is required"
}
```

```json theme={null}
{
  "error": "exactly one of id or source_specific_id must be provided"
}
```

```json theme={null}
{
  "error": "invalid ULID format for id parameter"
}
```

#### 404 Not Found

```json theme={null}
{
  "error": "ticket not found for identifier: ticket_abc123"
}
```

#### 409 Conflict (Duplicate)

```json theme={null}
{
  "error": "source specific id already exists"
}
```

#### 413 Payload Too Large

```json theme={null}
{
  "error": "File size exceeds 32MB"
}
```

### Important Notes

* **File Size Limit**: 32MB per file
* **Supported File Types**: Any file type can be uploaded
* **Deduplication**: Duplicate `source_specific_id` values are rejected for Slack/Community Slack sources
* **User Requirement**: User object with `user.id` is now mandatory (no anonymous users)
* **Query Parameter Exclusivity**: Exactly one of `id` or `source_specific_id` must be provided, not both
* **Rate Limiting**: Subject to rate limiting (60 requests per minute per API key/IP)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.