# Project calls

See the [OpenAPI document](/openapi.json) for schemas and operation IDs.

## Prerequisites

- Protected operations require an API key in `x-api-key` or a browser session cookie; some actions require a verified user session
- Tenant-scoped operations use `X-Organization-Id`; browser sessions can use their active workspace. Discovery and personal-workspace bootstrap do not require an active workspace
- The base URL for your deployment, `https://server.hlix.ai` by default

## Operations

| Method | Path | Operation |
| --- | --- | --- |
| `POST` | `/v1/api/projects/{projectId}/call` | [Join the project's call](#join-the-projects-call) |
| `PUT` | `/v1/api/projects/{projectId}/call/{participantId}` | [Keep the caller's place in the project's call](#keep-the-callers-place-in-the-projects-call) |
| `POST` | `/v1/api/projects/{projectId}/call/{participantId}/leave` | [Leave the project's call](#leave-the-projects-call) |

## Join the project's call

`POST /v1/api/projects/{projectId}/call` · operation ID `joinProjectCall`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `projectId` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |
| `X-Client-Portal` | header | no | string | The agency Workspace ID for a signed-in client's portal requests. A verified user session and portal membership are required; API keys cannot authenticate portal access. This header does not grant agency administration access. |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `201` | ProjectCallJoin | The caller's place in the call, started when nobody was in it. Send a heartbeat every 30 seconds; two minutes without one ends the place. Call time is metered per participant minute. |
| `400` | ApiError | The request named no active organization. |
| `401` | ApiError | No valid session or API key. |
| `402` | ApiError | The workspace has no credit left for new spend. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `404` | ApiError | No such project in this workspace — or the caller is a client collaborator with no grant on it. |
| `502` | ApiError | The call could not start. |
| `503` | ApiError | Calls are not available on this deployment. |

## Keep the caller's place in the project's call

`PUT /v1/api/projects/{projectId}/call/{participantId}` · operation ID `heartbeatProjectCall`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `projectId` | path | **yes** | string |  |
| `participantId` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |
| `X-Client-Portal` | header | no | string | The agency Workspace ID for a signed-in client's portal requests. A verified user session and portal membership are required; API keys cannot authenticate portal access. This header does not grant agency administration access. |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `200` | ProjectCallState | Still in the call. |
| `400` | ApiError | The request named no active organization. |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `404` | ApiError | No such project in this workspace — or the caller is a client collaborator with no grant on it. |
| `410` | ApiError | The place was closed: the caller left or was silent too long. Join again. |

## Leave the project's call

`POST /v1/api/projects/{projectId}/call/{participantId}/leave` · operation ID `leaveProjectCall`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `projectId` | path | **yes** | string |  |
| `participantId` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |
| `X-Client-Portal` | header | no | string | The agency Workspace ID for a signed-in client's portal requests. A verified user session and portal membership are required; API keys cannot authenticate portal access. This header does not grant agency administration access. |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `200` | ProjectCallState | The place is closed and its call token revoked. Leaving twice is not an error. |
| `400` | ApiError | The request named no active organization. |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `404` | ApiError | No such project in this workspace — or the caller is a client collaborator with no grant on it. |

## If a request fails

The response table for each operation lists its documented errors. Common status codes include:

- `400` — the body failed schema validation, or the request named no active organization. A `ValidationError` body carries the failing fields; an `ApiError` body carries only `error`.
- `401` — no valid session or API key.
- `403` — authenticated, but not a member of the named organization, or a client collaborator without the required access.
- `404` — check the resource ID and your access to the selected Workspace.
- `409` — the expected revision or state is stale, or another operation currently owns the transition.
- `500` — the operation failed server-side. Retry only where an idempotency key makes that safe.

## Next steps

[API reference](/api/reference/)
  [API & OpenAPI](/api/openapi/)
  [TypeScript SDK](/sdk/typescript/)
  [CLI reference](/reference/cli/)