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

# Manage partners via API

> Create, read, change, and delete partners with the Identity API, read the product scope catalogs, create partner applications, and handle the error codes.

The Identity API manages [partners](https://docs.lerian.studio/en/platform/access-manager/features/partners/overview) and their applications. Use it when you manage partners from your own tooling instead of the Console.

## Before you start

***

To manage partners, a user needs the `partners` permissions of `plugin-identity`: `get` to read partners and scope catalogs, `post` to create a partner, `patch` to change one and `delete` to delete one. Managing its applications needs the `applications` permissions `get`, `post` and `delete`. The `plugin-identity-editor-role` role holds all of them.

## The operations

***

| Operation | What it does | Reference |
| - | - | - |
| `GET /v1/partners` | Lists your partners, one page at a time, with `applicationsCount` for each one. | [List partners](https://docs.lerian.studio/en/reference/platform/access-manager/list-partners.md) |
| `POST /v1/partners` | Creates a partner. It returns `201` with the new partner and its `id`. It creates no application. | [Create a partner](https://docs.lerian.studio/en/reference/platform/access-manager/create-a-partner.md) |
| `GET /v1/partners/{id}` | Returns one partner. | [Retrieve a partner](https://docs.lerian.studio/en/reference/platform/access-manager/retrieve-a-partner.md) |
| `PATCH /v1/partners/{id}` | Changes a partner: its name, its permissions, its scope, its validity window, its IP allowlist, or its state. | [Update a partner](https://docs.lerian.studio/en/reference/platform/access-manager/update-a-partner.md) |
| `DELETE /v1/partners/{id}` | Deletes a partner without applications. It returns `204`. | [Delete a partner](https://docs.lerian.studio/en/reference/platform/access-manager/delete-a-partner.md) |
| `GET /v1/partners/ceiling` | Returns the most you can give a partner in the product that the `product` query parameter names. | [Retrieve the partner ceiling of a product](https://docs.lerian.studio/en/reference/platform/access-manager/retrieve-the-partner-ceiling-of-a-product.md) |
| `GET /v1/scope-catalog` | Lists the scope catalogs that products published, with `partners` for each one. | [List scope catalogs](https://docs.lerian.studio/en/reference/platform/access-manager/list-scope-catalogs.md) |
| `GET /v1/scope-catalog/{product}` | Returns the scope catalog of one product. A product without a catalog returns `404` with `IDE-1053`. | [Retrieve a product's scope catalog](https://docs.lerian.studio/en/reference/platform/access-manager/retrieve-a-product-s-scope-catalog.md) |

To learn which dimensions a product accepts in `scope`, read its scope catalog. Each dimension has a `name`, and the flags `required`, `multi`, and `explicit`.

## The partner fields

***

| Field | Required on create | Meaning |
| - | - | - |
| `displayName` | Yes | The partner's name, 1 to 100 characters. A letter with an accent, and any other character outside plain ASCII, counts as two or more. A longer name is refused. The name is unique in your tenant, and the comparison ignores case. |
| `permissions` | Yes | One or more entries, each with its own `product`, `resources`, and `actions`. Each entry needs at least one resource and one action. |
| `scope` | Yes, for each product whose scope catalog declares dimensions | One entry per restriction: `product`, `field`, and `values`. `field` is the `name` of a dimension in the product's scope catalog. |
| `ipAllowlist` | No | The partner's own IP allowlist. Each entry has a `cidr` and an optional `description` of up to 255 characters. |
| `validFrom` | No | The start of the validity window, as an RFC 3339 instant. Absent means no start date. |
| `validUntil` | No | The end of the validity window, as an RFC 3339 instant. Absent means no end date. |
| `state` | Not accepted | `active` or `suspended`. Every new partner is `active`. You change it with `PATCH`. |

The response also carries `id`, `applicationsCount`, `createdAt`, and `updatedAt`.

Rules that apply to the fields:

* `product` is the product slug that the product's scope catalog carries, such as `plugin-br-pix-jd`.
* Write `actions` as lowercase HTTP verbs: `get`, `post`, `put`, `patch`, `delete`.
* `resources` × `actions` is a full cross product. To give different actions on different resources, send more than one entry for the same product.
* Access Manager refuses the wildcard `*` in `resources`, `actions`, and `values`. List the items.
* A product in `scope` must also be in `permissions`.
* A product whose scope catalog declares dimensions needs at least one scope entry on every partner with permissions on that product. Without one, Access Manager refuses to create or change the partner, with `IDE-1060`. A partner stored without one before this rule is refused with `403` on every request to that product, until you add a scope entry.
* A dimension that the catalog marks as `required` needs a scope entry on every partner with permissions on that product, or Access Manager refuses with `IDE-0001`. A dimension without `multi` takes one value only, or Access Manager refuses with `IDE-0002`.
* For a dimension that the catalog marks as `explicit`, a permission on that dimension's collection needs a scope entry that lists its IDs. Without one, Access Manager refuses with `IDE-1052`. The partner reaches only the IDs you list.
* Access Manager does not check that the `values` exist in the product. Use the identifiers that the product's own API returns.
* `state` is `active` or `suspended`, never `expired`. After `validUntil`, a read still returns the stored state.
* After the partner's `validUntil` date, Access Manager refuses its requests, also with a token it already holds, and refuses new tokens.

## The IP allowlist field

***

`ipAllowlist` has three meanings on `PATCH`:

| You send | What happens |
| - | - |
| The field omitted | The stored list stays as it is. |
| `null` | The partner's own list is deleted. The partner goes back to your tenant's list. |
| A list of entries | These entries replace the partner's own list. |
| `[]` | Refused with `IDE-1048`. |

On `POST`, omit the field or send `null` to use your tenant's list.

When a partner has its own IP list, that list replaces the tenant's IP list for the partner's requests.

`validFrom` and `validUntil` work in a similar way on `PATCH`. Omit a bound to keep it, send an instant to set it, or send `null` to remove it.

## Examples

***

Replace the placeholders with your Identity API base URL, your bearer token, and identifiers from your own deployment.

```bash Create a partner theme={null}
IDENTITY_BASE_URL="https://identity.<your-domain>"   # your Identity API base URL
IDENTITY_BEARER_TOKEN="paste-your-access-token-here"

curl -sS -X POST "${IDENTITY_BASE_URL}/v1/partners" \
  -H "Authorization: Bearer ${IDENTITY_BEARER_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "Partner A",
    "permissions": [
      { "product": "plugin-br-pix-jd", "resources": ["entries"], "actions": ["get", "post"] }
    ],
    "scope": [
      { "product": "plugin-br-pix-jd", "field": "participantId", "values": ["12345678"] }
    ],
    "ipAllowlist": [
      { "cidr": "203.0.113.10", "description": "Partner A gateway" }
    ]
  }'
```

```bash Create its application theme={null}
IDENTITY_BASE_URL="https://identity.<your-domain>"   # your Identity API base URL
IDENTITY_BEARER_TOKEN="paste-your-access-token-here"
PARTNER_ID="paste-the-partner-id-here"

curl -sS -X POST "${IDENTITY_BASE_URL}/v1/applications" \
  -H "Authorization: Bearer ${IDENTITY_BEARER_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "plugin-br-pix-jd",
    "description": "Partner A access to Pix JD",
    "partnerId": "'"${PARTNER_ID}"'"
  }'
```

```bash Suspend it theme={null}
IDENTITY_BASE_URL="https://identity.<your-domain>"   # your Identity API base URL
IDENTITY_BEARER_TOKEN="paste-your-access-token-here"
PARTNER_ID="paste-the-partner-id-here"

curl -sS -X PATCH "${IDENTITY_BASE_URL}/v1/partners/${PARTNER_ID}" \
  -H "Authorization: Bearer ${IDENTITY_BEARER_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{ "state": "suspended" }'
```

```bash Go back to the tenant's IP list theme={null}
IDENTITY_BASE_URL="https://identity.<your-domain>"   # your Identity API base URL
IDENTITY_BEARER_TOKEN="paste-your-access-token-here"
PARTNER_ID="paste-the-partner-id-here"

curl -sS -X PATCH "${IDENTITY_BASE_URL}/v1/partners/${PARTNER_ID}" \
  -H "Authorization: Bearer ${IDENTITY_BEARER_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{ "ipAllowlist": null }'
```

## Create the partner's applications

***

A partner calls a product with an application that belongs to it. After you create the partner:

1. Create an application with [Create an Application](https://docs.lerian.studio/en/reference/platform/access-manager/create-an-application.md). Send the partner's `id` in `partnerId`, and the product slug in `target`, such as `plugin-br-pix-jd`.
2. The Identity API returns the client secret only in the response that creates the application. Store it then. If you lose the secret, delete the application and create a new one.
3. Send the client ID and the secret to the partner through a secure channel.
4. Repeat steps 1 to 3 for each product the partner calls. Create one application per product.

To list the applications of one partner, send its `id` in the `partnerId` query parameter of [List Applications](https://docs.lerian.studio/en/reference/platform/access-manager/list-applications.md). If `partnerId` does not name a partner of your tenant, both operations return `404` with `IDE-1046`.

## Change, suspend, or delete a partner

***

* On `PATCH`, send only the fields you change. A `permissions` or a `scope` list replaces the stored list as a whole. Read the partner first, then send the complete new list.
* To suspend a partner, send `"state": "suspended"`. To reactivate it, send `"state": "active"`.
* Suspending a partner in Access Manager stops its access, including the tokens it already holds. Reactivating the partner inside its validity window restores access with the same credentials.
* [When a change applies](https://docs.lerian.studio/en/platform/access-manager/features/partners/overview#when-a-change-applies) says when the partner sees a change of permissions or scope.
* You cannot delete a partner that still has applications. The response is `409` with `IDE-1049`, and its `errors` list names each blocking application with its client ID. Delete those applications first.
* Deleting an application stops its tokens from working.

## Error codes

***

Errors in the partner operations:

| Code | Status | Title | When |
| - | - | - | - |
| `IDE-0001` | 400 | Missing Fields in Request | A required field is missing, or the scope has no entry for a dimension the product requires. |
| `IDE-0002` | 400 | Invalid Field Type | A dimension that takes one value received several. |
| `IDE-0036` | 400 | Invalid IP Allowlist Entry | An `ipAllowlist` entry is not a valid address or CIDR range. |
| `IDE-1040` | 409 | Partner Display Name Already Exists | Another partner of your tenant has the same `displayName`. |
| `IDE-1042` | 400 | Unknown Scope Field | A scope `field` is not in the product's scope catalog, or the product has no scope catalog. |
| `IDE-1043` | 400 | Permission Above Product Ceiling | A permission is above what the product's editor role holds in your tenant. |
| `IDE-1044` | 400 | Scope Without Permissions | A product is in `scope` but not in `permissions`. |
| `IDE-1045` | 400 | Invalid Validity Window | `validUntil` is not later than `validFrom`. |
| `IDE-1046` | 404 | Partner Not Found | No partner with this `id` exists in your tenant. |
| `IDE-1047` | 400 | Wildcard Not Allowed | `*` is in `resources`, `actions`, or `values`. |
| `IDE-1048` | 400 | Empty IP Allowlist | `ipAllowlist` is an empty array. |
| `IDE-1049` | 409 | Partner Has Applications | The partner still has applications, so it cannot be deleted. |
| `IDE-1050` | 400 | Duplicate IP Allowlist Entry | The same network appears twice in `ipAllowlist`. |
| `IDE-1052` | 400 | Partner Rejected | The identity provider refused the partner for another reason, for example a permission on the collection of an `explicit` dimension without its IDs. The message repeats that reason. |
| `IDE-1053` | 404 | Scope Catalog Not Found | The product has not published a scope catalog. |
| `IDE-1054` | 400 | Product Not Ready For Partners | A permission names a product that has not published its scope catalog. |
| `IDE-1055` | 400 | Product Not Opted In To Partners | A permission names a product whose scope catalog does not accept partners. |
| `IDE-1056` | 400 | Partner Write Exceeds Its Scope | A write permission acts at tenant level, or at a level wider than the partner's scope. |
| `IDE-1057` | 400 | Partner Read Rejected | The identity provider refused the ceiling read, for example for an unknown product. |
| `IDE-1060` | 400 | Partner Product Without Scope | A permission names a product whose scope catalog declares dimensions, and `scope` has no entry for that product. On `PATCH`, removing the last scope entry of a product that keeps its permissions is refused too. |

For every other code, see the [Access Manager error list](https://docs.lerian.studio/en/reference/platform/access-manager/access-manager-error-list.md).


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