# Workspace events API

> Define workspace events and the types of their properties, so the w: events you send are checked.

Base URL: `https://api.emailit.com/v2`. Authenticate with `Authorization: Bearer <API key>`.

## Create a workspace event — POST /workspace/events

> Define a workspace event and its typed properties. Events of this type are then sent with the w: prefix and checked against the definition.

# Create a workspace event

Defines a workspace event: a name and the properties every event of that type carries, each with a type. You then send it as `w:<name>`, and Emailit rejects events that don't match. Requires an API key with the `full` scope.

Workspace events are included with Pro, Business and Custom plans. A workspace can define as many as its plan has event types: 100 on Pro and 1,000 on Business, with no limit on Custom. Custom events (`c:<name>`) need no definition. See [Workspace events](/docs/events/workspace-events/).

`POST /workspace/events`

## Body parameters

- `name` (string, required): The event name, for example `customer.type`: 1 to 100 letters, digits, `.`, `-` or `_`, starting with a letter or digit. You can also send it with the prefix (`w:customer.type`); the prefix is removed. Must be unique in the workspace.

- `title` (string | null): A readable name shown in the dashboard, up to 120 characters.

- `description` (string | null): Note for your team, up to 1,000 characters.

- `properties` (object[]): Up to 50 property definitions. Default `[]`, which means events of this type carry no properties. Each one has: - `name` (required): 1 to 64 letters, digits, `-` or `_`, starting with a letter or digit. Dots aren't allowed, because webhook filters and templates use dots to reach nested values. Names must be unique within the definition. - `type` (required): `string`, `number`, `date` or `boolean`, in any letter case. - `title`: a label, up to 120 characters. - `description`: up to 1,000 characters. - `required`: `true` if every event must include the property. Default `false`.

## Returns

Returns `201 Created` with the [workspace event object](/docs/api-reference/workspace-events/get/).

| Status | When |
| --- | --- |
| `403` | The API key doesn't have the `full` scope, or the workspace is on Pay as you go: `error` is `plan_required` and `required_plan` is `pro`. |
| `409` | A workspace event with this name exists. `errors.name` says so. |
| `422` | A field is invalid: `errors` is keyed by its path, such as `name` or `properties.1.type`, and `message` repeats the first problem. Also returned with `code: "workspace_events_limit"` when the workspace already has as many workspace events as its plan allows, and for a name that starts with `c:`. |

**Request** `POST /workspace/events`

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/workspace/events \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "customer.type",
    "title": "Customer type",
    "description": "Set when a customer'\''s account type changes in the shop.",
    "properties": [
      { "name": "segment", "type": "string", "title": "Segment", "description": "b2b or b2c", "required": true },
      { "name": "since", "type": "date" }
    ]
  }'
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/workspace/events', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EMAILIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'customer.type',
    title: 'Customer type',
    description: "Set when a customer's account type changes in the shop.",
    properties: [
      { name: 'segment', type: 'string', title: 'Segment', description: 'b2b or b2c', required: true },
      { name: 'since', type: 'date' },
    ],
  }),
});
const definition = await res.json();
```

**Python**

```python
import os, requests

r = requests.post(
    "https://api.emailit.com/v2/workspace/events",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
    json={
        "name": "customer.type",
        "title": "Customer type",
        "description": "Set when a customer's account type changes in the shop.",
        "properties": [
            {"name": "segment", "type": "string", "title": "Segment", "description": "b2b or b2c", "required": True},
            {"name": "since", "type": "date"},
        ],
    },
)
definition = r.json()
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->post('workspace/events', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
    'json' => [
        'name' => 'customer.type',
        'title' => 'Customer type',
        'description' => "Set when a customer's account type changes in the shop.",
        'properties' => [
            ['name' => 'segment', 'type' => 'string', 'title' => 'Segment', 'description' => 'b2b or b2c', 'required' => true],
            ['name' => 'since', 'type' => 'date'],
        ],
    ],
]);
$definition = json_decode($response->getBody(), true);
```

**201**

```json
{
  "object": "workspace_event",
  "id": "etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0",
  "name": "customer.type",
  "type": "w:customer.type",
  "title": "Customer type",
  "description": "Set when a customer's account type changes in the shop.",
  "properties": [
    { "name": "segment", "type": "string", "title": "Segment", "description": "b2b or b2c", "required": true },
    { "name": "since", "type": "date", "title": null, "description": null, "required": false }
  ],
  "created_at": "2026-10-19T08:00:00.000000+00:00",
  "updated_at": "2026-10-19T08:00:00.000000+00:00"
}
```

**403**

```json
{
  "error": "plan_required",
  "required_plan": "pro",
  "message": "Workspace and custom events are included with Pro and Business."
}
```

**409**

```json
{
  "error": "w:customer.type is already defined",
  "errors": {
    "name": ["is already defined"]
  }
}
```

**422**

```json
{
  "error": "properties.1.type must be one of string, number, date, boolean",
  "message": "properties.1.type must be one of string, number, date, boolean",
  "errors": {
    "properties.1.type": ["must be one of string, number, date, boolean"]
  }
}
```

---
Source: https://emailit.com/docs/api-reference/workspace-events/create/

## Retrieve a workspace event — GET /workspace/events/{id}

> Retrieve a workspace event definition by ID or name, with its typed properties.

# Retrieve a workspace event

Retrieves the definition of a workspace event: its name, title and the properties senders must follow. Requires an API key with the `full` scope.

`GET /workspace/events/{id}`

## Path parameters

- `id` (string, required): The definition ID (`etp_…`), its name (`customer.type`) or its event type (`w:customer.type`). URL-encode the `:` if your client doesn't.

## Returns

Returns the workspace event object.

- `object` (string): Always `workspace_event`.

- `id` (string): Definition ID, prefixed `etp_`.

- `name` (string): The event name, without the prefix.

- `type` (string): The type to send and filter by: `w:` followed by the name.

- `title` (string | null): A readable name, shown in the dashboard instead of the type, for example on a contact's activity.

- `description` (string | null): Note for your team.

- `properties` (object[]): The properties an event of this type can carry, each with: - `name`: the key in the event's `properties`. - `type`: `string`, `number`, `date` or `boolean`. See [Property types](/docs/events/workspace-events/#property-types). - `title`, `description`: optional labels, or `null`. - `required`: whether every event must include it.

- `created_at, updated_at` (string): Timestamps in UTC.

Returns `404` with `error: "Workspace event not found"` if no definition matches.

**Request** `GET /workspace/events/{id}`

**cURL**

```bash
curl https://api.emailit.com/v2/workspace/events/w%3Acustomer.type \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/workspace/events/customer.type', {
  headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` },
});
const definition = await res.json();
```

**Python**

```python
import os, requests

r = requests.get(
    "https://api.emailit.com/v2/workspace/events/customer.type",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
)
definition = r.json()
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->get('workspace/events/customer.type', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
]);
$definition = json_decode($response->getBody(), true);
```

**200**

```json
{
  "object": "workspace_event",
  "id": "etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0",
  "name": "customer.type",
  "type": "w:customer.type",
  "title": "Customer type",
  "description": "Set when a customer's account type changes in the shop.",
  "properties": [
    { "name": "segment", "type": "string", "title": "Segment", "description": "b2b or b2c", "required": true },
    { "name": "since", "type": "date", "title": null, "description": null, "required": false }
  ],
  "created_at": "2026-10-19T08:00:00.000000+00:00",
  "updated_at": "2026-10-19T08:00:00.000000+00:00"
}
```

**404**

```json
{
  "error": "Workspace event not found"
}
```

---
Source: https://emailit.com/docs/api-reference/workspace-events/get/

## Update a workspace event — POST /workspace/events/{id}

> Rename a workspace event or change its title, description or properties. Events already stored don't change.

# Update a workspace event

Updates the fields you pass and leaves the others unchanged. Requires an API key with the `full` scope.

The definition only checks new events. Events already stored keep their type and properties, so after a change, older events may have properties the definition no longer lists.

- `properties` replaces the whole list. To add a property, send the current list plus the new one.
- Renaming changes the type to send. Events stored under the old name keep it, and new events with the old name are rejected, unless you define it again.

`POST /workspace/events/{id}`

## Path parameters

- `id` (string, required): The definition ID (`etp_…`), its name or its event type (`w:…`).

## Body parameters

- `name` (string): A new name, with the same rules as on [create](/docs/api-reference/workspace-events/create/#body-parameters).

- `title` (string | null): Up to 120 characters. `null` or an empty string clears it.

- `description` (string | null): Up to 1,000 characters. `null` or an empty string clears it.

- `properties` (object[]): The new property list, up to 50, as on [create](/docs/api-reference/workspace-events/create/#body-parameters). `[]` removes every property.

## Returns

Returns the updated [workspace event object](/docs/api-reference/workspace-events/get/).

| Status | When |
| --- | --- |
| `404` | No definition matches `id`. |
| `409` | Another workspace event already has the new name. |
| `422` | A field is invalid: `errors` is keyed by its path, and `message` repeats the first problem. |

**Request** `POST /workspace/events/{id}`

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/workspace/events/customer.type \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": [
      { "name": "segment", "type": "string", "title": "Segment", "required": true },
      { "name": "since", "type": "date" },
      { "name": "vat_exempt", "type": "boolean" }
    ]
  }'
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/workspace/events/customer.type', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EMAILIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    properties: [
      { name: 'segment', type: 'string', title: 'Segment', required: true },
      { name: 'since', type: 'date' },
      { name: 'vat_exempt', type: 'boolean' },
    ],
  }),
});
const definition = await res.json();
```

**Python**

```python
import os, requests

r = requests.post(
    "https://api.emailit.com/v2/workspace/events/customer.type",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
    json={
        "properties": [
            {"name": "segment", "type": "string", "title": "Segment", "required": True},
            {"name": "since", "type": "date"},
            {"name": "vat_exempt", "type": "boolean"},
        ]
    },
)
definition = r.json()
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->post('workspace/events/customer.type', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
    'json' => [
        'properties' => [
            ['name' => 'segment', 'type' => 'string', 'title' => 'Segment', 'required' => true],
            ['name' => 'since', 'type' => 'date'],
            ['name' => 'vat_exempt', 'type' => 'boolean'],
        ],
    ],
]);
$definition = json_decode($response->getBody(), true);
```

**200**

```json
{
  "object": "workspace_event",
  "id": "etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0",
  "name": "customer.type",
  "type": "w:customer.type",
  "title": "Customer type",
  "description": "Set when a customer's account type changes in the shop.",
  "properties": [
    { "name": "segment", "type": "string", "title": "Segment", "description": null, "required": true },
    { "name": "since", "type": "date", "title": null, "description": null, "required": false },
    { "name": "vat_exempt", "type": "boolean", "title": null, "description": null, "required": false }
  ],
  "created_at": "2026-10-19T08:00:00.000000+00:00",
  "updated_at": "2026-10-19T10:12:45.000000+00:00"
}
```

**409**

```json
{
  "error": "w:customer.segment is already defined",
  "errors": {
    "name": ["is already defined"]
  }
}
```

---
Source: https://emailit.com/docs/api-reference/workspace-events/update/

## List workspace events — GET /workspace/events

> List the workspace's event definitions in name order, with their typed properties, search and filters.

# List workspace events

Returns the workspace's event definitions, sorted by name. Requires an API key with the `full` scope.

`GET /workspace/events`

## Query parameters

- `page` (integer): Page number, starting at 1.

- `limit` (integer): Definitions per page, from 1 to 250.

- `search` (string): Case-insensitive match on part of the name or the title.

- `match`, `order`, `direction`: see [Filtering](https://emailit.com/docs/api-reference/filtering/).

### Filter keys

Filters use `key.condition=value` query parameters, for example `name.starts_with=order.` or `created_at.after=2026-10-01`. See [Filtering](/docs/api-reference/filtering/) for the conditions per type.

| Key | Type | Notes |
| --- | --- | --- |
| `name` | string | The name without the `w:` prefix. |
| `title` | string | |
| `created_at` | date | |
| `updated_at` | date | |

Sort keys for `order`: `name`, `title`, `created_at`, `updated_at`. The default is `name`, ascending.

## Returns

- `data` (object[]): [Workspace event objects](/docs/api-reference/workspace-events/get/) on this page.

- `total_records` (integer): Number of definitions that match the query.

- `next_page_url` (string | null): Path of the next page, or `null` on the last page. It carries only `page` and `limit`; add your search and filters again when you follow it.

- `previous_page_url` (string | null): Path of the previous page, or `null` on the first page.

**Request** `GET /workspace/events`

**cURL**

```bash
curl -G https://api.emailit.com/v2/workspace/events \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  --data-urlencode "search=customer"
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/workspace/events?search=customer', {
  headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` },
});
const { data, total_records } = await res.json();
```

**Python**

```python
import os, requests

r = requests.get(
    "https://api.emailit.com/v2/workspace/events",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
    params={"search": "customer"},
)
definitions = r.json()["data"]
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->get('workspace/events', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
    'query' => ['search' => 'customer'],
]);
$definitions = json_decode($response->getBody(), true)['data'];
```

**200**

```json
{
  "data": [
    {
      "object": "workspace_event",
      "id": "etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0",
      "name": "customer.type",
      "type": "w:customer.type",
      "title": "Customer type",
      "description": "Set when a customer's account type changes in the shop.",
      "properties": [
        { "name": "segment", "type": "string", "title": "Segment", "description": "b2b or b2c", "required": true },
        { "name": "since", "type": "date", "title": null, "description": null, "required": false }
      ],
      "created_at": "2026-10-19T08:00:00.000000+00:00",
      "updated_at": "2026-10-19T08:00:00.000000+00:00"
    }
  ],
  "total_records": 1,
  "next_page_url": null,
  "previous_page_url": null
}
```

---
Source: https://emailit.com/docs/api-reference/workspace-events/list/

## Delete a workspace event — DELETE /workspace/events/{id}

> Delete a workspace event definition. Stored events are kept, and new events of that type are rejected.

# Delete a workspace event

Deletes a workspace event definition. Requires an API key with the `full` scope.

Events already stored with this type are kept, in the event log and on contacts. New events of the type are rejected with `422` until you define it again. Webhooks subscribed to the type keep the subscription.

`DELETE /workspace/events/{id}`

## Path parameters

- `id` (string, required): The definition ID (`etp_…`), its name or its event type (`w:…`).

## Returns

- `object` (string): Always `workspace_event`.

- `id` (string): ID of the deleted definition.

- `name` (string): Its name.

- `type` (string): Its event type, `w:` followed by the name.

- `deleted` (boolean): Always `true`.

Returns `404` if no definition matches.

**Request** `DELETE /workspace/events/{id}`

**cURL**

```bash
curl -X DELETE https://api.emailit.com/v2/workspace/events/etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0 \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/workspace/events/etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` },
});
const result = await res.json();
```

**Python**

```python
import os, requests

r = requests.delete(
    "https://api.emailit.com/v2/workspace/events/etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
)
result = r.json()
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->delete('workspace/events/etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
]);
$result = json_decode($response->getBody(), true);
```

**200**

```json
{
  "object": "workspace_event",
  "id": "etp_2yHn4Kd8QwE1rT6vBx9LmZ3sPf0",
  "name": "customer.type",
  "type": "w:customer.type",
  "deleted": true
}
```

---
Source: https://emailit.com/docs/api-reference/workspace-events/delete/
