# Approve or reject a self-service request.


The webhook-mode counterpart of the portal's approve / reject buttons: the tenant's backend posts the decision here after acting on a `self_service.request.submitted` event. Validation, merge, offer or invitation creation, status transition and pub-sub all live in the selfservice package — this handler is a thin auth + scope check (`self_service`).

Endpoint: POST /b2b/v1/self-service/requests/{requestId}/decision
Version: 1.0.0
Security: BearerAuth

## Security:

  - `BearerAuth` (unknown)
    http bearer JWT

## Path parameters:

  - `requestId` (string, required)

## Header parameters:

  - `X-Org-Id` (string, required)
    Organization the call is acting on. The authenticated service user must be a member of this organization in DeepAdmin; otherwise the request returns 404.

  - `X-Environment` (string, required)
    Environment the call is scoped to. Resources are isolated per environment.

## Request fields (application/json):

  - `admin_claims` (object)
    Optional in the contract because configs with no admin-filled claims approve without one. The server-side coverage check (selfservice package) is what enforces presence when the config does have admin-filled keys — a missing key returns InvalidArgument. Wrapped in Option so the generated OpenAPI spec marks it optional; a plain json.RawMessage gets emitted as required by Encore regardless of json:omitempty.

  - `decision` (string, required)
    "approve" or "reject".

  - `reason` (string)
    Required on reject. Stored as the request's rejection_reason and shown to the end-user in the rejection email.

## Response 200:

  - `200` (unknown)
    Success response

## Response 200 fields (application/json):

  - `offer_id` (string, required)
    UUID v4 identifier.
    Example: 550e8400-e29b-41d4-a716-446655440000

  - `request_id` (string, required)
    UUID v4 identifier.
    Example: 550e8400-e29b-41d4-a716-446655440000

  - `status` (string, required)

## Response 400:

  - `400` (unknown)
    Invalid request. Common causes: missing or malformed X-Org-Id / X-Environment headers, or a missing required field in the request body.

## Response 400 fields (application/json):

  - `code` (string, required)
    Machine-readable error code.

  - `message` (string, required)
    Human-readable error description.

  - `details` (object)
    Optional structured data with additional context.

## Response 401:

  - `401` (unknown)
    Unauthenticated. The Bearer token failed validation (signature, issuer, audience, or expiry).

## Response 401 fields (application/json):

  - `code` (string, required)
    Machine-readable error code.

  - `message` (string, required)
    Human-readable error description.

  - `details` (object)
    Optional structured data with additional context.

## Response 403:

  - `403` (unknown)
    Permission denied. The token does not carry the scope required by this endpoint. Check the `scope` claim on the token you received from the DeepCloud SSO token endpoint.

## Response 403 fields (application/json):

  - `code` (string, required)
    Machine-readable error code.

  - `message` (string, required)
    Human-readable error description.

  - `details` (object)
    Optional structured data with additional context.

## Response 404:

  - `404` (unknown)
    Resource not found. Either the resource ID is unknown, or the X-Org-Id you supplied is not an organization the authenticated service user is a member of.

## Response 404 fields (application/json):

  - `code` (string, required)
    Machine-readable error code.

  - `message` (string, required)
    Human-readable error description.

  - `details` (object)
    Optional structured data with additional context.

## Response 429:

  - `429` (unknown)
    Rate limit exceeded.

## Response 429 fields (application/json):

  - `code` (string, required)
    Machine-readable error code.

  - `message` (string, required)
    Human-readable error description.

  - `details` (object)
    Optional structured data with additional context.

## Response 500:

  - `500` (unknown)
    Internal server error.

## Response 500 fields (application/json):

  - `code` (string, required)
    Machine-readable error code.

  - `message` (string, required)
    Human-readable error description.

  - `details` (object)
    Optional structured data with additional context.

