{
  "openapi": "3.0.3",
  "info": {
    "title": "Axiom API 0.1.1 - Bootstrap And Tenant Context",
    "description": "Authentication bootstrap, admitted tenant discovery, and tenant-context setup.",
    "version": "0.1.1",
    "contact": {
      "name": "Axiom Platform Team",
      "email": "hello@axiom.express"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://axiom.express/license"
    }
  },
  "servers": [
    {
      "url": "https://api.afr-dev.axiom.express",
      "description": "Africa developer preview"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Identity",
      "description": "Authenticated actor, admitted tenant discovery, and tenant-context bootstrap.\n\nPublic maturity: Developer preview. This surface is available to admitted alpha consumers when their issued access pack grants authority; breaking changes remain possible before 1.0.0.",
      "x-axiom-public-maturity": {
        "availability": "developer-preview",
        "stability": "evolving",
        "response_profile": "endpoint-specific",
        "usage": "available",
        "published": true,
        "authorisation": "requires-issued-alpha-access-pack",
        "alpha_access_required": true,
        "production_ready": false,
        "note": "Available to admitted alpha consumers when their issued access pack grants authority; breaking changes remain possible before 1.0.0."
      }
    }
  ],
  "paths": {
    "/v1/me/tenants": {
      "get": {
        "operationId": "getMeTenants",
        "tags": [
          "Identity"
        ],
        "x-axiom-wire-success-profile": "json-api",
        "summary": "List admitted tenants",
        "description": "Returns the tenants admitted for the authenticated actor. Use the returned tenant selection data to request a server-minted tenant context.",
        "responses": {
          "200": {
            "description": "Admitted tenant list for the authenticated actor.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessEnvelope"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data",
                        "status"
                      ],
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "granting_role"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "typed-prefix-id",
                                "pattern": "^tnt_[0-9A-HJKMNP-TV-Z]{26}$",
                                "description": "Tenant identifier admitted for this authenticated actor.",
                                "example": "tnt_01ARZ3NDEKTSV4RRFFQ69G5FAV",
                                "x-axiom-identifier-shape": "typed-prefix"
                              },
                              "name": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 255,
                                "description": "Tenant display name.",
                                "example": "Example Tenant"
                              },
                              "granting_role": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128,
                                "description": "Role granting access to the tenant.",
                                "example": "tenant_operator"
                              }
                            }
                          }
                        },
                        "meta": {
                          "type": "object",
                          "additionalProperties": false,
                          "properties": {
                            "total": {
                              "type": "integer",
                              "minimum": 0,
                              "description": "Number of admitted tenants returned."
                            }
                          }
                        }
                      },
                      "additionalProperties": true
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Bearer token missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "No tenant admission is available for this actor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "x-axiom-public-maturity": {
          "availability": "developer-preview",
          "stability": "evolving",
          "response_profile": "json-api",
          "usage": "available",
          "published": true,
          "authorisation": "requires-issued-alpha-access-pack",
          "alpha_access_required": true,
          "production_ready": false,
          "note": "Available to admitted alpha consumers when their issued access pack grants authority; breaking changes remain possible before 1.0.0."
        },
        "x-axiom-contract-consistency": {
          "response_profile": "json-api",
          "error_profile": "json-api",
          "pagination_profile": "not-list",
          "filter_profile": "none"
        },
        "x-axiom-pagination-contract": {
          "profile": "not-list",
          "request_parameters": [],
          "consumer_posture": "not-list"
        },
        "x-axiom-filter-contract": {
          "profile": "none",
          "filter_parameters": []
        },
        "x-axiom-auth-contract": {
          "bearer": "required",
          "scope_profile": "none",
          "scopes": [],
          "required_permissions": [],
          "permission_runtime_posture": "alpha-posture",
          "tenant_context": "bootstrap-not-required",
          "tenant_context_authority": "server-minted-X-Tenant-Context",
          "client_supplied_tenant_id_authority": "forbidden",
          "failure_order": [
            "bearer-authentication",
            "admitted-tenant-authorisation"
          ]
        },
        "x-axiom-operational-limits": {
          "upload": {
            "mode": "not-upload"
          },
          "rate_limit": {
            "posture": "not-published",
            "exception": "API 0.1.1 does not publish a per-operation rate-limit commitment."
          }
        },
        "x-axiom-operation-safety": {
          "mutation": false,
          "read_allowed": true,
          "write_allowed": false,
          "agent_invocation": "bootstrap-read",
          "tenant_context": "bootstrap-not-required",
          "idempotency_required": false,
          "retry_automation": "safe-read-policy-required",
          "source": "generated-public-openapi-profile"
        }
      }
    },
    "/v1/me/tenant-context": {
      "post": {
        "operationId": "postMeTenantContext",
        "tags": [
          "Identity"
        ],
        "x-axiom-wire-success-profile": "json-api",
        "summary": "Mint tenant context",
        "description": "Mints a server-authoritative tenant-context token for one admitted tenant. Use that token as the X-Tenant-Context header on tenant-scoped API calls.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "tenant_id"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "string",
                    "format": "typed-prefix-id",
                    "pattern": "^tnt_[0-9A-HJKMNP-TV-Z]{26}$",
                    "description": "Tenant identifier selected from GET /v1/me/tenants.",
                    "example": "tnt_01ARZ3NDEKTSV4RRFFQ69G5FAV",
                    "x-axiom-identifier-shape": "typed-prefix"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tenant context minted for an admitted tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessEnvelope"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data",
                        "status"
                      ],
                      "properties": {
                        "data": {
                          "type": "object",
                          "additionalProperties": false,
                          "required": [
                            "tenant_context_token",
                            "tenant_id",
                            "expires_at"
                          ],
                          "properties": {
                            "tenant_context_token": {
                              "type": "string",
                              "minLength": 1,
                              "description": "Server-minted token for X-Tenant-Context on tenant-scoped requests.",
                              "example": "<server-minted tenant-context token>"
                            },
                            "tenant_id": {
                              "type": "string",
                              "format": "typed-prefix-id",
                              "pattern": "^tnt_[0-9A-HJKMNP-TV-Z]{26}$",
                              "description": "Tenant identifier bound into the token.",
                              "example": "tnt_01ARZ3NDEKTSV4RRFFQ69G5FAV",
                              "x-axiom-identifier-shape": "typed-prefix"
                            },
                            "expires_at": {
                              "type": "string",
                              "format": "date-time",
                              "description": "UTC expiry timestamp.",
                              "example": "2026-08-10T12:00:00Z"
                            }
                          }
                        }
                      },
                      "additionalProperties": true
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Tenant selection payload is missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Bearer token missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The selected tenant is not admitted for this actor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "x-axiom-public-maturity": {
          "availability": "developer-preview",
          "stability": "evolving",
          "response_profile": "json-api",
          "usage": "available",
          "published": true,
          "authorisation": "requires-issued-alpha-access-pack",
          "alpha_access_required": true,
          "production_ready": false,
          "note": "Available to admitted alpha consumers when their issued access pack grants authority; breaking changes remain possible before 1.0.0."
        },
        "x-axiom-contract-consistency": {
          "response_profile": "json-api",
          "error_profile": "json-api",
          "pagination_profile": "not-list",
          "filter_profile": "none"
        },
        "x-axiom-pagination-contract": {
          "profile": "not-list",
          "request_parameters": [],
          "consumer_posture": "not-list"
        },
        "x-axiom-filter-contract": {
          "profile": "none",
          "filter_parameters": []
        },
        "x-axiom-auth-contract": {
          "bearer": "required",
          "scope_profile": "none",
          "scopes": [],
          "required_permissions": [],
          "permission_runtime_posture": "alpha-posture",
          "tenant_context": "bootstrap-not-required",
          "tenant_context_authority": "server-minted-X-Tenant-Context",
          "client_supplied_tenant_id_authority": "forbidden",
          "failure_order": [
            "bearer-authentication",
            "admitted-tenant-authorisation"
          ]
        },
        "x-axiom-operational-limits": {
          "upload": {
            "mode": "not-upload"
          },
          "rate_limit": {
            "posture": "not-published",
            "exception": "API 0.1.1 does not publish a per-operation rate-limit commitment."
          }
        },
        "x-axiom-operation-safety": {
          "mutation": true,
          "read_allowed": false,
          "write_allowed": false,
          "agent_invocation": "bootstrap-mint-restricted",
          "tenant_context": "bootstrap-not-required",
          "idempotency_required": true,
          "retry_automation": "forbidden-for-mutation",
          "source": "generated-public-openapi-profile"
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT token obtained from authentication service"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "status",
          "title"
        ],
        "properties": {
          "status": {
            "type": "string",
            "description": "HTTP status code as a string",
            "example": "422",
            "x-axiom-coded-value-classification": "platform-http-status-code"
          },
          "code": {
            "type": "string",
            "description": "Application-specific error code",
            "example": "VALIDATION_ERROR",
            "pattern": "^[A-Z][A-Z0-9_]*$"
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary of the error",
            "example": "Validation Error"
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation of the error",
            "example": "Field 'policy_number' is required"
          },
          "help_url": {
            "type": "string",
            "format": "uri",
            "description": "Documentation URL for this error code",
            "example": "https://developers.afr-dev.axiom.express/api/reference/0.1.1/errors/VALIDATION_ERROR/"
          },
          "source": {
            "$ref": "#/components/schemas/ErrorSource"
          },
          "meta": {
            "type": "object",
            "additionalProperties": true,
            "description": "Additional error metadata"
          }
        },
        "additionalProperties": false
      },
      "ErrorMeta": {
        "type": "object",
        "properties": {
          "correlation_id": {
            "type": "string",
            "description": "Request correlation ID for support reference",
            "example": "req-abc-123-def-456",
            "x-axiom-identifier-classification": "correlation-id",
            "x-axiom-identifier-shape": "alpha-exception",
            "x-axiom-identifier-alpha-exception": "API 0.1.1 preserves this identifier as a named alpha/operational exception until the owning runtime contract migrates to a canonical typed-prefix or UUID wire shape."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the error occurred",
            "example": "2026-02-07T12:00:00Z"
          },
          "request_id": {
            "type": "string",
            "description": "Unique request identifier",
            "example": "req-789-ghi",
            "x-axiom-identifier-classification": "request-id",
            "x-axiom-identifier-shape": "alpha-exception",
            "x-axiom-identifier-alpha-exception": "API 0.1.1 preserves this identifier as a named alpha/operational exception until the owning runtime contract migrates to a canonical typed-prefix or UUID wire shape."
          }
        },
        "additionalProperties": false
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Error"
            },
            "description": "Array of error objects"
          },
          "meta": {
            "$ref": "#/components/schemas/ErrorMeta"
          }
        },
        "additionalProperties": false
      },
      "ErrorSource": {
        "type": "object",
        "properties": {
          "pointer": {
            "type": "string",
            "description": "JSON Pointer to the field that caused the error",
            "example": "/data/attributes/policy_number"
          },
          "parameter": {
            "type": "string",
            "description": "Query parameter that caused the error",
            "example": "filter[status]"
          },
          "header": {
            "type": "string",
            "description": "Header that caused the error",
            "example": "X-Tenant-Context"
          }
        },
        "additionalProperties": false
      },
      "SuccessEnvelope": {
        "type": "object",
        "required": [
          "data",
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Always the literal string 'success' for successful responses. This invariant is established here and must not be overridden by any operation's response schema."
          },
          "data": {
            "description": "Operation-specific payload. Overridden per-endpoint via allOf composition (e.g. PartyResponse = allOf:[SuccessEnvelope, {data: Party}]). A caller holding a bare SuccessEnvelope-typed reference sees data as unknown/Any \u2014 hold the op-specific composed type (e.g. PartyResponse) to get the typed data."
          },
          "message": {
            "type": "string",
            "description": "Optional human-readable message. Present when supplied by the API."
          },
          "meta": {
            "type": "object",
            "description": "Optional response metadata (pagination, request echo). Present when supplied by the API.",
            "additionalProperties": true
          },
          "links": {
            "type": "object",
            "description": "Optional hypermedia links. Present when supplied by the API.",
            "additionalProperties": true
          },
          "telemetry": {
            "type": "object",
            "description": "Response telemetry block under the governed contract. Present on every wrapped success response. Contains timing and trace fields (total_ms, handler_ms, idempotency_replayed, trace_id).",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      }
    }
  },
  "x-axiom-schema-contract": {
    "schema_version": "axiom.public-schema-contract.v1",
    "posture": "classified-alpha-baseline",
    "component_schema_count": 5,
    "object_shape": {
      "closed_object_count": 4,
      "open_extension_object_count": 5,
      "open_object_gap_count": 0,
      "posture": "closed-or-intentional-open"
    },
    "identifier_shape": {
      "typed_id_reference_count": 0,
      "format_constrained_id_count": 0,
      "classified_id_string_count": 2,
      "untyped_id_string_count": 0,
      "posture": "classified-or-constrained"
    },
    "money_shape": {
      "shared_money_reference_count": 0,
      "classified_money_like_count": 0,
      "inline_money_like_count": 0,
      "posture": "shared-money-or-classified"
    },
    "coded_values": {
      "enum_string_count": 1,
      "classified_code_string_count": 1,
      "unconstrained_code_string_count": 0,
      "posture": "enum-or-classified-catalogue"
    }
  }
}
