> ## Documentation Index
> Fetch the complete documentation index at: https://docs.answeringagent.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Organizations

> Manage customer organizations using the organization-first creation flow.

## Overview

Organizations represent your customers' businesses in Answering Agent. They can be provisioned by your partner account or independently owned and linked to it. Linked organizations remain customer-owned and default-deny for partner writes.

<Note>
  Use the **organization-first flow** to onboard customers: Create the organization and owner user in a single API call, then add locations and additional users as needed.
</Note>

***

## Data Hierarchy

Understanding how organizations fit into the Answering Agent structure:

```
Your Partner Account
  │
  ├─ Organization (Customer Business)
  │   ├─ Owner User (created with org)
  │   ├─ Additional Users (team members)
  │   └─ Locations (phone numbers)
  │       └─ AI Agents (handle calls)
  │
  └─ More Organizations...
```

**Key Points:**

* Organizations must have at least one **owner** user
* Owners are created automatically when you create an organization
* Users are identified by your system's `external_id` for easy mapping
* Locations (phone numbers) belong to organizations
* All data is scoped to your partner account - you only see provisioned organizations and organizations visible through an accepted partner link
* `partner_type` identifies `provisioned` vs `linked` organizations
* `permissions.can_manage_dashboard_viewers` tells you whether a linked organization's owner/admin approved viewer management

***

## Base URL

`https://answeringagent.com/api/v1`

All requests must include the **X-API-KEY** header containing a valid API key.

<Note>
  This is the Partner API. It accepts keys from reseller accounts only. A regular team's key gets `401`. To read your own team's conversations, tasks, contacts, and reports, use the [Customer API](/api/overview).
</Note>

***

## Endpoints

| Method & Endpoint | Capability |
| - | - |
| `GET /organizations` | List all your customer organizations |
| `POST /organizations` | Create organization with owner |
| `GET /organizations/{organization_id}` | Get organization details |
| `PATCH /organizations/{organization_id}` | Update organization |
| `DELETE /organizations/{organization_id}` | Delete organization |
| `PUT /organizations/{organization_id}/dashboard-viewers/{external_id}` | Attach one read-only viewer to an approved linked organization |
| `DELETE /organizations/{organization_id}/dashboard-viewers/{external_id}` | Detach one viewer without deleting the identity |

***

## 1. List Organizations

| Property | Value |
| - | - |
| **Method** | `GET` |
| **Endpoint** | `/organizations` |
| **Success** | `200 OK` |

List all organizations for the authenticated reseller.

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-API-KEY: <your-api-key>" \
       https://answeringagent.com/api/v1/organizations
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations', {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const organizations = await res.json();
  ```
</CodeGroup>

#### Success Response

```json theme={null}
200 OK
[
  {
    "id": 123,
    "name": "Acme Corporation",
    "partner_type": "provisioned",
    "permissions": {
      "can_view_dashboard": true,
      "can_manage_dashboard_viewers": true
    },
    "created_at": "2025-05-14T10:30:00Z",
    "updated_at": "2025-05-14T10:30:00Z",
    "users": [
      {
        "id": 456,
        "external_id": "user_123",
        "name": "John Doe",
        "email": "john@acme.com"
      }
    ],
    "phone_numbers": [
      {
        "id": 789,
        "name": "Main Office",
        "phone_number": "+13035551234",
        "status": "active"
      }
    ]
  }
]
```

***

## 2. Create Organization

| Property | Value |
| - | - |
| **Method** | `POST` |
| **Endpoint** | `/organizations` |
| **Success** | `201 Created` |

Create a new organization with an owner. This is the **recommended way** to onboard new customers as it creates both the organization and owner user in a single operation.

### Request Fields

| Field | Type | Required | Notes |
| - | - | - | - |
| `name` | string | ✔︎ | Organization name |
| `description` | string | – | Optional organization description |
| `owner` | object | ✔︎ | Owner user details |
| `owner.external_id` | string | ✔︎ | Your unique identifier for the owner user |
| `owner.email` | string | ✔︎ | Owner's email address |
| `owner.name` | string | – | Owner's display name |

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST -H "X-API-KEY: <your-api-key>" \
       -H "Content-Type: application/json" \
       -d '{
             "name": "Acme Corporation",
             "description": "A technology company specializing in innovative solutions",
             "owner": {
               "external_id": "user_123",
               "email": "john@acme.com",
               "name": "John Doe"
             }
           }' \
       https://answeringagent.com/api/v1/organizations
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations', {
    method: 'POST',
    headers: {
      'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: 'Acme Corporation',
      description: 'A technology company specializing in innovative solutions',
      owner: { external_id: 'user_123', email: 'john@acme.com', name: 'John Doe' },
    }),
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const { organization, owner } = await res.json();
  ```
</CodeGroup>

#### Success Response

```json theme={null}
201 Created
{
  "organization": {
    "id": 123,
    "name": "Acme Corporation",
    "created_at": "2025-05-14T10:30:00Z",
    "updated_at": "2025-05-14T10:30:00Z"
  },
  "owner": {
    "id": 456,
    "external_id": "user_123",
    "name": "John Doe",
    "email": "john@acme.com",
    "created_at": "2025-05-14T10:30:00Z",
    "updated_at": "2025-05-14T10:30:00Z"
  }
}
```

<Note>
  The owner user is automatically created and assigned full access to manage the organization. They can add team members, configure locations, and manage all settings.
</Note>

***

## 3. Get Organization

| Property | Value |
| - | - |
| **Method** | `GET` |
| **Endpoint** | `/organizations/{organization_id}` |
| **Success** | `200 OK` |

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-API-KEY: <your-api-key>" \
       https://answeringagent.com/api/v1/organizations/123
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations/123', {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const organization = await res.json();
  ```
</CodeGroup>

#### Success Response

```json theme={null}
200 OK
{
  "id": 123,
  "name": "Acme Corporation",
  "created_at": "2025-05-14T10:30:00Z",
  "updated_at": "2025-05-14T10:30:00Z",
  "users": [
    {
      "id": 456,
      "external_id": "user_123",
      "name": "John Doe",
      "email": "john@acme.com"
    }
  ],
  "phone_numbers": [
    {
      "id": 789,
      "name": "Main Office",
      "phone_number": "+13035551234",
      "status": "active"
    }
  ]
}
```

***

## 4. Update Organization

| Property | Value |
| - | - |
| **Method** | `PATCH` |
| **Endpoint** | `/organizations/{organization_id}` |
| **Success** | `200 OK` |

### Request Fields

| Field | Type | Required | Notes |
| - | - | - | - |
| `name` | string | – | Updated organization name |
| `description` | string | – | Updated organization description |

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH -H "X-API-KEY: <your-api-key>" \
       -H "Content-Type: application/json" \
       -d '{
             "name": "Acme Corp",
             "description": "Updated description"
           }' \
       https://answeringagent.com/api/v1/organizations/123
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations/123', {
    method: 'PATCH',
    headers: {
      'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ name: 'Acme Corp', description: 'Updated description' }),
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const organization = await res.json();
  ```
</CodeGroup>

#### Success Response

```json theme={null}
200 OK
{
  "id": 123,
  "name": "Acme Corp",
  "created_at": "2025-05-14T10:30:00Z",
  "updated_at": "2025-05-14T11:15:00Z"
}
```

***

## 5. Delete Organization

| Property | Value |
| - | - |
| **Method** | `DELETE` |
| **Endpoint** | `/organizations/{organization_id}` |
| **Success** | `200 OK` |

<Warning>
  Organizations can only be deleted if they have no users. Remove all users from the organization before attempting to delete it.
</Warning>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE -H "X-API-KEY: <your-api-key>" \
       https://answeringagent.com/api/v1/organizations/123
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations/123', {
    method: 'DELETE',
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const { message } = await res.json();
  ```
</CodeGroup>

#### Success Response

```json theme={null}
200 OK
{
  "message": "Organization deleted successfully"
}
```

***

## Organization-First Workflow

The recommended workflow for onboarding new customers:

1. **Create Organization**: Use `POST /organizations` with owner details
2. **Add Additional Users**: Use `POST /users?organization_id={id}` for additional team members
3. **Create Locations**: Use `POST /locations?organization_id={id}` for phone numbers
4. **Generate Embed Token**: Use `GET /users/{external_id}/embed-token` for dashboard access

### Complete Example

<CodeGroup>
  ```bash cURL theme={null}
  # 1. Create organization with owner
  curl -X POST -H "X-API-KEY: <your-api-key>" \
       -H "Content-Type: application/json" \
       -d '{
             "name": "Pizza Palace",
             "owner": {
               "external_id": "owner_456",
               "email": "manager@pizzapalace.com",
               "name": "Maria Rodriguez"
             }
           }' \
       https://answeringagent.com/api/v1/organizations

  # 2. Add additional user to organization
  curl -X POST -H "X-API-KEY: <your-api-key>" \
       -H "Content-Type: application/json" \
       -d '{
             "external_id": "staff_789",
             "email": "staff@pizzapalace.com",
             "name": "John Smith"
           }' \
       "https://answeringagent.com/api/v1/users?organization_id=123"

  # 3. Create location for organization
  curl -X POST -H "X-API-KEY: <your-api-key>" \
       -H "Content-Type: application/json" \
       -d '{
             "name": "Main Location",
             "address": "123 Pizza St, Denver, CO",
             "area_code": "303"
           }' \
       "https://answeringagent.com/api/v1/locations?organization_id=123"

  # 4. Get embed token for dashboard access
  curl -H "X-API-KEY: <your-api-key>" \
       https://answeringagent.com/api/v1/users/owner_456/embed-token
  ```

  ```javascript JavaScript theme={null}
  // 1. Create organization with owner
  const orgRes = await fetch('https://answeringagent.com/api/v1/organizations', {
    method: 'POST',
    headers: {
      'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: 'Pizza Palace',
      owner: {
        external_id: 'owner_456',
        email: 'manager@pizzapalace.com',
        name: 'Maria Rodriguez',
      },
    }),
  });
  if (!orgRes.ok) throw new Error(`${orgRes.status}: ${await orgRes.text()}`);
  const { organization, owner } = await orgRes.json();

  // 2. Add additional user to organization
  const userRes = await fetch('https://answeringagent.com/api/v1/users?organization_id=123', {
    method: 'POST',
    headers: {
      'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      external_id: 'staff_789',
      email: 'staff@pizzapalace.com',
      name: 'John Smith',
    }),
  });
  if (!userRes.ok) throw new Error(`${userRes.status}: ${await userRes.text()}`);
  const staff = await userRes.json();

  // 3. Create location for organization
  const locationRes = await fetch('https://answeringagent.com/api/v1/locations?organization_id=123', {
    method: 'POST',
    headers: {
      'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: 'Main Location',
      address: '123 Pizza St, Denver, CO',
      area_code: '303',
    }),
  });
  if (!locationRes.ok) throw new Error(`${locationRes.status}: ${await locationRes.text()}`);
  const location = await locationRes.json();

  // 4. Get embed token for dashboard access
  const tokenRes = await fetch('https://answeringagent.com/api/v1/users/owner_456/embed-token', {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!tokenRes.ok) throw new Error(`${tokenRes.status}: ${await tokenRes.text()}`);
  const { embed_token } = await tokenRes.json();
  ```
</CodeGroup>

***

## Owner-Linked Organization Workflow

Use this flow when the customer already owns their Answering Agent organization and your account managers need approved, read-only embedded dashboard access.

### 1. Confirm visibility and permission

After the customer owner accepts the partner link, list or fetch the organization:

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-API-KEY: <your-api-key>" \
    https://answeringagent.com/api/v1/organizations/456
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations/456', {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const organization = await res.json();
  ```
</CodeGroup>

```json theme={null}
{
  "id": 456,
  "name": "Customer-Owned Wash Group",
  "partner_type": "linked",
  "permissions": {
    "can_view_dashboard": true,
    "can_manage_dashboard_viewers": true
  }
}
```

If `can_manage_dashboard_viewers` is `false`, the organization owner or an admin must enable it in Answering Agent before your API can attach viewers. The partner API cannot self-approve this grant.

### 2. Attach an existing partner identity

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT -H "X-API-KEY: <your-api-key>" \
    https://answeringagent.com/api/v1/organizations/456/dashboard-viewers/account-manager-42
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations/456/dashboard-viewers/account-manager-42', {
    method: 'PUT',
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const user = await res.json();
  ```
</CodeGroup>

The `external_id` must identify a user provisioned by your partner account. A successful response shows organization `456` in that user's `organizations` array with role `user`. The same identity can be attached independently to other approved linked organizations.

### 3. Request an organization-scoped token

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-API-KEY: <your-api-key>" \
    "https://answeringagent.com/api/v1/users/account-manager-42/embed-token?organization_id=456"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/users/account-manager-42/embed-token?organization_id=456', {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const { embed_token } = await res.json();
  ```
</CodeGroup>

Pass the returned compact token to a `/dashboard/embed` iframe. It authorizes read-only access to all current and future locations in organization `456`, never to another organization.

### 4. Detach without deleting the identity

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE -H "X-API-KEY: <your-api-key>" \
    https://answeringagent.com/api/v1/organizations/456/dashboard-viewers/account-manager-42
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/organizations/456/dashboard-viewers/account-manager-42', {
    method: 'DELETE',
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  ```
</CodeGroup>

This returns `204 No Content`, invalidates stale scoped authority for organization `456`, and preserves the identity and its other organization relationships.

<Warning>
  Disabling or revoking the grant, revoking the partner link, removing the team membership, or deleting the user also revokes scoped authority. Re-enabling a grant does not silently restore viewers; attach each viewer again and issue a fresh token.
</Warning>

***

## Error Codes

| Code | Meaning | Typical Cause |
| - | - | - |
| 401 | Unauthorized | Missing or invalid `X-API-KEY` |
| 404 | Not Found | Organization not found |
| 422 | Validation Error | Missing required fields or duplicate email |
| 500 | Internal Server Error | Unexpected error during creation |

***

## Benefits of Organization-First Flow

* **Single API Call**: Create both organization and owner in one request
* **Atomic Operations**: Either both are created successfully or neither
* **Simplified Onboarding**: Fewer API calls needed for customer setup
* **Automatic Relationships**: Owner is automatically linked to organization
* **Better Data Consistency**: Reduces chance of orphaned records


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.