# Members API reference

> The member operations of the Fax for Agents API. Invite a person by email, withdraw an invitation, list the members, change a role and remove a member.

Page: https://faxforagents.com/docs/api/reference/members/
Last changed: 2026-11-13

Updated Nov 13, 2026

6 operations of the Fax for Agents API, from the OpenAPI document version 1.20.0, snapshot of 2026-11-13. The base URL is `https://api.faxforagents.com/v1`. This is one group of the [full reference](https://faxforagents.com/docs/api/reference/).

- An invitation is a link sent by email that works for 7 days.
- Removing a member needs org:admin, which only the owner of the organization holds.
- Changing a member's role needs member:admin and the new role in the body.

## Operations

- `GET /v1/invitations` Open invitations
- `POST /v1/invitations` Invite someone by email (a link that works for 7 days)
- `DELETE /v1/invitations/{invitation_id}` Withdraw an invitation
- `GET /v1/members` The organization's members
- `DELETE /v1/members/{member_id}` Remove a member (owner)
- `PATCH /v1/members/{member_id}` Change a member's role

## How does a person join an organization?

By invitation. `POST /v1/invitations` takes an `email` and a `role`, and mails a link that works for 7 days. The person opens it, signs in with that address and accepts. The accept call is in the [auth group](https://faxforagents.com/docs/api/reference/auth/), and it checks that the signed-in email matches the invited one.

`GET /v1/invitations` lists the open ones with who sent each and when it expires. `DELETE /v1/invitations/{invitation_id}` withdraws one. The link then stops working.

## How are roles changed and members removed?

`GET /v1/members` lists the members with their name, email and role. `PATCH /v1/members/{member_id}` changes a role. The body needs `role`. The schema marks it optional for one reason, stated in its description. A member id of another organization answers 404 before the body is looked at.

`DELETE /v1/members/{member_id}` removes a member. The summary says "owner": the call needs `org:admin`.

## Which scopes do member calls need?

Listing members needs `account:read`. Invitations and role changes need `member:admin`. Removal needs `org:admin`. An agent key is never issued `member:admin` or `org:admin`, so an agent cannot invite anyone or change who belongs.

A role limits what a person can do in the dashboard and what that person can grant to a connected app. The organization itself, its name and its data requests, is in the [organizations group](https://faxforagents.com/docs/api/reference/organizations/).

## Each operation in detail

### GET `/v1/invitations`

Open invitations

Credential: an API key or a signed-in session. Scope: `member:admin`.

#### Responses

GET /v1/invitations responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

GET /v1/invitations response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array of object Invitation | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/invitations \ -H "Authorization: Bearer ffa_test_..."`
```

### POST `/v1/invitations`

Invite someone by email (a link that works for 7 days)

Credential: an API key or a signed-in session. Scope: `member:admin`.

#### Parameters

POST /v1/invitations parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Request body application/json, required

POST /v1/invitations request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `email` | string (email) | yes |  |
| `role` | string (owner, admin, member, viewer) | no |  |

#### Responses

POST /v1/invitations responses

| Status | Meaning |
| --- | --- |
| `201` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/invitations response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `accepted_at` | string or null | yes |  |
| `created_at` | string | yes |  |
| `email` | string | yes |  |
| `expires_at` | string | yes |  |
| `id` | string | yes |  |
| `invited_by` | string | yes |  |
| `role` | string (owner, admin, member, viewer) | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/invitations \ -X POST \ -H "Authorization: Bearer ffa_test_..." \ -H "Content-Type: application/json" \ -d '{"email":"reader@example.com"}'`
```

### DELETE `/v1/invitations/{invitation_id}`

Withdraw an invitation

Credential: an API key or a signed-in session. Scope: `member:admin`.

#### Parameters

DELETE /v1/invitations/{invitation_id} parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `invitation_id` | path | string | yes |  |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Responses

DELETE /v1/invitations/{invitation_id} responses

| Status | Meaning |
| --- | --- |
| `204` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/invitations/INVITATION_ID \ -X DELETE \ -H "Authorization: Bearer ffa_test_..."`
```

### GET `/v1/members`

The organization's members

Credential: an API key or a signed-in session. Scope: `account:read`.

#### Responses

GET /v1/members responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

GET /v1/members response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array of object Member | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/members \ -H "Authorization: Bearer ffa_test_..."`
```

### DELETE `/v1/members/{member_id}`

Remove a member (owner)

Credential: an API key or a signed-in session. Scope: `org:admin`.

#### Parameters

DELETE /v1/members/{member_id} parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `member_id` | path | string | yes |  |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Responses

DELETE /v1/members/{member_id} responses

| Status | Meaning |
| --- | --- |
| `204` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/members/MEMBER_ID \ -X DELETE \ -H "Authorization: Bearer ffa_test_..."`
```

### PATCH `/v1/members/{member_id}`

Change a member's role

Credential: an API key or a signed-in session. Scope: `member:admin`.

#### Parameters

PATCH /v1/members/{member_id} parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `member_id` | path | string | yes |  |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Request body application/json, required

PATCH /v1/members/{member_id} request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `role` | string (owner, admin, member, viewer) or null | no | Required. Optional in the schema so a foreign id is a 404 first. |

#### Responses

PATCH /v1/members/{member_id} responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

PATCH /v1/members/{member_id} response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `created_at` | string | yes |  |
| `email` | string | yes |  |
| `id` | string | yes |  |
| `name` | string or null | yes |  |
| `role` | string (owner, admin, member, viewer) | yes |  |
| `user_id` | string or null | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/members/MEMBER_ID \ -X PATCH \ -H "Authorization: Bearer ffa_test_..." \ -H "Content-Type: application/json" \ -d '{}'`
```
