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

# Revoke group

> Revokes every member token that is not already REVOKED. Revocation is permanent. The action is applied in the background to the tokens that are members when the call is made; tokens added later are not affected. Members whose status the action does not apply to are counted in `skipped`. Not available yet: a request that passes validation is answered 501 (`NOT_IMPLEMENTED`), and retrying will not help.

Requires the `emsp:tokens:write` scope.



## OpenAPI

````yaml /openapi/emsp-token/openapi.yaml post /emsp/v1/token-groups/{groupId}/revoke
openapi: 3.0.0
info:
  title: Spirii EMMS - Token Management API
  description: >-
    Register, provision, activate, and manage charging tokens and token groups.


    ## Authentication

    Every operation needs an OAuth2 client-credentials access token sent as
    `Authorization: Bearer <token>`. The API gateway rejects a missing,
    malformed, invalid or expired token with 401 before the request reaches the
    service. Each operation states the scope it requires: `emsp:tokens:read` for
    reads and `emsp:tokens:write` for changes, and `emsp:tokens:write` also
    allows every read. A token without the required scope gets 403.


    ## Errors

    Errors from the service are returned as RFC 9457 problem details with
    content type `application/problem+json`. `error_code` is a machine-readable
    code for the error, `retryable` says whether the same request may succeed
    later, and `correlation_id` matches the `X-Request-Id` response header.
    Validation failures return 422 with one entry per failed rule in `errors`,
    so a field can appear more than once; a 400 carries `errors` in the same
    shape. `errors[].field` is a JSON-path style location of the input:
    `body.type`, `body.tokens[3].uid`, `query.limit`, `path.tokenId`,
    `header.Idempotency-Key`, or `body` when the body is not valid JSON. Errors
    raised by the API gateway before a request reaches the service, such as a
    rejected access token, throttling or an unknown path, use a plain JSON body
    with a `message` field instead.


    `error_code` names the cause, and a status can carry more than one:


    | `error_code` | Status | Retryable | When |

    | --- | --- | --- | --- |

    | `INVALID_REQUEST_BODY` | 400 | no | The request body is not valid JSON |

    | `INVALID_PATH_ID` | 400 | no | A path id is not a UUID |

    | `INVALID_IDEMPOTENCY_KEY` | 400 | no | The Idempotency-Key header is
    missing or not a UUID |

    | `INVALID_CURSOR` | 400 | no | The `after` cursor is not one this service
    issued, or was issued for a different sort order |

    | `AUTH_CONTEXT_INVALID` | 401 | no | The `x-spirii-*` principal headers are
    missing or not UUIDs. Not raised behind the API gateway, which rejects a
    missing or invalid access token first with a plain JSON body |

    | `INSUFFICIENT_SCOPE` | 403 | no | The access token does not carry the
    scope this operation requires |

    | `RESOURCE_NOT_FOUND` | 404 | no | The requested resource was not found |

    | `UID_ALREADY_REGISTERED` | 409 | no | The uid is already registered, in
    this tenant or another: uids are unique across every tenant |

    | `IDEMPOTENCY_KEY_REUSED` | 409 | no | The Idempotency-Key was already used
    with a different request body |

    | `REQUEST_IN_PROGRESS` | 409 | yes | A request with this Idempotency-Key is
    still in progress, or failed less than a minute ago. Retry with the same key
    and body |

    | `RESOURCE_CONFLICT` | 409 | no | The resource is in a conflicting state,
    such as a network assignment that would put a member token on two BASE
    networks |

    | `PAYLOAD_TOO_LARGE` | 413 | no | The request body exceeds the 1 MB limit |

    | `UNSUPPORTED_MEDIA_TYPE` | 415 | no | The request body uses a charset or
    Content-Encoding the service does not accept |

    | `VALIDATION_FAILED` | 422 | no | The request body or a query parameter
    failed validation, and errors lists each failed rule |

    | `RATE_LIMIT_EXCEEDED` | 429 | yes | Too many requests. Not raised by the
    service today: the API gateway throttles first, with a plain JSON body |

    | `INTERNAL_SERVER_ERROR` | 500 | yes | An unexpected error occurred. Retry
    after retry_after_seconds |

    | `NOT_IMPLEMENTED` | 501 | no | The operation is documented but not
    available yet. Retrying will not help |


    ## Idempotency

    Operations that take an `Idempotency-Key` header require a client-generated
    UUID. Repeating a request with the same key and body within 24 hours replays
    the original response and sets `Idempotent-Replay: true`; the same key with
    a different body returns 409. Keys are scoped to the method and path, so the
    same key on a different token or group is a separate request. If a request
    fails, its key stays reserved for about a minute: retrying with the same key
    and body in that window returns 409, and after it the same key runs the
    request again. Send a corrected request with a new key.


    ## Pagination

    List operations are cursor-paginated. Pass `pagination.end_cursor` from one
    response as `after` on the next, and stop when `pagination.has_next` is
    false.


    ## Asynchronous operations

    Token group lifecycle actions and bulk provisioning will be accepted with
    202 and processed in the background. An endpoint for reading an operation by
    `operation_id` is not available yet.


    ## Resources

    On tokens and token groups, optional fields without a value are sent as
    `null` rather than left out. A token history event's `reason` and a group
    operation's `failures` are left out when they do not apply.


    ## Current limitations

    Token group membership, network assignment and the group lifecycle actions
    are not available yet: a request that passes validation is answered 501
    (`NOT_IMPLEMENTED`), and retrying will not help. Until networks can be
    assigned, `network_ids` on a group is always empty. A tenant without a
    TOKEN_GROUP metadata schema cannot store metadata on a group: any non-empty
    `metadata` map is a 422 until that schema exists. Every other token and
    token group operation answers as documented. Bulk import validates the
    documented 1000 tokens in one request, and a request body over 1 MB returns
    413, but a batch that passes validation is answered 501 (`NOT_IMPLEMENTED`)
    until bulk provisioning is available.
  version: v1
  contact: {}
servers:
  - url: https://api.spirii.com
    description: Production
security:
  - OAuth2ClientCredentials: []
tags:
  - name: Tokens
    description: Provision tokens, change their lifecycle and read their history
  - name: Token Groups
    description: >-
      Create token groups, manage their member tokens and network assignments,
      and change the lifecycle of every member at once
paths:
  /emsp/v1/token-groups/{groupId}/revoke:
    post:
      tags:
        - Token Groups
      summary: Revoke group
      description: >-
        Revokes every member token that is not already REVOKED. Revocation is
        permanent. The action is applied in the background to the tokens that
        are members when the call is made; tokens added later are not affected.
        Members whose status the action does not apply to are counted in
        `skipped`. Not available yet: a request that passes validation is
        answered 501 (`NOT_IMPLEMENTED`), and retrying will not help.


        Requires the `emsp:tokens:write` scope.
      operationId: token_groups_revoke
      parameters:
        - name: groupId
          required: true
          in: path
          description: The token group `group_id`
          schema:
            type: string
            format: uuid
        - name: Idempotency-Key
          in: header
          description: >-
            Client-generated unique key per operation intent (UUID). Same key +
            identical body replays the original response; same key + different
            body returns 409.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReasonRequestDto'
      responses:
        '202':
          description: The operation was accepted
          headers:
            Idempotent-Replay:
              description: >-
                Present and `true` when this response is a replay of an earlier
                request with the same Idempotency-Key
              schema:
                type: string
                enum:
                  - 'true'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupOperationResultDto'
        '400':
          description: >-
            A path id is not a UUID (`INVALID_PATH_ID`). The Idempotency-Key
            header is missing or not a UUID (`INVALID_IDEMPOTENCY_KEY`), or the
            body is not valid JSON (`INVALID_REQUEST_BODY`)
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
        '401':
          description: >-
            The access token is missing, invalid or expired, rejected by the API
            gateway with a plain JSON body
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '403':
          description: >-
            The access token does not carry the scope this operation requires
            (`INSUFFICIENT_SCOPE`)
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
        '404':
          description: No token group with this id exists in your tenant
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
        '409':
          description: >-
            The Idempotency-Key was already used with a different body
            (`IDEMPOTENCY_KEY_REUSED`), or that request is still in progress
            (`REQUEST_IN_PROGRESS`)
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
        '422':
          description: >-
            The request body failed validation (`VALIDATION_FAILED`). `errors`
            lists each failed rule
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
        '429':
          description: >-
            Too many requests, rejected by the API gateway with a plain JSON
            body
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '500':
          description: >-
            Unexpected server error. When `retryable` is true, retry after
            `retry_after_seconds`. Where the operation takes an Idempotency-Key,
            reuse the same key; a retry within about a minute may return 409
            while it is still reserved
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
        '501':
          description: >-
            The operation is not available yet (`NOT_IMPLEMENTED`). Not
            retryable
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetailDto'
components:
  schemas:
    ReasonRequestDto:
      type: object
      properties:
        reason:
          type: string
          maxLength: 500
          description: >-
            Free-text reason, recorded on the history event of each token the
            action changes
          example: Card reported lost
    GroupOperationResultDto:
      type: object
      properties:
        operation_id:
          type: string
          format: uuid
          description: Identifies this background operation
        group_id:
          type: string
          format: uuid
        action:
          type: string
          enum:
            - ACTIVATE
            - SUSPEND
            - REACTIVATE
            - REVOKE
        status:
          type: string
          enum:
            - PENDING
            - IN_PROGRESS
            - COMPLETED
            - FAILED
          description: Progress of the operation
        total:
          type: integer
          minimum: 0
          description: Member tokens when the action was requested
        eligible:
          type: integer
          minimum: 0
          description: Members whose status the action applies to
        succeeded:
          type: integer
          minimum: 0
          description: Eligible members the action has been applied to
        failed:
          type: integer
          minimum: 0
          description: Eligible members the action failed on
        skipped:
          type: integer
          minimum: 0
          description: >-
            Members whose status the action does not apply to; `total` minus
            `eligible`
        failures:
          description: >-
            The members the action failed on. Absent until the operation has
            processed tokens
          type: array
          items:
            $ref: '#/components/schemas/TokenFailureDto'
        created_at:
          type: string
          format: date-time
        completed_at:
          type: string
          nullable: true
          format: date-time
          description: When the operation reached COMPLETED or FAILED; null until then
      required:
        - operation_id
        - group_id
        - action
        - status
        - total
        - eligible
        - succeeded
        - failed
        - skipped
        - created_at
    ProblemDetailDto:
      type: object
      properties:
        type:
          type: string
          example: /errors/validation-failed
          description: Error type URI
        title:
          type: string
          example: Validation Failed
        status:
          type: integer
          example: 422
        detail:
          type: string
        error_code:
          example: RESOURCE_NOT_FOUND
          description: >-
            Machine-readable error cause. The Errors section of the API
            description says when each is returned
          allOf:
            - $ref: '#/components/schemas/ErrorCode'
        correlation_id:
          type: string
          format: uuid
          description: Matches X-Request-Id header
        retryable:
          type: boolean
        retry_after_seconds:
          type: integer
          minimum: 1
        errors:
          type: array
          items:
            $ref: '#/components/schemas/FieldErrorDto'
      required:
        - type
        - title
        - status
        - detail
        - error_code
        - correlation_id
        - retryable
    TokenFailureDto:
      type: object
      properties:
        token_id:
          type: string
          format: uuid
          description: The member token the action failed on
        current_status:
          type: string
          enum:
            - PROVISIONED
            - ACTIVE
            - SUSPENDED
            - EXPIRED
            - REVOKED
          description: The status the token was left in
        error_code:
          type: string
          description: Machine-readable cause of the failure
        message:
          type: string
          description: Human-readable cause of the failure
      required:
        - token_id
        - current_status
        - error_code
        - message
    ErrorCode:
      type: string
      enum:
        - INVALID_REQUEST_BODY
        - INVALID_PATH_ID
        - INVALID_IDEMPOTENCY_KEY
        - INVALID_CURSOR
        - AUTH_CONTEXT_INVALID
        - INSUFFICIENT_SCOPE
        - RESOURCE_NOT_FOUND
        - UID_ALREADY_REGISTERED
        - IDEMPOTENCY_KEY_REUSED
        - REQUEST_IN_PROGRESS
        - RESOURCE_CONFLICT
        - PAYLOAD_TOO_LARGE
        - UNSUPPORTED_MEDIA_TYPE
        - VALIDATION_FAILED
        - RATE_LIMIT_EXCEEDED
        - INTERNAL_SERVER_ERROR
        - NOT_IMPLEMENTED
      description: >-
        Machine-readable error cause. The Errors section of the API description
        says when each is returned
    FieldErrorDto:
      type: object
      properties:
        field:
          type: string
          description: >-
            The input that failed, as a JSON-path style location: `body.type`,
            `body.tokens[3].uid`, `query.limit`, `path.tokenId`,
            `header.Idempotency-Key`, or `body` when the body is not valid JSON
          example: body.tokens[3].uid
        code:
          type: string
          enum:
            - INVALID_ENUM
            - INVALID_FORMAT
            - MISSING_REQUIRED
            - CONSTRAINT_VIOLATION
          description: Machine-readable validation error code
        message:
          type: string
          description: Human-readable error description
      required:
        - field
        - code
        - message
  securitySchemes:
    OAuth2ClientCredentials:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: >-
            https://auth.spirii.dk/realms/public-api/protocol/openid-connect/token
          scopes:
            emsp:tokens:read: >-
              Read tokens, token history, token groups and their network
              assignments
            emsp:tokens:write: >-
              Provision, update and change the lifecycle of tokens; create and
              manage token groups. Also grants everything `emsp:tokens:read`
              does

````

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