# Create Segment

`POST https://api.inboxjot.com/v1/segments`

Creates a segment. A static segment holds the contacts you add. A dynamic segment holds every contact that matches its rules, and keeps itself up to date. Needs a Full key. A key limited to one domain answers 403. Send an optional `Idempotency-Key` header to retry safely. See Idempotency.

## Body Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | The segment name, 1 to 100 characters. |
| `description` | string \| null | No | A description, up to 500 characters. |
| `type` | string | Yes | `static` or `dynamic`. |
| `conditions` | object \| null | No | Needed for a dynamic segment, and not allowed for a static one. |
| `conditions.match` | string | Yes | `all` needs every rule. `any` needs one. |
| `conditions.rules` | object[] | Yes | Up to 20 rules. |
| `conditions.rules[].field` | string | Yes | `email`, `first_name`, `last_name`, `language`, `status`, `created_at`, `segment`, `email.sent`, `email.delivered`, `email.opened`, `email.clicked`, `email.bounced`, `email.complained`, or `property.<key>` for a property you added. |
| `conditions.rules[].operator` | string | Yes | Text fields take `is`, `is_not`, `contains`, `not_contains`, `starts_with`, `ends_with`, `is_set` and `is_not_set`. Numbers take `equals`, `not_equals`, `greater_than` and `less_than`. Dates take `within`, `not_within`, `before` and `after`. `segment` takes `in` and `not_in`. Email activity takes `within`, `not_within`, `at_least` and `never`. |
| `conditions.rules[].value` | string \| number \| boolean \| object | No | Text up to 500 characters, a number or a boolean. A date window is a date or a number of days such as `30d`. `at_least` takes `{ "count": 2, "days": 30 }`, with a count up to 1,000 and up to 400 days. A `segment` rule takes the id of a static segment. |
| `conditions.rules[].value.count` | number | Yes | How many times, up to 1,000. |
| `conditions.rules[].value.days` | number | Yes | The window in days, up to 400. |

## Response

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | No | The segment id. |
| `name` | string | No | The segment name. |
| `description` | string \| null | No | The description. |
| `type` | string | No | `static` or `dynamic`. |
| `conditions` | object \| null | No | The rules of a dynamic segment. `null` for a static one. |
| `conditions.match` | string | No | `all` needs every rule. `any` needs one. |
| `conditions.rules` | object[] | No | Up to 20 rules. |
| `conditions.rules[].field` | string | No | `email`, `first_name`, `last_name`, `language`, `status`, `created_at`, `segment`, `email.sent`, `email.delivered`, `email.opened`, `email.clicked`, `email.bounced`, `email.complained`, or `property.<key>` for a property you added. |
| `conditions.rules[].operator` | string | No | Text fields take `is`, `is_not`, `contains`, `not_contains`, `starts_with`, `ends_with`, `is_set` and `is_not_set`. Numbers take `equals`, `not_equals`, `greater_than` and `less_than`. Dates take `within`, `not_within`, `before` and `after`. `segment` takes `in` and `not_in`. Email activity takes `within`, `not_within`, `at_least` and `never`. |
| `conditions.rules[].value` | string \| number \| boolean \| object | No | Text up to 500 characters, a number or a boolean. A date window is a date or a number of days such as `30d`. `at_least` takes `{ "count": 2, "days": 30 }`, with a count up to 1,000 and up to 400 days. A `segment` rule takes the id of a static segment. |
| `conditions.rules[].value.count` | number | No | How many times, up to 1,000. |
| `conditions.rules[].value.days` | number | No | The window in days, up to 400. |
| `contact_count` | integer \| null | No | How many contacts are in it. `null` until a dynamic segment is first counted. |
| `counted_at` | string \| null | No | When a dynamic segment was last counted. |
| `created_at` | string | No | When it was created. |
| `updated_at` | string | No | When it last changed. |

## Request

cURL:

```bash
curl -X POST https://api.inboxjot.com/v1/segments \
  -H "Authorization: Bearer $INBOXJOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engaged customers",
    "type": "dynamic",
    "conditions": {
      "match": "all",
      "rules": [
        {
          "field": "property.plan",
          "operator": "is",
          "value": "pro"
        },
        {
          "field": "email.opened",
          "operator": "within",
          "value": "30d"
        }
      ]
    }
  }'
```

## Responses

| Status | Description |
| --- | --- |
| 201 | Created the segment. |
| 400 | A field is missing or invalid, or the Idempotency-Key header is not valid. |
| 401 | The API key is missing, revoked or expired. |
| 403 | The key is a Sending key or is limited to one domain, or the request comes from outside its IP allowlist. |
| 409 | A request with the same Idempotency-Key is still running. Retry after one second. |
| 413 | The body is larger than 2 MB. |
| 415 | The Content-Type header is not application/json. |
| 422 | The Idempotency-Key was already used with a different request. |
| 429 | Too many requests for this key. Wait for the seconds in the Retry-After header. |
| 500 | Something failed on our side. Retry later. |

201:

```json
{
  "id": "seg_06d2mfk8r2kd7fq4mx9ab",
  "name": "Engaged customers",
  "description": null,
  "type": "dynamic",
  "conditions": {
    "match": "all",
    "rules": [
      {
        "field": "property.plan",
        "operator": "is",
        "value": "pro"
      },
      {
        "field": "email.opened",
        "operator": "within",
        "value": "30d"
      }
    ]
  },
  "contact_count": null,
  "counted_at": null,
  "created_at": "2026-10-01T12:00:00.000Z",
  "updated_at": "2026-10-01T12:00:00.000Z"
}
```

400:

```json
{
  "name": "validation_error",
  "status": 400,
  "message": "A dynamic segment needs conditions",
  "errors": [
    {
      "message": "A dynamic segment needs conditions",
      "location": "conditions"
    }
  ],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

401:

```json
{
  "name": "unauthorized",
  "status": 401,
  "message": "Unauthorized",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

403:

```json
{
  "name": "forbidden",
  "status": 403,
  "message": "This key cannot be used from 203.0.113.7",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

409:

```json
{
  "name": "concurrent_idempotent_requests",
  "status": 409,
  "message": "A request with this idempotency key is still in progress. Try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

413:

```json
{
  "name": "payload_too_large",
  "status": 413,
  "message": "The request body is too large",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

415:

```json
{
  "name": "unsupported_media_type",
  "status": 415,
  "message": "The Content-Type must be application/json",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

422:

```json
{
  "name": "invalid_idempotent_request",
  "status": 422,
  "message": "This idempotency key was already used with a different request",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

429:

```json
{
  "name": "rate_limit_exceeded",
  "status": 429,
  "message": "Too many attempts. Try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

500:

```json
{
  "name": "unknown_error",
  "status": 500,
  "message": "Something went wrong. Please try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```
