> ## 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.

# Update a partner

> Changes a partner's access, its validity window, its IP allowlist or its state. Every member is optional and anything you omit is left alone — but `permissions` and `scope`, when supplied, REPLACE the stored list wholesale. There is no per-entry merge, because a merge would make "remove the last ledger" impossible to express.

Called to widen or narrow a partner mid-life, and to suspend or reactivate one (`state: "suspended"` / `"active"`). Suspending is the reversible kill switch; deleting is not.

`ipAllowlist` has THREE meanings here and they are not interchangeable: omit the member to leave the list as it is, send `null` to go back to inheriting the organization's list, send entries to replace it with the partner's own. An empty array is refused.

`validFrom` and `validUntil` work the same way, one bound at a time: omit the member to keep the stored bound, send an RFC 3339 instant to set it, send `null` to remove it and leave the window open on that side (no start date: honoured from now on; no end date: never expires — a partner already past its end date is honoured again unless it is suspended). An empty string is refused with `422`. When you send only one bound it is checked against the other one as stored: moving `validFrom` to or past the stored `validUntil`, or `validUntil` to or before the stored `validFrom`, is `400 IDE-1045` and nothing is written. To move a window to a later period, send both bounds in the same request.

What changes: the stored record, and with it every future authorization. The change takes effect on the next authorization decision, including for access tokens already issued to this partner. Token issuance is refused while the partner is suspended or outside its validity window, and from an address outside its IP allowlist; a permission or scope change does not stop issuance, it limits what the token can do. To cut a partner off, suspend it.

Failures: every code `POST` can return, applied to the record as it will be after the patch (`IDE-1042`, `IDE-1043`, `IDE-1044`, `IDE-1045`, `IDE-1047`, `IDE-1048`, `IDE-0036`, `IDE-1050`, `IDE-1052`, `409 IDE-1040`), plus:
- `400 IDE-1054` — the product is not ready for partners yet: it has not published a scope catalog. Raised only when the request sends `permissions`: a partner that already holds such a line can still be suspended, reactivated or renamed, and the line can be removed.
- `400 IDE-1055` — a permission names a product that has not opted in to partners. Like IDE-1054 it is raised only when the request sends `permissions`, for every line; remove the line to proceed.
- `400 IDE-1056` is checked when either `permissions` or `scope` changes: granting a write and narrowing the scope under a write already granted both put the write above the scope. Narrow the scope and drop the write in the same update.
- `404 IDE-1046` — no such partner in your organization.
- `403` — your token does not hold the `partners` resource.
- `503 IDE-0066` — the identity provider is unavailable (unreachable, too slow to answer, or failing). Nothing about the request was wrong; retry it later.



## OpenAPI

````yaml /en/openapi/v3-current/AM-identity.yaml patch /v1/partners/{id}
openapi: 3.1.0
info:
  contact:
    name: Lerian Studio
    url: https://lerian.studio
  description: OpenAPI 3.1 surface for the Access Manager identity component.
  license:
    name: Lerian Studio General License
  title: Plugin Access Manager — Identity API
  version: v1
servers:
  - url: https://identity.sandbox.lerian.net
security: []
tags:
  - description: >-
      M2M-only: each plugin declares its own permissions, roles and M2M
      contract, and the server reconciles them.
    name: Declarations
  - description: >-
      A tenant administrator's customers. Each partner holds what its
      credentials may DO (permissions, per product) and WHERE they may do it
      (scope, per product and dimension); an M2M application attached to one is
      confined to that intersection. Administrator-only: authorized on the
      "partners" resource, and every route resolves the owning organization from
      the caller's token.
    name: Partners
paths:
  /v1/partners/{id}:
    patch:
      tags:
        - Partners
      summary: Update a partner
      description: >-
        Changes a partner's access, its validity window, its IP allowlist or its
        state. Every member is optional and anything you omit is left alone —
        but `permissions` and `scope`, when supplied, REPLACE the stored list
        wholesale. There is no per-entry merge, because a merge would make
        "remove the last ledger" impossible to express.


        Called to widen or narrow a partner mid-life, and to suspend or
        reactivate one (`state: "suspended"` / `"active"`). Suspending is the
        reversible kill switch; deleting is not.


        `ipAllowlist` has THREE meanings here and they are not interchangeable:
        omit the member to leave the list as it is, send `null` to go back to
        inheriting the organization's list, send entries to replace it with the
        partner's own. An empty array is refused.


        `validFrom` and `validUntil` work the same way, one bound at a time:
        omit the member to keep the stored bound, send an RFC 3339 instant to
        set it, send `null` to remove it and leave the window open on that side
        (no start date: honoured from now on; no end date: never expires — a
        partner already past its end date is honoured again unless it is
        suspended). An empty string is refused with `422`. When you send only
        one bound it is checked against the other one as stored: moving
        `validFrom` to or past the stored `validUntil`, or `validUntil` to or
        before the stored `validFrom`, is `400 IDE-1045` and nothing is written.
        To move a window to a later period, send both bounds in the same
        request.


        What changes: the stored record, and with it every future authorization.
        The change takes effect on the next authorization decision, including
        for access tokens already issued to this partner. Token issuance is
        refused while the partner is suspended or outside its validity window,
        and from an address outside its IP allowlist; a permission or scope
        change does not stop issuance, it limits what the token can do. To cut a
        partner off, suspend it.


        Failures: every code `POST` can return, applied to the record as it will
        be after the patch (`IDE-1042`, `IDE-1043`, `IDE-1044`, `IDE-1045`,
        `IDE-1047`, `IDE-1048`, `IDE-0036`, `IDE-1050`, `IDE-1052`, `409
        IDE-1040`), plus:

        - `400 IDE-1054` — the product is not ready for partners yet: it has not
        published a scope catalog. Raised only when the request sends
        `permissions`: a partner that already holds such a line can still be
        suspended, reactivated or renamed, and the line can be removed.

        - `400 IDE-1055` — a permission names a product that has not opted in to
        partners. Like IDE-1054 it is raised only when the request sends
        `permissions`, for every line; remove the line to proceed.

        - `400 IDE-1056` is checked when either `permissions` or `scope`
        changes: granting a write and narrowing the scope under a write already
        granted both put the write above the scope. Narrow the scope and drop
        the write in the same update.

        - `404 IDE-1046` — no such partner in your organization.

        - `403` — your token does not hold the `partners` resource.

        - `503 IDE-0066` — the identity provider is unavailable (unreachable,
        too slow to answer, or failing). Nothing about the request was wrong;
        retry it later.
      operationId: updatePartner
      parameters:
        - description: Identifier of the partner to modify.
          in: path
          name: id
          required: true
          schema:
            description: Identifier of the partner to modify.
            examples:
              - 00000000-0000-0000-0000-000000000000
            format: uuid
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerUpdateInput'
              description: The members to change. Anything omitted is left as it is.
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerResponse'
          description: OK
        '422':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Unprocessable Entity
        '500':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Internal Server Error
        '503':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Service Unavailable
        default:
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Error
      security:
        - BearerAuth: []
components:
  schemas:
    PartnerUpdateInput:
      additionalProperties: false
      properties:
        displayName:
          description: >-
            New human-readable name. Still unique within the organization
            (IDE-1040).
          examples:
            - Loja do Zé Matriz
          minLength: 1
          type: string
        ipAllowlist:
          description: >-
            Omit to leave the list untouched, send null to go back to inheriting
            the organization's list, send entries to replace it. An empty array
            is refused (IDE-1048).
          items:
            $ref: '#/components/schemas/IPAllowlistEntry'
          type:
            - array
            - 'null'
        permissions:
          description: Replaces the whole permissions list when supplied.
          items:
            $ref: '#/components/schemas/PartnerPermission'
          type: array
        scope:
          description: Replaces the whole scope list when supplied.
          items:
            $ref: '#/components/schemas/PartnerScope'
          type: array
        state:
          description: >-
            Suspend or reactivate the partner. Takes effect on the next
            authorization decision, including for access tokens already issued,
            and on the next token issuance.
          enum:
            - active
            - suspended
          examples:
            - suspended
          type: string
        validFrom:
          description: >-
            New window start (RFC 3339). Omit to keep the stored start; send
            null to remove it, so the partner's credentials are honoured from
            now on; an empty string is refused (422). The resulting window is
            checked against the stored validUntil when that is not sent:
            validUntil must stay later than validFrom, else 400 IDE-1045.
          examples:
            - '2026-01-01T00:00:00Z'
          format: date-time
          type:
            - string
            - 'null'
        validUntil:
          description: >-
            New window end (RFC 3339). Omit to keep the stored end; send null to
            remove it, so the window has no end date and a partner already past
            its end date is honoured again (unless suspended); an empty string
            is refused (422). Must be later than validFrom — the one sent, or
            the stored one when validFrom is not sent — else 400 IDE-1045.
          examples:
            - '2027-01-01T00:00:00Z'
          format: date-time
          type:
            - string
            - 'null'
      type: object
    PartnerResponse:
      additionalProperties: false
      properties:
        applicationsCount:
          description: >-
            How many M2M applications are currently attached to this partner. A
            non-zero value is what makes DELETE answer 409 (IDE-1049).
          examples:
            - 2
          format: int64
          type: integer
        createdAt:
          description: When the partner was created (RFC 3339).
          examples:
            - '2026-01-15T09:30:00Z'
          type: string
        displayName:
          description: Human-readable name, unique within the organization.
          examples:
            - Loja do Zé
          type: string
        id:
          description: >-
            Server-generated identifier of the partner (UUID). This is the value
            to pass as partnerId when creating an application.
          examples:
            - 00000000-0000-0000-0000-000000000000
          type: string
        ipAllowlist:
          description: >-
            The partner's own IP allowlist, or null when it inherits the
            organization's list. Null and an empty list are NOT the same thing
            here: null is inheritance, and an empty own list cannot be stored.
          items:
            $ref: '#/components/schemas/IPAllowlistEntry'
          type:
            - array
            - 'null'
        permissions:
          description: What the partner may do, per product.
          items:
            $ref: '#/components/schemas/PartnerPermission'
          type:
            - array
            - 'null'
        scope:
          description: Where the partner may do it, per product and dimension.
          items:
            $ref: '#/components/schemas/PartnerScope'
          type:
            - array
            - 'null'
        state:
          description: >-
            Whether the partner's credentials are honoured. Note this never
            reads "expired": expiry is derived from validUntil at decision time,
            so a closed window shows here as "active" with a past validUntil.
          enum:
            - active
            - suspended
          examples:
            - active
          type: string
        updatedAt:
          description: When it was last modified (RFC 3339).
          examples:
            - '2026-01-15T09:30:00Z'
          type: string
        validFrom:
          description: >-
            Start of the validity window (RFC 3339), or null when it is
            open-ended.
          examples:
            - '2026-01-01T00:00:00Z'
          format: date-time
          type:
            - string
            - 'null'
        validUntil:
          description: >-
            End of the validity window (RFC 3339), or null when it is
            open-ended.
          examples:
            - '2027-01-01T00:00:00Z'
          format: date-time
          type:
            - string
            - 'null'
      required:
        - id
        - displayName
        - state
        - permissions
        - scope
        - ipAllowlist
        - validFrom
        - validUntil
        - applicationsCount
        - createdAt
        - updatedAt
      type: object
    Detail:
      additionalProperties: true
      properties:
        code:
          description: >-
            Stable, machine-readable domain error code scoped to the emitting
            service (format: <SERVICE>-NNNN).
          type: string
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          examples:
            - Property foo is required but is missing.
          type: string
        errors:
          description: Optional list of individual error details
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type:
            - array
            - 'null'
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          examples:
            - https://example.com/error-log/abc123
          format: uri
          type: string
        status:
          description: HTTP status code
          examples:
            - 400
          format: int64
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This value
            should not change between occurrences of the error.
          examples:
            - Bad Request
          type: string
        type:
          default: about:blank
          description: A URI reference to human-readable documentation for the error.
          examples:
            - https://example.com/errors/example
          format: uri
          type: string
        upstream:
          $ref: '#/components/schemas/Upstream'
          description: >-
            RFC 9457 extension member: the error a proxied third-party provider
            reported. Absent unless the emitting service explicitly surfaced
            one.
      type: object
    IPAllowlistEntry:
      additionalProperties: false
      properties:
        cidr:
          description: >-
            Network in CIDR form, or a bare IPv4/IPv6 address which is widened
            to a host route (/32, /128) on persist. Malformed entries are
            refused with IDE-0036; the same cidr twice with IDE-1050.
          examples:
            - 203.0.113.0/24
          type: string
        description:
          description: >-
            Free-text label for this entry, shown to operators. Never influences
            an access decision; bounded only by length.
          examples:
            - Loja do Zé — SP datacenter
          type: string
      required:
        - cidr
      type: object
    PartnerPermission:
      additionalProperties: false
      properties:
        actions:
          description: >-
            Verbs the partner may use on those collections, lowercase ("get",
            "post", "patch", "delete"). "head" is granted together with "get".
            Each resource/action pair must be held by one permission of your
            organization's editor role in the product, else IDE-1043. "*" is
            refused (IDE-1047).
          examples:
            - - get
              - post
          items:
            type: string
          type:
            - array
            - 'null'
        product:
          description: >-
            Product slug these permissions apply to, as returned by GET
            /v1/applications/available. Matched by exact equality.
          examples:
            - midaz
          type: string
        resources:
          description: >-
            Collections the partner may reach in this product, named exactly as
            the product declares them ("accounts", "transactions"). Each
            resource/action pair must be held by one permission of your
            organization's editor role in the product, else IDE-1043. "*" is
            refused (IDE-1047).
          examples:
            - - accounts
              - balances
          items:
            type: string
          type:
            - array
            - 'null'
      required:
        - product
        - resources
        - actions
      type: object
    PartnerScope:
      additionalProperties: false
      properties:
        field:
          description: >-
            Dimension being scoped, as the product's published scope catalog
            names it (GET /v1/scope-catalog/{product}). A field the catalog does
            not declare is refused with IDE-1042; a required dimension left out
            with IDE-0001; several values on a single-valued dimension with
            IDE-0002.
          examples:
            - ledgerId
          type: string
        product:
          description: >-
            Product slug this scope applies to. Must also appear in permissions,
            else IDE-1044.
          examples:
            - midaz
          type: string
        values:
          description: >-
            Instance identifiers for this dimension, compared after trimming: a
            canonical UUID case-insensitively, any other value (such as an
            account alias) exactly. Neither format nor existence inside the
            product is checked, so supply values the product's own list API
            returned.
          examples:
            - - 00000000-0000-0000-0000-000000000000
          items:
            type: string
          type:
            - array
            - 'null'
      required:
        - product
        - field
        - values
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        location:
          description: >-
            Where the error occurred, e.g. 'body.items[3].tags' or
            'path.thing-id'
          type: string
        message:
          description: Error message text
          type: string
        value:
          description: The value at the given location
      type: object
    Upstream:
      additionalProperties: false
      properties:
        code:
          description: The upstream provider's own error code, verbatim.
          examples:
            - E4001
          type: string
        message:
          description: >-
            The upstream provider's own error message, verbatim (bounded, never
            its raw response body).
          examples:
            - account not found at provider
          type: string
      type: object
  securitySchemes:
    BearerAuth:
      bearerFormat: JWT
      description: JWT bearer token issued by the identity provider.
      scheme: bearer
      type: http

````

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