# Memberships

Manage organisation memberships under your partner account.

This endpoint set is **partner-level only**. Organisation API keys cannot access these endpoints.

**Base URL:** `https://api.chargebackstop.com/v1/memberships/`\
**Authentication:** Bearer token via API key.

Required abilities:

* `memberships:read` for GET endpoints
* `memberships:write` for POST, PATCH, and DELETE endpoints

Access scope model:

* Admin partner-group keys can access memberships across all organisations belonging to their partner.
* Non-admin partner-group keys can access memberships only in organisations explicitly assigned to their group.
* Organisation-level keys receive `401 Unauthorised` on all endpoints in this API.

***

## GET /v1/memberships - List memberships

Returns memberships accessible to the authenticated partner-group API key.

**API level:** Partner-level only\
**Authentication:** `memberships:read`

### Query parameters

| Parameter         | Type    | Description                     |
| ----------------- | ------- | ------------------------------- |
| `organisation_id` | string  | Filter by exact organisation ID |
| `limit`           | integer | Number of results per page      |
| `offset`          | integer | Number of results to skip       |

{% hint style="info" %}
Results are ordered by `created_at` descending.
{% endhint %}

### Example request

```bash
curl -X GET "https://api.chargebackstop.com/v1/memberships/?organisation_id=org_xyz456&limit=20&offset=0" \
  -H "Authorization: Bearer <api_key>"
```

### Example response

```json
{
  "items": [
    {
      "id": "mem_abc123",
      "organisation_id": "org_xyz456",
      "user_id": "usr_aaa111",
      "first_name": "John",
      "last_name": "Doe",
      "email": "john.doe@example.com",
      "role": "ADMIN",
      "is_alert_action_required_email_enabled": true,
      "is_alert_resolved_email_enabled": true,
      "is_alert_dismissed_email_enabled": true,
      "is_evidence_requested_email_enabled": true,
      "created_at": "2026-02-10T09:30:00Z",
      "updated_at": "2026-02-10T09:30:00Z",
      "links": [
        {
          "rel": "self",
          "uri": "/v1/memberships/mem_abc123"
        }
      ]
    },
    {
      "id": "mem_def456",
      "organisation_id": "org_xyz456",
      "user_id": "usr_bbb222",
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane.smith@example.com",
      "role": "STANDARD",
      "is_alert_action_required_email_enabled": true,
      "is_alert_resolved_email_enabled": false,
      "is_alert_dismissed_email_enabled": false,
      "is_evidence_requested_email_enabled": true,
      "created_at": "2026-02-08T15:12:44Z",
      "updated_at": "2026-02-08T15:12:44Z",
      "links": [
        {
          "rel": "self",
          "uri": "/v1/memberships/mem_def456"
        }
      ]
    }
  ],
  "count": 2
}
```

***

## POST /v1/memberships - Create membership

Create a new membership for an accessible organisation.

**API level:** Partner-level only\
**Authentication:** `memberships:write`

### Request body

| Field                                    | Type    | Required | Validation                    | Description                           |
| ---------------------------------------- | ------- | -------- | ----------------------------- | ------------------------------------- |
| `organisation_id`                        | string  | Yes      | Must be accessible by API key | Organisation that owns the membership |
| `first_name`                             | string  | Yes      | Min length 1                  | User first name                       |
| `last_name`                              | string  | Yes      | Min length 1                  | User last name                        |
| `email`                                  | string  | Yes      | Valid email format            | User email                            |
| `role`                                   | string  | Yes      | `ADMIN` or `STANDARD`         | Membership role                       |
| `is_alert_action_required_email_enabled` | boolean | No       | Defaults to `true`            | Alert action-required email setting   |
| `is_alert_resolved_email_enabled`        | boolean | No       | Defaults to `true`            | Alert resolved email setting          |
| `is_alert_dismissed_email_enabled`       | boolean | No       | Defaults to `true`            | Alert dismissed email setting         |
| `is_evidence_requested_email_enabled`    | boolean | No       | Defaults to `true`            | Evidence requested email setting      |

{% hint style="info" %}

* If the user is already a member of the organisation, the API returns `422` with `MEMBERSHIP_ALREADY_EXISTS`.
* Notification setting values provided in the request are applied as sent.
  {% endhint %}

### Example request

```bash
curl -X POST "https://api.chargebackstop.com/v1/memberships/" \
  -H "Authorization: Bearer <api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "organisation_id": "org_xyz456",
    "first_name": "Alice",
    "last_name": "Johnson",
    "email": "alice.johnson@example.com",
    "role": "ADMIN",
    "is_alert_action_required_email_enabled": true,
    "is_alert_resolved_email_enabled": false,
    "is_alert_dismissed_email_enabled": true,
    "is_evidence_requested_email_enabled": true
  }'
```

### Example response

```json
{
  "id": "mem_new123",
  "organisation_id": "org_xyz456",
  "user_id": "usr_new123",
  "first_name": "Alice",
  "last_name": "Johnson",
  "email": "alice.johnson@example.com",
  "role": "ADMIN",
  "is_alert_action_required_email_enabled": true,
  "is_alert_resolved_email_enabled": false,
  "is_alert_dismissed_email_enabled": true,
  "is_evidence_requested_email_enabled": true,
  "created_at": "2026-02-16T12:00:00Z",
  "updated_at": "2026-02-16T12:00:00Z",
  "links": [
    {
      "rel": "self",
      "uri": "/v1/memberships/mem_new123"
    }
  ]
}
```

***

## GET /v1/memberships/{membership\_id} - Get membership by ID

Retrieve one accessible membership by ID.

**API level:** Partner-level only\
**Authentication:** `memberships:read`

### URL parameters

| Parameter       | Type   | Description   |
| --------------- | ------ | ------------- |
| `membership_id` | string | Membership ID |

### Example request

```bash
curl -X GET "https://api.chargebackstop.com/v1/memberships/mem_abc123" \
  -H "Authorization: Bearer <api_key>"
```

### Example response

```json
{
  "id": "mem_abc123",
  "organisation_id": "org_xyz456",
  "user_id": "usr_aaa111",
  "first_name": "John",
  "last_name": "Doe",
  "email": "john.doe@example.com",
  "role": "ADMIN",
  "is_alert_action_required_email_enabled": true,
  "is_alert_resolved_email_enabled": true,
  "is_alert_dismissed_email_enabled": true,
  "is_evidence_requested_email_enabled": true,
  "created_at": "2026-02-10T09:30:00Z",
  "updated_at": "2026-02-16T09:05:00Z",
  "links": [
    {
      "rel": "self",
      "uri": "/v1/memberships/mem_abc123"
    }
  ]
}
```

***

## PATCH /v1/memberships/{membership\_id} - Update membership

Update one accessible membership.

**API level:** Partner-level only\
**Authentication:** `memberships:write`

### URL parameters

| Parameter       | Type   | Description             |
| --------------- | ------ | ----------------------- |
| `membership_id` | string | Membership ID to update |

### Request body

All fields are optional.

| Field                                    | Type    | Required | Validation            | Description                                 |
| ---------------------------------------- | ------- | -------- | --------------------- | ------------------------------------------- |
| `role`                                   | string  | No       | `ADMIN` or `STANDARD` | Updated membership role                     |
| `is_alert_action_required_email_enabled` | boolean | No       | Optional              | Updated alert action-required email setting |
| `is_alert_resolved_email_enabled`        | boolean | No       | Optional              | Updated alert resolved email setting        |
| `is_alert_dismissed_email_enabled`       | boolean | No       | Optional              | Updated alert dismissed email setting       |
| `is_evidence_requested_email_enabled`    | boolean | No       | Optional              | Updated evidence requested email setting    |

{% hint style="info" %}

* Only fields included in the request are updated.
* If no fields are provided, the API returns the existing membership unchanged.
  {% endhint %}

### Example request

```bash
curl -X PATCH "https://api.chargebackstop.com/v1/memberships/mem_abc123" \
  -H "Authorization: Bearer <api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "STANDARD",
    "is_alert_resolved_email_enabled": false,
    "is_alert_dismissed_email_enabled": false
  }'
```

### Example response

```json
{
  "id": "mem_abc123",
  "organisation_id": "org_xyz456",
  "user_id": "usr_aaa111",
  "first_name": "John",
  "last_name": "Doe",
  "email": "john.doe@example.com",
  "role": "STANDARD",
  "is_alert_action_required_email_enabled": true,
  "is_alert_resolved_email_enabled": false,
  "is_alert_dismissed_email_enabled": false,
  "is_evidence_requested_email_enabled": true,
  "created_at": "2026-02-10T09:30:00Z",
  "updated_at": "2026-02-16T12:10:00Z",
  "links": [
    {
      "rel": "self",
      "uri": "/v1/memberships/mem_abc123"
    }
  ]
}
```

***

## DELETE /v1/memberships/{membership\_id} - Delete membership

Delete one accessible membership.

**API level:** Partner-level only\
**Authentication:** `memberships:write`

### URL parameters

| Parameter       | Type   | Description             |
| --------------- | ------ | ----------------------- |
| `membership_id` | string | Membership ID to delete |

### Example request

```bash
curl -X DELETE "https://api.chargebackstop.com/v1/memberships/mem_abc123" \
  -H "Authorization: Bearer <api_key>"
```

### Example response

204 No Content

***

## Common error responses

<details>

<summary>400 Invalid request</summary>

Returned when a membership cannot be created for the target user (for example, a staff user).

```json
{
  "errors": [
    {
      "code": "INVALID_REQUEST",
      "message": "Invalid request"
    }
  ]
}
```

</details>

<details>

<summary>401 Unauthorised</summary>

Returned for invalid or expired API keys, and for organisation-level keys calling this partner-only API.

```json
{
  "errors": [
    {
      "code": "UNAUTHORISED",
      "message": "Unauthorised"
    }
  ]
}
```

</details>

<details>

<summary>403 Forbidden (missing ability)</summary>

Returned when the API key is valid but missing required ability (`memberships:read` or `memberships:write`).

```json
{
  "errors": [
    {
      "code": "FORBIDDEN",
      "message": "Forbidden"
    }
  ]
}
```

</details>

<details>

<summary>404 Not found</summary>

Returned when the membership is not found or outside the key's accessible scope.

```json
{
  "errors": [
    {
      "code": "NOT_FOUND",
      "message": "Not found"
    }
  ]
}
```

</details>

<details>

<summary>422 Unprocessable Entity (membership already exists)</summary>

```json
{
  "errors": [
    {
      "code": "MEMBERSHIP_ALREADY_EXISTS",
      "message": "A user with this email is already a member of this organisation"
    }
  ]
}
```

</details>

<details>

<summary>422 Unprocessable Entity (membership deletion forbidden)</summary>

```json
{
  "errors": [
    {
      "code": "MEMBERSHIP_DELETION_FORBIDDEN",
      "message": "This membership cannot be deleted"
    }
  ]
}
```

</details>

Other business validation codes you may receive:

| Code                            | Meaning                                                    |
| ------------------------------- | ---------------------------------------------------------- |
| `MEMBERSHIP_ALREADY_EXISTS`     | A membership for this user and organisation already exists |
| `MEMBERSHIP_DELETION_FORBIDDEN` | Membership cannot be deleted due to business rules         |

Schema validation errors are also returned as `422` with `VALIDATION_*` codes.


---

# Agent Instructions: 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:

```
GET https://docs.chargebackstop.com/developer/api-documentation/memberships.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
