> For the complete documentation index, see [llms.txt](https://help.getmobly.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.getmobly.com/documentation/rest-api/rest-api-v0.md).

# REST API v0

This document describes the **Mobly REST API (version v0)**.

All endpoints are:

* **JSON-based**
* **Authenticated via API Key**
* **Versioned under `/v0`**

***

## Base URL

All requests should be made relative to the following base URL:

<https://core-api.getmobly.com/api/v0>

## Authentication

All requests must include a valid API key. You can request an API key by contacting customer support.

### API Key Header

Send your API key using the `x-api-key` header:

```http
x-api-key: YOUR_API_KEY_HERE
```

### Example Request

```http
GET /api/v0/events?limit=20&offset=0 HTTP/1.1
Host: core-api.mobly.com
Accept: application/json
x-api-key: abcd123
```

### Authentication Errors

| Condition       | Status | Description                            |
| --------------- | ------ | -------------------------------------- |
| Missing API key | 401    | `Unauthorized` – API key not provided. |
| Invalid API key | 403    | `Forbidden` – API key header invalid.  |

Error responses follow this structure:

```json
{
  "status": 403,
  "error": "Forbidden"
}
```

***

## Response Format

All successful endpoints return results in a consistent wrapper format.

### Single-Resource Endpoints

```jsonc
{
  "status": 200,
  "results": {
    /* single resource object */
  },
}
```

* `status`: HTTP status code.
* `results`: Single object for the specific resource (e.g. `event`, `lead`).

### Array-Resource Endpoints (Paginated)

```jsonc
{
  "status": 200,
  "pagination": {
    "limit": 20,
    "offset": 0,
  },
  "results": {
    "<resource>": [
      /* array of resource objects */
    ],
    "total": 123,
  },
}
```

* `status`: HTTP status code.
* `pagination.limit`: number of items returned in this page.
* `pagination.offset`: zero-based *page* index.
* `results.<resource>`: an array for the specific resource (e.g. `events`, `leads`).
* `results.total`: total number of records matching the query for the organization.

If a resource cannot be found, a `404` is returned:

```json
{
  "status": 404,
  "error": "Not Found"
}
```

***

## Pagination Parameters

List endpoints support the following query parameters:

| Name   | Type   | Default | Max | Description                                    |
| ------ | ------ | ------- | --- | ---------------------------------------------- |
| limit  | number | `20`    | 50  | Page size. Values greater than 50 are clamped. |
| offset | number | `0`     | —   | Zero-based page index (`0` = first page).      |

Example:

```http
GET /api/v0/leads?limit=25&offset=2
```

Returns up to 25 leads, for the **third** page of results.

***

## Rate Limiting

Mobly API requests are rate-limited to ensure fair usage and to protect system performance. Rate limits apply **per API key** using a token bucket model with two key properties:

* **Burst Capacity (`maxTokens`)** – the maximum number of requests that can be made at once
* **Refill Rate (`refillRate`)** – how many requests are added back to the bucket over time

Each incoming request consumes **1 token**. If no tokens are available, the API returns **HTTP 429 – Too Many Requests**.

Clients can track their usage in real time using the rate-limit headers returned on every response.

### How the Token Bucket Works

Every API key has:

* `maxTokens` – maximum number of allowed burst requests
* `refillRate` – tokens added per second
* `tokensRemaining` – current number of tokens in the bucket
* `retryAt` – timestamp when the next token will be available if the bucket is empty

**Example:**

Given the default usage rates:

maxTokens = 20 refillRate = 1 token/second

Then:

* You can make **up to 20 requests instantly** (burst)
* You can sustain **1 request per second** indefinitely
* If you exceed the limit, you must wait until a token becomes available

### Rate Limit Headers

The following headers are included on **all successful responses** and **all 429 responses**:

| Header                    | Description                                                 |
| ------------------------- | ----------------------------------------------------------- |
| **X-RateLimit-Limit**     | The maximum burst capacity (`maxTokens`) for the API key.   |
| **X-RateLimit-Remaining** | How many tokens remain *after* this request\*.              |
| **X-RateLimit-Reset**     | Unix timestamp (seconds) when the bucket will fully refill. |
| **Retry-After**           | *(Only on 429)* Number of seconds to wait before retrying.  |

***

## Endpoint Summary

All available endpoints in **v0**:

* `GET /events`
* `GET /events/:eventId`
* `POST /events`
* `PUT /events/:eventId`
* `DELETE /events/:eventId`
* `GET /events/:eventId/leads`
* `PUT /events/:eventId/leads`
* `DELETE /events/:eventId/leads/:leadId`
* `GET /events/:eventId/users`
* `GET /leads`
* `GET /leads/:leadId`
* `POST /leads`
* `PATCH /leads/:leadId`
* `DELETE /leads/:leadId`
* `GET /leadActivityEvents`
* `GET /leadActivityEvents/:leadActivityEventId`
* `GET /activations`
* `GET /activations/:activationId`
* `GET /tagGroups`
* `GET /tagGroups/:tagGroupId`
* `GET /industryEvents`
* `GET /industryEvents/bookmarks`
* `GET /industryEvents/:industryEventId`
* `POST /industryEvents`
* `PUT /industryEvents/:industryEventId`
* `POST /industryEvents/:industryEventId/bookmark`
* `DELETE /industryEvents/:industryEventId/bookmark`

***

## Events

### GET `/events`

List events for the authenticated organization.

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 10, "offset": 1 },
  "results": {
    "events": [
      {
        "id": 123,
        "name": "Mobly Live Demo",
        "type": "CONFERENCE",
        "registrationEnabled": true,
        "createdAt": "2025-11-17T19:23:45.000Z",
        "startDate": "2025-11-20",
        "endDate": "2025-11-21",
        "location": {
          "streetAddress": "123 Main St",
          "city": "Salt Lake City",
          "state": "UT",
          "zip": "84101",
          "country": "US",
          "latitude": "40.7608",
          "longitude": "-111.8910",
          "timeZone": "America/Denver",
        },
        "tagGroups": [
          "262dc028-1426-498a-943c-e0c1dbd664c1",
          "171de7g4-2675-4d27-8297-5403a96b493d",
        ],
      },
    ],
    "total": 11,
  },
}
```

#### `EventV0Response`

```ts
type EventV0Response = {
  id: number;
  name: string;
  type: EventType;
  registrationEnabled: boolean;
  createdAt: string;
  startDate: string | null;
  endDate: string | null;
  location: {
    streetAddress: string | null;
    city: string | null;
    state: string | null;
    zip: string | null;
    country: string | null;
    latitude: string | null;
    longitude: string | null;
    timeZone: string | null;
  } | null;
  tagGroups: string[];
};
```

> **Note:** `EventType` is a string enum (e.g. `CONFERENCE`, `TRADE_SHOW`, `EVENT`, `SIDECAR`, `DINNER_MEAL`, `HAPPY_HOUR`, `OTHER`).

> **Note:** `startDate` & `endDate` are formatted as an ISO 8601 date, e.g. "2025-11-21"

***

### GET `/events/:eventId`

Fetch a single event by ID.

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |

**Example**

```http
GET /api/v0/events/123
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* EventV0Response */
  },
}
```

***

### POST `/events`

Create an event for the authenticated organization.

**Body Payload**

```ts
type EventCreateV0Input = {
  eventName: string;
  eventType: EventType;
  startDate: string; // ISO 8601 date, e.g. "2025-11-20"
  endDate: string; // ISO 8601 date, e.g. "2025-11-21"
  createdByEmail: string;
  registrationEnabled?: boolean;
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* EventV0Response */
  },
}
```

***

### PUT `/events/:eventId`

Update an event for the authenticated organization.

> **Important:** This endpoint updates the full event record.

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |

**Body Payload**

```ts
type EventUpdateV0Input = {
  eventName: string;
  eventType: EventType;
  startDate: string; // ISO 8601 date, e.g. "2025-11-20"
  endDate: string; // ISO 8601 date, e.g. "2025-11-21"
  registrationEnabled?: boolean;
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* EventV0Response */
  },
}
```

***

### DELETE `/events/:eventId`

Delete an event for the authenticated organization.

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |

**Response**

```jsonc
{
  "status": 200,
  "results": {},
}
```

***

### GET `/events/:eventId/leads`

Retrieve the leads associated with a specific event, including their registration and check-in status.

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 20, "offset": 0 },
  "results": {
    "eventLeads": [
      {
        "leadId": "8588613f-669b-4cfe-8aa2-37561a775103",
        "registered": true,
        "checkedIn": false,
      },
    ],
    "total": 1,
  },
}
```

#### `EventLeadV0Response`

```ts
type EventLeadV0Response = {
  leadId: string;
  registered: boolean;
  checkedIn: boolean;
};
```

***

### PUT `/events/:eventId/leads`

Associate existing leads with an event and optionally update their `registered` and `checkedIn` status.

* If a lead is **not yet associated** with the event, a new association is created.
* If the lead **is already associated**, the existing `registered` and `checkedIn` values are **updated**.

If `registered` or `checkedIn` are omitted, they default to `false`.

Note: This endpoint does not remove existing associations. To remove a lead from an event, use:

DELETE /events/:eventId/leads/:leadId

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |

**Body Payload**

```ts
type EventAddLeadsV0Input = {
  eventLeads: {
    leadId: string;
    registered?: boolean;
    checkedIn?: boolean;
  }[];
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    "eventLeads": [
      /* EventLeadV0Response */
    ],
  },
}
```

***

### DELETE `/events/:eventId/leads/:leadId`

Delete a lead's association with an event for the authenticated organization.

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |
| leadId  | string | Lead ID     |

**Response**

```jsonc
{
  "status": 200,
  "results": {},
}
```

***

### GET `/events/:eventId/users`

Retrieve the users assigned to a specific event for the authenticated organization.

**Path Parameters**

| Name    | Type   | Description |
| ------- | ------ | ----------- |
| eventId | number | Event ID    |

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 20, "offset": 0 },
  "results": {
    "users": [
      {
        "id": 42,
        "email": "jane.doe@example.com",
        "firstName": "Jane",
        "lastName": "Doe",
      },
    ],
    "total": 1,
  },
}
```

#### `UserV0Response`

```ts
type UserV0Response = {
  id: number;
  email: string | null;
  firstName: string | null;
  lastName: string | null;
};
```

***

## Leads

### GET `/leads`

List leads for the authenticated organization.

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 10, "offset": 1 },
  "results": {
    "leads": [
      {
        "id": "8588613f-669b-4cfe-8aa2-37561a775103",
        "createdAt": "2025-11-17T19:23:45.000Z",
        "isEnriched": true,
        "firstName": "Zach",
        "lastName": "Barney",
        "email": "zach@getmobly.com",
        "description": "CEO at Mobly",
        "linkedin": "https://www.linkedin.com/in/zachbarney/",
        "facebook": null,
        "twitter": null,
        "jobTitle": "CEO",
        "address": "123 Main St, Salt Lake City, UT",
        "phoneNumbers": {
          "leadProvided": [],
          "moblyProvided": [
            {
              "number": "+1-555-555-0001",
              "type": "MOBILE",
              "preferred": true,
            },
          ],
        },
        "company": {
          "name": "Mobly",
          "industry": "Software",
          "linkedin": "https://www.linkedin.com/company/getmobly",
          "streetAddress": "123 Main St",
          "city": "Salt Lake City",
          "state": "UT",
          "zip": "84101",
          "country": "US",
        },
        "numberOfScans": 3,
        "lastScannedBy": "kristian@getmobly.com",
        "activations": [
          {
            "activationId": "ca6df5fd-1abf-49af-bc72-0eeb45fce2b1",
            "checkedIn": true,
            "registered": true,
          },
        ],
        "tags": [
          {
            "tagOptionId": "46426cc1-2ecc-49dc-aaab-cbb8e0a1bccf",
            "value": "VIP",
          },
        ],
        "leadActivityEvents": ["077fe3bf-31ff-45d4-8a35-0313bd5e4cf2"],
      },
    ],
    "total": 11,
  },
}
```

#### `LeadV0Response`

```ts
type LeadV0Response = {
  id: string;
  createdAt: string;
  isEnriched: boolean;
  firstName: string | null;
  lastName: string | null;
  email: string | null;
  description: string | null;
  linkedin: string | null;
  facebook: string | null;
  twitter: string | null;
  jobTitle: string | null;
  address: string | null;
  phoneNumbers: {
    leadProvided: {
      number: string;
      type: PhoneNumberTypeEnum;
      preferred: boolean;
    }[];
    moblyProvided: {
      number: string;
      type: PhoneNumberTypeEnum;
      preferred: boolean;
    }[];
  };
  company: {
    name: string | null;
    industry: string | null;
    linkedin: string | null;
    streetAddress: string | null;
    city: string | null;
    state: string | null;
    zip: string | null;
    country: string | null;
  };
  numberOfScans: number;
  lastScannedBy: string | null;
  activations: {
    activationId: string;
    checkedIn: boolean;
    registered: boolean;
  }[];
  tags: {
    tagOptionId: string;
    value: string;
  }[];
  leadActivityEvents: string[];
  remoteIds: {
    id: string;
    integrationType: IntegrationType;
  }[];
};
```

> **Note:** `IntegrationType` is a string enum (e.g. `MARKETO`, `HUB_SPOT`, `ZOHO`, `SALES_FORCE`, `PIPE_DRIVE`, `ELOQUA`, `PARDOT`, `WEBHOOK`).

> **Note:** `PhoneNumberTypeEnum` is a string enum (e.g. `MOBILE`, `LANDLINE`, `DIRECT`, `OFFICE`, `HQ`, `UNKNOWN`).

> **Note:** `leadProvided` includes numbers users from your organization have entered whereas `moblyProvided` includes numbers provided by Mobly's data enrichment.

***

### GET `/leads/:leadId`

Fetch a single lead by ID.

**Path Parameters**

| Name   | Type   | Description |
| ------ | ------ | ----------- |
| leadId | string | Lead ID     |

**Example**

```http
GET /api/v0/leads/8588613f-669b-4cfe-8aa2-37561a775103
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* LeadV0Response */
  },
}
```

***

### POST `/leads`

Create a lead for the authenticated organization.

**Body Payload**

```ts
type LeadCreateV0Input = {
  createdByEmail: string;
  firstName: string;
  lastName: string;
  companyName: string;
  email?: string;
  phoneNumbers?: {
    number: string;
    preferred: boolean;
    type: PhoneNumberTypeEnum;
  }[];
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* LeadV0Response */
  },
}
```

### PATCH `/leads/:leadId`

Partially update a lead and its associated persona record.

Only the fields included in the request body are modified. All omitted fields remain unchanged.

This endpoint is designed for incomplete or incremental updates to lead data. Sending all persona fields in the body effectively performs a full update of the lead record.

#### PATCH Semantics

* If a field is **omitted**, it is left unchanged.
* If a field is explicitly set to **`null`**, the corresponding value is cleared (set to `NULL`).

For `phoneNumbers`:

* If `phoneNumbers` is **omitted**, existing phone numbers remain unchanged.
* If `phoneNumbers` is **`null`** or an **empty array `[]`**, all existing phone numbers are removed.
* If `phoneNumbers` is a **non-empty array**, it fully replaces all existing phone numbers.

> `phoneNumbers` is not merged. Always send the complete list of phone numbers you want to retain or omit the field.

For `remoteId`:

* If `remoteId` is **omitted**, existing remote ID's remain unchanged.
* If `remoteId` is included and `id` is set to **`null`**, the remote ID for the provided `integrationType` is cleared.
* If `remoteId` is included and `id` has a value, the remote ID for the provided `integrationType` is created or updated.

**Path Parameters**

| Name   | Type   | Description |
| ------ | ------ | ----------- |
| leadId | string | Lead ID     |

**Body Payload**

```ts
type LeadPatchV0Input = {
  firstName?: string | null;
  lastName?: string | null;
  email?: string | null;
  address?: string | null;
  linkedin?: string | null;
  facebook?: string | null;
  twitter?: string | null;
  profilePicture?: string | null;
  description?: string | null;
  jobTitle?: string | null;
  phoneNumbers?: {
    number: string;
    preferred: boolean;
    type: PhoneNumberTypeEnum;
  }[];
  remoteId?: { id: string | null; integrationType: IntegrationType };
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* LeadV0Response */
  },
}
```

***

### DELETE `/leads/:leadId`

Delete a lead for the authenticated organization.

**Path Parameters**

| Name   | Type   | Description |
| ------ | ------ | ----------- |
| leadId | string | Lead ID     |

**Response**

```jsonc
{
  "status": 200,
  "results": {},
}
```

***

## Lead Activity Events

### GET `/leadActivityEvents`

List lead activity events for the authenticated organization.

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)
* `leadId` – Optional filter to only return results associated with a specific lead
* `eventType` – Optional filter to only return results of a specific type

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 10, "offset": 1 },
  "results": {
    "leadActivityEvents": [
      {
        "id": "077fe3bf-31ff-45d4-8a35-0313bd5e4cf2",
        "createdAt": "2025-11-17T14:57:07.838Z",
        "createdBy": "kristian@getmobly.com",
        "eventType": "CALENDAR",
        "eventNotes": "Booked follow up call",
        "associatedLead": "8588613f-669b-4cfe-8aa2-37561a775103",
        "associatedCampaign": null,
        "associatedEvent": null,
        "associatedActivation": null,
        "associatedTagOption": null,
      },
    ],
    "total": 11,
  },
}
```

#### `LeadActivityEventV0Response`

```ts
type LeadActivityEventV0Response = {
  id: string;
  createdAt: string;
  createdBy: string | null;
  eventType: LeadActivityEventType;
  eventNotes: string | null;
  associatedLead: string;
  associatedCampaign: string | null;
  associatedEvent: number | null;
  associatedActivation: string | null;
  associatedTagOption: string | null;
};
```

> **Note:** `LeadActivityEventType` is a string enum (e.g. `NOTE`, `FACEBOOK`, `LINKEDIN`, `TWITTER`, `CALENDAR`, `PHONE`, `EMAIL`, `SMS`, `CAMPAIGN_ASSOCIATION`, `CSV_UPLOAD`, `MOBLY_API`, `EMAIL_CONTENT`, `SMS_CONTENT`, `OTHER_CONTENT`).

***

### GET `/leadActivityEvents/:leadActivityEventId`

Fetch a single lead activity event by ID.

**Path Parameters**

| Name                | Type   | Description            |
| ------------------- | ------ | ---------------------- |
| leadActivityEventId | string | Lead activity event ID |

**Example**

```http
GET /api/v0/leadActivityEvents/077fe3bf-31ff-45d4-8a35-0313bd5e4cf2
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* LeadActivityEventV0Response */
  },
}
```

***

## Activations

### GET `/activations`

List activations for the organization.

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 10, "offset": 1 },
  "results": {
    "activations": [
      {
        "id": "ca6df5fd-1abf-49af-bc72-0eeb45fce2b1",
        "eventId": 123,
        "name": "Morning Session",
        "createdAt": "2025-11-17T19:23:45.000Z",
        "type": "BREAKFAST",
        "startDate": "2025-11-20",
        "endDate": "2025-11-20",
        "startTime": "09:00:00",
        "endTime": "12:00:00",
        "createdBy": "kristian@getmobly.com",
        "location": {
          "streetAddress": "123 Main St",
          "city": "Salt Lake City",
          "state": "UT",
          "zip": "84101",
          "country": "US",
          "latitude": "40.7608",
          "longitude": "-111.8910",
          "timeZone": "America/Denver",
        },
        "users": ["kristian@example.com", "kris@getmobly.com"],
        "numberOfScans": 57,
      },
    ],
    "total": 11,
  },
}
```

#### `ActivationV0Response`

```ts
type ActivationV0Response = {
  id: string;
  eventId: number;
  name: string;
  createdAt: string;
  type: ActivationType;
  startDate: string;
  endDate: string;
  startTime: string;
  endTime: string;
  createdBy: string | null;
  location: {
    streetAddress: string | null;
    city: string | null;
    state: string | null;
    zip: string | null;
    country: string | null;
    latitude: string | null;
    longitude: string | null;
    timeZone: string | null;
  } | null;
  users: string[];
  numberOfScans: number;
};
```

> **Note:** `ActivationType` is a string enum (e.g. `CONFERENCE`, `TRADE_SHOW`, `EVENT`, `SIDECAR`, `DINNER_MEAL`, `HAPPY_HOUR`, `BREAKFAST`, `LUNCH`, `COFFEE_CHAT`, `RECEPTION`, `SPEAKING_SESSION`, `PANEL_DISCUSSION`, `WORKSHOP`, `DEMO`, `SPORTS_GAME`, `PARTY`, `BOOTH`, `GIVEAWAY`, `NETWORKING_MIXER`, `ONSITE_OFFICE_VISIT`, `OTHER`).

***

### GET `/activations/:activationId`

Fetch a single activation by ID.

**Path Parameters**

| Name         | Type   | Description    |
| ------------ | ------ | -------------- |
| activationId | string | Activation ID. |

**Example**

```http
GET /api/v0/activations/ca6df5fd-1abf-49af-bc72-0eeb45fce2b1
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* ActivationV0Response */
  },
}
```

***

## Tag Groups

### GET `/tagGroups`

List tag groups defined for the organization, including their tag options.

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 10, "offset": 1 },
  "results": {
    "tagGroups": [
      {
        "id": "262dc028-1426-498a-943c-e0c1dbd664c1",
        "name": "Lead Status",
        "status": "PUBLISHED",
        "allowsMultipleSelection": false,
        "displayOrder": 1,
        "usageInstructions": "Select the current status of the lead.",
        "required": true,
        "allEvents": true,
        "tagOptions": [
          {
            "id": "46426cc1-2ecc-49dc-aaab-cbb8e0a1bccf",
            "displayOrder": 1,
            "value": "VIP",
          },
          {
            "id": "c5d8f163-ee0d-424b-af59-4224f4d8456a",
            "displayOrder": 2,
            "value": "Engaged",
          },
        ],
      },
    ],
    "total": 11,
  },
}
```

#### `TagGroupV0Response`

```ts
type TagGroupV0Response = {
  id: string;
  name: string;
  status: TagGroupStatus;
  allowsMultipleSelection: boolean;
  displayOrder: number;
  usageInstructions: string | null;
  required: boolean;
  allEvents: boolean;
  tagOptions: {
    id: string;
    displayOrder: number;
    value: string;
  }[];
};
```

> **Note:** `TagGroupStatus` is a string enum (e.g. `ARCHIVED`, `DRAFT`, `PUBLISHED`).

***

### GET `/tagGroups/:tagGroupId`

Fetch a single tag group by ID.

**Path Parameters**

| Name       | Type   | Description   |
| ---------- | ------ | ------------- |
| tagGroupId | string | Tag group ID. |

**Example**

```http
GET /api/v0/tagGroups/262dc028-1426-498a-943c-e0c1dbd664c1
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    /* TagGroupV0Response */
  },
}
```

***

## Industry Events

Industry events represent trade shows, conferences, and other industry events tracked globally (not scoped to a single organization). Organizations can bookmark industry events to track interest.

### GET `/industryEvents`

List industry events. Supports filtering by URL or searching by keyword.

**Query Parameters**

* `limit` – page size (default 20, maximum 50)
* `offset` – zero-based page index (default 0)
* `eventUrl` – optional; returns only the industry event matching this exact URL
* `q` – optional; full-text search across name, venueCity, venueState, venueCountry, description, keywords, industries, and personas

> **Note:** If `eventUrl` is provided, `q` is ignored. If neither is provided, all industry events are returned (paginated).

**Response**

```jsonc
{
  "status": 200,
  "pagination": { "limit": 20, "offset": 0 },
  "results": {
    "industryEvents": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "createdAt": "2026-01-15T10:00:00.000Z",
        "updatedAt": "2026-01-20T14:30:00.000Z",
        "name": "Dreamforce 2026",
        "startDate": "2026-09-15T00:00:00.000Z",
        "endDate": "2026-09-18T00:00:00.000Z",
        "sourceType": "MANUAL",
        "sourceId": null,
        "eventType": "CONFERENCE",
        "venueCity": "San Francisco",
        "venueState": "CA",
        "venueCountry": "United States",
        "venueName": "Moscone Center",
        "venueFullAddress": "747 Howard St, San Francisco, CA 94103",
        "venueCoordinates": "37.7849,-122.4005",
        "numberOfAttendees": 40000,
        "numberOfExhibitors": 500,
        "attendeeCost": "$1,299 - $2,199",
        "boothCost": "$50,000+",
        "exhibitorIndustries": ["CRM", "Cloud Computing", "AI"],
        "attendeePersonas": ["Sales leaders", "IT decision makers"],
        "keywords": ["salesforce", "CRM", "cloud", "AI"],
        "website": "https://dreamforce.com",
        "description": "Salesforce's annual flagship conference...",
        "eventUrl": "https://www.salesforce.com/dreamforce/",
      },
    ],
    "total": 1,
  },
}
```

#### `IndustryEventV0Response`

```ts
type IndustryEventV0Response = {
  id: string;
  createdAt: string;
  updatedAt: string;
  name: string;
  startDate: string | null;
  endDate: string | null;
  sourceType: string | null;
  sourceId: string | null;
  eventType: string | null;
  venueCity: string | null;
  venueState: string | null;
  venueCountry: string | null;
  venueName: string | null;
  venueFullAddress: string | null;
  venueCoordinates: string | null;
  numberOfAttendees: number | null;
  numberOfExhibitors: number | null;
  attendeeCost: string | null;
  boothCost: string | null;
  exhibitorIndustries: string[] | null;
  attendeePersonas: string[] | null;
  keywords: string[] | null;
  website: string | null;
  description: string | null;
  eventUrl: string | null;
  isBookmarked?: boolean; // only present on single-resource endpoint
};
```

***

### GET `/industryEvents/bookmarks`

List industry events bookmarked by the authenticated organization.

**Response**

```jsonc
{
  "status": 200,
  "results": {
    "industryEvents": [
      /* IndustryEventV0Response */
    ],
  },
}
```

***

### GET `/industryEvents/:industryEventId`

Fetch a single industry event by ID. Includes `isBookmarked` indicating whether the authenticated organization has bookmarked this event.

**Path Parameters**

| Name            | Type   | Description       |
| --------------- | ------ | ----------------- |
| industryEventId | string | Industry event ID |

**Response**

```jsonc
{
  "status": 200,
  "results": {
    "industryEvent": {
      /* IndustryEventV0Response with isBookmarked */
    },
  },
}
```

***

### POST `/industryEvents`

Create an industry event. Includes automatic deduplication:

1. If an industry event with the same `eventUrl` already exists, the existing record is returned (`created: false`).
2. If no URL match but the `name` and `startDate` match an existing record, the new event is still created but `potentialDuplicates` are returned for the caller to review.

**Body Payload**

```ts
type IndustryEventCreateV0Input = {
  name: string;
  startDate?: string | null; // ISO 8601 date-time
  endDate?: string | null; // ISO 8601 date-time
  sourceType?: string | null;
  sourceId?: string | null;
  eventType?: string | null;
  venueCity?: string | null;
  venueState?: string | null;
  venueCountry?: string | null;
  venueName?: string | null;
  venueFullAddress?: string | null;
  venueCoordinates?: string | null;
  numberOfAttendees?: number | null;
  numberOfExhibitors?: number | null;
  attendeeCost?: string | null;
  boothCost?: string | null;
  exhibitorIndustries?: string[] | null;
  attendeePersonas?: string[] | null;
  keywords?: string[] | null;
  website?: string | null;
  description?: string | null;
  eventUrl?: string | null;
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    "industryEvent": {
      /* IndustryEventV0Response */
    },
    "created": true,
    "potentialDuplicates": [
      /* IndustryEventV0Response[] — events with matching name + startDate */
    ],
  },
}
```

***

### PUT `/industryEvents/:industryEventId`

Partially update an industry event. Only the fields included in the request body are modified.

**Path Parameters**

| Name            | Type   | Description       |
| --------------- | ------ | ----------------- |
| industryEventId | string | Industry event ID |

**Body Payload**

```ts
type IndustryEventUpdateV0Input = {
  name?: string;
  startDate?: string | null;
  endDate?: string | null;
  sourceType?: string | null;
  sourceId?: string | null;
  eventType?: string | null;
  venueCity?: string | null;
  venueState?: string | null;
  venueCountry?: string | null;
  venueName?: string | null;
  venueFullAddress?: string | null;
  venueCoordinates?: string | null;
  numberOfAttendees?: number | null;
  numberOfExhibitors?: number | null;
  attendeeCost?: string | null;
  boothCost?: string | null;
  exhibitorIndustries?: string[] | null;
  attendeePersonas?: string[] | null;
  keywords?: string[] | null;
  website?: string | null;
  description?: string | null;
  eventUrl?: string | null;
};
```

**Response**

```jsonc
{
  "status": 200,
  "results": {
    "industryEvent": {
      /* IndustryEventV0Response */
    },
  },
}
```

***

### POST `/industryEvents/:industryEventId/bookmark`

Bookmark an industry event for the authenticated organization.

**Path Parameters**

| Name            | Type   | Description       |
| --------------- | ------ | ----------------- |
| industryEventId | string | Industry event ID |

**Response**

```jsonc
{
  "status": 200,
  "results": { "success": true },
}
```

***

### DELETE `/industryEvents/:industryEventId/bookmark`

Remove an industry event from the authenticated organization's bookmarks.

**Path Parameters**

| Name            | Type   | Description       |
| --------------- | ------ | ----------------- |
| industryEventId | string | Industry event ID |

**Response**

```jsonc
{
  "status": 200,
  "results": { "success": true },
}
```

***

## Error Examples

### 400 Bad Request

```jsonc
{
  "status": 400,
  "error": "Bad Request",
}
```

```jsonc
{
  "status": 400,
  "error": "Missing or invalid '{field}'",
}
```

### 401 Unauthorized

```jsonc
{
  "status": 401,
  "error": "Unauthorized",
}
```

### 403 Forbidden

```jsonc
{
  "status": 403,
  "error": "Forbidden",
}
```

### 404 Not Found

```jsonc
{
  "status": 404,
  "error": "Not Found",
}
```

### 429 Too Many Requests

The response includes:

* `Retry-After` — how many seconds the client should wait
* `X-RateLimit-Reset` — when the bucket will refill

**Guidelines:**

* **Do not retry immediately**
* **Respect the `Retry-After` header\`**
* **Use exponential backoff** for repeated failures

```jsonc
{
  "status": 429,
  "error": "Too Many Requests",
}
```

### 500 Internal Server Error

```jsonc
{
  "status": 500,
  "error": "Internal Server Error",
}
```


---

# 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://help.getmobly.com/documentation/rest-api/rest-api-v0.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.
