# REST API

{% hint style="info" %}
The API is available to all users in the **Enterprise** **plan.** If you're interested in testing the API or trialing Enterprise, reach out to our sales team (<sales@arcade.software>).&#x20;
{% endhint %}

The Arcade API is actively being developed and subject to changes. Only a subset of what’s possible in the app is covered by the API. Let us know which features you want to see on the API first!

## Authentication

### How do I authenticate with the API?

First, generate an **API key**:

1. Go to `Settings > Advanced` in your Arcade team dashboard.
2. Generate a new API key.

Then, include the API key in the `authorization` header of all requests:

```
makefileCopyEditauthorization: YOUR_API_KEY
```

All requests are made to `https://api.arcade.software`.

{% @arcade/embed flowId="Qy6aqygmLgMjdyRvDchT" url="<https://app.arcade.software/share/Qy6aqygmLgMjdyRvDchT>" %}

***

## Creating an Arcade from a Video

This API flow lets you programmatically create an Arcade from a video and a list of interaction events.

***

### Step 1: How do I generate an upload URL?

**Method:** `POST`\
**Endpoint:** `/generate-upload-url`\
**URL:** `https://api.arcade.software/generate-upload-url`

#### Headers:

```http
httpCopyEditauthorization: YOUR_API_KEY
content-type: application/json
```

#### Body:

```json
jsonCopyEdit{
  "contentType": "video/webm"
  // or "video/mp4"
  // or "video/quicktime"
}
```

#### Response:

```json
jsonCopyEdit{
  "success": true,
  "uploadUrl": "https://...",
  "uploadId": "my.company-uuid.webm"
}
```

***

### Step 2: How do I upload the video?

**Method:** `PUT`\
**URL:** Use the `uploadUrl` from Step 1

#### Headers:

```http
httpCopyEditcontent-type: video/webm
```

#### Body:

Binary video file (e.g. `.webm`, `.mp4`, or `.mov`)

***

### Step 3: How do I create the Arcade?

**Method:** `POST`\
**URL:** `https://api.arcade.software/arcades`

#### Headers:

```http
httpCopyEditauthorization: YOUR_API_KEY
content-type: application/json
```

#### Body:

```json
jsonCopyEdit{
  "title": "Title of your Arcade",
  "description": "Optional description",
  "uploadId": "your-uploadId from Step 1",
  "events": [
    {
      "type": "click",
      "timestamp": 2.75,
      "target": {
        "x": 400,
        "y": 300
      },
      "label": "Optional hotspot label"
    },
    {
      "type": "scroll",
      "timestamp": 3
    },
    {
      "type": "click",
      "timestamp": 3.5,
      "target": {
        "x": 650,
        "y": 120
      }
    },
    {
      "type": "type",
      "timestamp": 5
    }
  ]
}
```

#### Notes:

* **Click events** create hotspots.
* **Scroll** and **type** events are used to determine if a video step should be created.
* If there’s no scroll or type between clicks, the step will default to an image.

#### Response:

```json
jsonCopyEdit{
  "success": true,
  "arcadeId": "abc123"
}
```

***

## Replacing an Existing Arcade

### Can I update an existing Arcade with a new video and event list?

Yes. Use the same flow as the creation endpoint, but instead of `POST /arcades`, use a different method and endpoint.

**Method:** `PUT`\
**URL:** `https://api.arcade.software/arcades/:id`\
(Replace `:id` with the ID of the Arcade you're updating)

#### Headers:

```http
httpCopyEditauthorization: YOUR_API_KEY
content-type: application/json
```

#### Body:

Same as the **create Arcade** endpoint:

```json
jsonCopyEdit{
  "title": "Updated Arcade Title",
  "description": "Optional new description",
  "uploadId": "your-new-upload-id",
  "events": [ /* same event format */ ]
}
```

This completely replaces the Arcade’s video and interaction steps with the new content.

***

## Arcade User Provisioning API (Public)

This document describes Arcadeʼs user provisioning endpoints for customers\
who want to manage users and teams programmatically.

### Base URL

**Production**

```
https://api.arcade.software
```

### Authentication

All requests must include your **Arcade API key** in the `Authorization` header.

#### Generate an API Key

1. Go to **Settings → Advanced** in your Workspace.
2. Select **New API key**.
3. Enable **User provisioning** in the modal.

> Enabling this grants the API key the required **provisioning scope** for all endpoints below.

#### Example

```bash
curl -sS \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  https://api.arcade.software/users
```

***

### Requirements & Limits

#### Plan Requirement

* Workspace must be on **Growth** or higher.

#### Rate Limiting

* **100 requests per minute per IP**

***

### Error Responses (Common)

All responses are JSON.

#### 401 Unauthorized

```json
{ "error": "Missing authorization header" }
```

```json
{ "error": "Invalid API key" }
```

```json
{ "error": "Workspace is not growth or above" }
```

#### 403 Forbidden

```json
{ "success": false, "error": "This operation requires provisioning scope" }
```

#### 400 Bad Request

```json
{ "success": false, "errors": [...] }
```

#### 5xx Server Errors

```json
{ "success": false, "error": "..." }
```

***

### Users

#### List Users

Returns all **active users** in the workspace.

**Method**

```
GET /users
```

**Auth**

* API key with provisioning scope

**Example**

```bash
curl -sS \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  https://api.arcade.software/users
```

**Response (200)**

```json
{
  "success": true,
  "users": [
    {
      "id": "USER_ID",
      "email": "user@company.com",
      "name": "User Name",
      "role": "Admin"
    }
  ]
}
```

***

#### Create User (Single)

Creates a user **directly** in the workspace (no invite acceptance required).

**Method**

```
POST /users
```

**Roles Allowed**

* Admin
* Editor
* Collaborator
* Viewer
* BillingUser

**Request Body**

```json
{
  "email": "jane.doe@company.com",
  "name": "Jane Doe",
  "role": "Editor"
}
```

**Example**

```bash
curl -sS \
  -X POST \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"jane.doe@company.com","name":"Jane Doe","role":"Editor"}' \
  https://api.arcade.software/users
```

**Response (201)**

```json
{
  "success": true,
  "user": {
    "id": "USER_ID",
    "email": "jane.doe@company.com",
    "name": "Jane Doe",
    "role": "Editor",
    "status": "Active"
  }
}
```

**Notes**

* If the user already exists, the request fails with **409 Conflict**:

  ```
  User already exists in workspace
  ```

***

#### Create Users (Bulk)

Creates multiple users in a single request. Each user is processed independently.

**Method**

```
POST /users
```

**Request Body**

```json
[
  { "email": "a@company.com", "name": "A", "role": "Admin" },
  { "email": "b@company.com", "name": "B", "role": "Viewer" }
]
```

**Example**

```bash
curl -sS \
  -X POST \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"email":"a@company.com","name":"A","role":"Admin"},{"email":"b@company.com","name":"B","role":"Viewer"}]' \
  https://api.arcade.software/users
```

**Response (201)**

```json
{
  "success": true,
  "users": [
    {
      "id": "USER_ID_A",
      "email": "a@company.com",
      "name": "A",
      "role": "Admin",
      "status": "Active"
    },
    {
      "id": "USER_ID_B",
      "email": "b@company.com",
      "name": "B",
      "role": "Viewer",
      "status": "Active"
    }
  ]
}
```

**Notes**

* Duplicate emails **within the same request** return:

  ```json
  { "status": "error", "error": "Duplicate email in request" }
  ```
* Partial failures return `success: false` with per-user errors.

***

#### Delete Users (Bulk)

Deactivates one or more users.

**Method**

```
DELETE /users
```

Users may be identified by **user IDs**, **emails**, or both.

**Delete by User ID**

```bash
curl -sS \
  -X DELETE \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"userIds":["USER_ID_1","USER_ID_2"]}' \
  https://api.arcade.software/users
```

**Delete by Email**

```bash
curl -sS \
  -X DELETE \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails":["a@company.com","b@company.com"]}' \
  https://api.arcade.software/users
```

**Response (200)**

```json
{
  "success": true,
  "deleted": 2
}
```

**Notes**

* Deleting the **workspace Owner** is not allowed.
* Partial failures return an `errors` array:

```json
{
  "success": false,
  "deleted": 1,
  "errors": [
    {
      "identifier": "b@company.com",
      "error": "Active user not found"
    }
  ]
}
```

***

### Teams

#### List Teams

Returns all active teams and their active members.

**Method**

```
GET /teams
```

**Example**

```bash
curl -sS \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  https://api.arcade.software/teams
```

**Response (200)**

```json
{
  "success": true,
  "teams": [
    {
      "id": "TEAM_ID",
      "slug": "engineering",
      "name": "Engineering",
      "members": [
        {
          "id": "USER_ID",
          "email": "user@company.com",
          "name": "User Name",
          "type": "Editor"
        }
      ]
    }
  ]
}
```

***

#### Update Team Members (Replace List)

Replaces the team’s entire member list.

> ⚠️ Any existing members **not included** in the new list will be **removed from the team**.

**Method**

```
PATCH /teams/:id/members
```

**Member Types Allowed**

* Admin
* Editor
* Collaborator
* Viewer

**Request Body**

```json
{
  "members": [
    { "userId": "USER_ID_1", "type": "Admin" },
    { "userId": "USER_ID_2", "type": "Viewer" }
  ]
}
```

**Example**

```bash
curl -sS \
  -X PATCH \
  -H "Authorization: YOUR_ARCADE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"members":[{"userId":"USER_ID_1","type":"Admin"},{"userId":"USER_ID_2","type":"Viewer"}]}' \
  https://api.arcade.software/teams/TEAM_ID/members
```

**Response (200)**

```json
{
  "success": true,
  "memberCount": 2
}
```

**Notes**

* Each `userId` must already be an **active workspace member**.
* Errors:
  * `400` – invalid or inactive user
  * `404` – team not found
  * `403` – team belongs to another workspace
