> For the complete documentation index, see [llms.txt](https://mava.gitbook.io/mava-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mava.gitbook.io/mava-docs/webhooks-and-api/api/create-ticket.md).

# Create Ticket

### Endpoint

```
POST https://gateway.mava.app/api/ticket
```

### Authentication

Authentication requires an API token passed via the `x-auth-token` header. Generate API keys in your dashboard under **Admin → API & Webhooks → API Keys**.

**Rate Limit:** 90 requests per 30 seconds per API key. Exceeding this threshold returns `429 Too Many Requests`.

```
x-auth-token: YOUR_API_KEY
Content-Type: application/json
```

### Request Body

Provide exactly one of `customerId` or `customer`. All other parameters are optional with sensible defaults.

| Field                    | Type      | Required                 | Description                                                                                                                        |
| ------------------------ | --------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `customerId`             | string    | Conditional              | ObjectId of an existing customer. Mutually exclusive with `customer`.                                                              |
| `customer`               | object    | Conditional              | Customer details for find-or-create by email or wallet. Mutually exclusive with `customerId`. Requires `email` or `walletAddress`. |
| `customer.name`          | string    | No                       | Display name (applied only on creation).                                                                                           |
| `customer.email`         | string    | No\*                     | Lookup/creation identifier. Required if `walletAddress` absent.                                                                    |
| `customer.walletAddress` | string    | No\*                     | EVM address (`0x` + 40 hex). Required if `email` absent.                                                                           |
| `customer.attributes`    | array     | No                       | Up to 30 custom attributes: `{ "attribute": "<id>", "content": "<value>" }`                                                        |
| `status`                 | string    | No                       | Initial ticket status. Default: `"Open"`.                                                                                          |
| `priority`               | number    | No                       | `1` = Low, `2` = Medium, `3` = High. Default: `2`.                                                                                 |
| `sourceType`             | string    | No                       | Origin source. Default: `"web"`.                                                                                                   |
| `assignedTo`             | string    | No                       | ID of the agent to assign (from GET /agents).                                                                                      |
| `category`               | string    | No                       | ObjectId of a ticket category.                                                                                                     |
| `tags`                   | string\[] | No                       | Tag ObjectIds (max 20).                                                                                                            |
| `emailSubjectLine`       | string    | No                       | Email subject (max 998 chars).                                                                                                     |
| `attributes`             | array     | No                       | Up to 30 ticket attributes: `{ "attribute": "<id>", "content": "<value>" }`                                                        |
| `message`                | object    | No                       | Optional initial customer message.                                                                                                 |
| `message.content`        | string    | Yes (if message present) | Message text (max 10,000 chars).                                                                                                   |
| `message.attachments`    | array     | No                       | Pre-uploaded file attachments (max 10).                                                                                            |
| `silent`                 | boolean   | No                       | When true, suppresses notifications and automations. Default: `false`.                                                             |
| `notify`                 | boolean   | No                       | In-app notification for assigned agent. Default: `true`.                                                                           |
| `triggerAutomations`     | boolean   | No                       | Run automations with initial message. Default: `true`.                                                                             |

> **Note:** `assignedTo` takes an agent **ID** (obtained from GET /agents), not an email address. This allows agents who signed up with a wallet — and therefore have no email — to be assigned tickets. An ID that does not belong to your organization is rejected with `ASSIGNEE_NOT_FOUND`.

#### Valid Values

* **`status`**: `"Open"`, `"Pending"`, `"Resolved"`, `"Waiting"`
* **`priority`**: `1`, `2`, `3`
* **`sourceType`**: `"web"`, `"discord"`, `"telegram"`, `"twitter"`, `"email"`

#### Attachments

Files must be pre-uploaded to Mava-approved storage. The endpoint validates URLs against an allow-list and rejects external URLs.

| Field      | Type   | Required | Description                                                                     |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------- |
| `url`      | string | Yes      | HTTPS URL in your Mava S3 bucket.                                               |
| `fileName` | string | Yes      | Original filename.                                                              |
| `fileSize` | number | No       | File size in bytes.                                                             |
| `type`     | string | No       | Type enum: `"Image"`, `"Video"`, `"Audio"`, `"Voice"`, `"Animation"`, `"File"`. |

#### Customer Resolution

When providing a `customer` object, the system looks up existing customers in your organization by: (1) `email` if provided, otherwise (2) `walletAddress`. If no match exists, a new customer is created. Existing customers are reused without overwriting `name` or `attributes`.

### Response

**Success — `201 Created`**

Returns the fully populated ticket with all fields:

```json
{
  "ticket": {
    "_id": "645xyz...",
    "customer": {
      "_id": "645abc...",
      "name": "Jane Doe",
      "email": "jane@example.com"
    },
    "client": "645org...",
    "status": "Open",
    "priority": 2,
    "sourceType": "web",
    "assignedTo": null,
    "category": null,
    "tags": [],
    "attributes": [],
    "aiStatus": "None",
    "isVisible": true,
    "messages": [
      {
        "_id": "645msg...",
        "messageType": "ExternalMessage",
        "content": "Hello, I need help with my order.",
        "senderType": "customer",
        "senderName": null,
        "attachments": [],
        "createdAt": "2026-05-14T12:00:00.000Z"
      }
    ],
    "createdAt": "2026-05-14T12:00:00.000Z",
    "updatedAt": "2026-05-14T12:00:00.000Z"
  }
}
```

#### **Error Responses**

All non-2xx responses include a stable, uppercase `error` code and optional `message`:

| Status | Error Code               | Condition                                                      |
| ------ | ------------------------ | -------------------------------------------------------------- |
| `400`  | `INVALID_CUSTOMER_MODE`  | Both or neither customer mode sent, or missing email/wallet.   |
| `400`  | `VALIDATION_ERROR`       | Field validation failed (type, range, length, etc.).           |
| `400`  | `INVALID_ATTACHMENT_URL` | URL outside allow-list, non-HTTPS, or path traversal detected. |
| `400`  | `ASSIGNEE_NOT_FOUND`     | Agent ID does not exist.                                       |
| `401`  | —                        | Missing or invalid token.                                      |
| `404`  | `CUSTOMER_NOT_FOUND`     | Customer ID not found or belongs to another org.               |
| `404`  | `ASSIGNEE_NOT_FOUND`     | Agent ID not found or in different org.                        |
| `404`  | `CATEGORY_NOT_FOUND`     | Category not found or in different org.                        |
| `404`  | `TAG_NOT_FOUND`          | One or more tags not found or in different org.                |
| `429`  | —                        | Rate limit exceeded.                                           |
| `500`  | `INTERNAL_ERROR`         | Server error; request rolls back completely.                   |

Error format:

```json
{
  "error": "VALIDATION_ERROR",
  "message": "body/priority must be equal to one of the allowed values"
}
```

### Behavior

* **Atomicity** — All operations (customer creation, ticket creation, messaging, notifications) execute within a single transaction. Failure rolls back the entire request.
* **Tenant Isolation** — All ObjectId references are verified against your organization. Cross-org references return `404`.
* **Empty Tickets** — Tickets without messages won't appear in the default "Open" filter but remain visible in Global space.
* **Silent Override** — Setting `silent: true` forces both `notify` and `triggerAutomations` to `false`.

### Code Examples

**Curl — Minimal with Existing Customer**

```bash
curl -X POST https://gateway.mava.app/api/ticket \
  -H "x-auth-token: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "645abc1234567890abcdef12"
  }'
```

**Curl — Find-or-Create by Email with Message**

```bash
curl -X POST https://gateway.mava.app/api/ticket \
  -H "x-auth-token: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": {
      "email": "jane@example.com",
      "name": "Jane Doe"
    },
    "priority": 3,
    "message": {
      "content": "I cannot log in to my account."
    }
  }'
```

**Curl — Full Payload with Assignment, Category, Tags, and Attachment**

```bash
curl -X POST https://gateway.mava.app/api/ticket \
  -H "x-auth-token: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "645abc1234567890abcdef12",
    "status": "Open",
    "priority": 3,
    "sourceType": "email",
    "assignedTo": "645ghi1234567890abcdef34",
    "category": "645jkl1234567890abcdef56",
    "tags": ["645mno1234567890abcdef78"],
    "emailSubjectLine": "Refund request — order #1234",
    "message": {
      "content": "Please see attached receipt.",
      "attachments": [
        {
          "url": "https://s3.eu-central-1.amazonaws.com/app.mava.container.2/receipt.jpg",
          "fileName": "receipt.jpg",
          "fileSize": 30106,
          "type": "Image"
        }
      ]
    }
  }'
```

> The `assignedTo` value above (`645ghi1234567890abcdef34`) is an agent **ID** from GET /agents, not an email.

**Node.js — Create and Retrieve Ticket ID**

```javascript
const response = await fetch('https://gateway.mava.app/api/ticket', {
  method: 'POST',
  headers: {
    'x-auth-token': process.env.MAVA_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    customer: {
      email: 'jane@example.com',
      name: 'Jane Doe',
    },
    message: {
      content: 'Hello, I need help with my order.',
    },
  }),
});

if (!response.ok) {
  const { error, message } = await response.json();
  throw new Error(`Mava create-ticket failed: ${error} — ${message ?? ''}`);
}

const { ticket } = await response.json();
console.log('Created ticket:', ticket._id);
```

**Node.js — Silent Backfill**

```javascript
await fetch('https://gateway.mava.app/api/ticket', {
  method: 'POST',
  headers: {
    'x-auth-token': process.env.MAVA_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    customer: { email: 'legacy@example.com' },
    status: 'Resolved',
    sourceType: 'email',
    message: { content: 'Imported from legacy system.' },
    silent: true,
  }),
});
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://mava.gitbook.io/mava-docs/webhooks-and-api/api/create-ticket.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
