{
  "openapi": "3.1.0",
  "info": {
    "title": "Piipe Host JSON API",
    "version": "1.0",
    "description": "Implemented JSON API for a backend application to establish an organisation-scoped Piipe service session and perform bounded identity operations. POST /api/login is application authentication, not human sign-in: it accepts an opaque organization_id, App ID and client secret and always issues the organisation's fixed piipe-api writer principal. Numeric internal tenant IDs and human usernames are not login inputs. The opaque tenant_session is carried in subsequent JSON request bodies."
  },
  "externalDocs": {
    "description": "Piipe developer guide",
    "url": "/developers/"
  },
  "servers": [
    {
      "url": "https://api.piipe.io",
      "description": "Piipe production application API"
    }
  ],
  "tags": [
    {
      "name": "Application session",
      "description": "Authenticate and inspect the fixed organisation application principal."
    },
    {
      "name": "Protected identity",
      "description": "Search, add, retrieve, edit and delete through the authenticated Piipe path."
    }
  ],
  "paths": {
    "/api/login": {
      "post": {
        "operationId": "createApplicationSession",
        "tags": [
          "Application session"
        ],
        "summary": "Create an application service session",
        "description": "Exchanges the organisation's opaque public ID, App ID and client secret for an eight-hour opaque session. The session is always bound to the fixed piipe-api writer principal and its shared rate buckets. The endpoint does not accept tenant_id, username, email or another human selector and cannot impersonate a human membership.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApplicationLoginRequest"
              },
              "examples": {
                "applicationLogin": {
                  "summary": "Server-side application login",
                  "value": {
                    "organization_id": "org_exampleOpaqueId",
                    "app_id": 42,
                    "client_secret": "<secret-manager-value>"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Application session created for the fixed piipe-api writer principal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationLoginResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/AuthenticationRateLimited"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-principal": "piipe-api",
        "x-piipe-principal-role": "writer",
        "x-piipe-human-impersonation": "forbidden",
        "x-piipe-session-ttl-seconds": 28800
      }
    },
    "/api/current-tenant": {
      "post": {
        "operationId": "getCurrentApplicationOrganisation",
        "tags": [
          "Application session"
        ],
        "summary": "Inspect the current application scope",
        "description": "Validates the opaque application session and returns its organisation and fixed piipe-api principal. The client cannot select another organisation in this request.",
        "requestBody": {
          "$ref": "#/components/requestBodies/TenantSession"
        },
        "responses": {
          "200": {
            "description": "Current organisation and application principal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CurrentTenantResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session"
      }
    },
    "/api/logout": {
      "post": {
        "operationId": "revokeApplicationSession",
        "tags": [
          "Application session"
        ],
        "summary": "Revoke an application session",
        "description": "Invalidates the supplied opaque tenant_session. Logout is idempotent and does not rotate the organisation's application credential.",
        "requestBody": {
          "$ref": "#/components/requestBodies/TenantSession"
        },
        "responses": {
          "200": {
            "description": "Logout accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OkResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session"
      }
    },
    "/api/subject-token": {
      "post": {
        "operationId": "searchProtectedIdentity",
        "tags": [
          "Protected identity"
        ],
        "summary": "Search an exact organisation-scoped subject",
        "description": "Derives the organisation-scoped token and confirms whether the protected identity exists without returning PII. The Search Piipe Control and the fixed piipe-api principal's rate limit remain authoritative.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubjectTokenRequest"
              },
              "examples": {
                "customerReference": {
                  "value": {
                    "tenant_session": "<opaque-session>",
                    "subject": "crm_customer_12345",
                    "subject_type": "customer_id"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search completed. exists is false when no active protected identity is present.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubjectTokenResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "423": {
            "$ref": "#/components/responses/PiipeClosed"
          },
          "429": {
            "$ref": "#/components/responses/ServicePrincipalRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PiipeScheduleUnavailable"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session",
        "x-piipe-required-controls": [
          "search"
        ],
        "x-piipe-rate-limits": {
          "principal": "piipe-api",
          "window_seconds": 60,
          "all_operations": 60
        }
      }
    },
    "/api/write": {
      "post": {
        "operationId": "addProtectedIdentity",
        "tags": [
          "Protected identity"
        ],
        "summary": "Add protected identity fields",
        "description": "Adds up to three supported named fields. Exact subject mode uses the organisation-scoped customer reference. Duplicate adds preserve the existing protected identity and do not return its field values. Search and Add Piipe Controls remain authoritative.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NamedFieldWriteRequest"
              },
              "examples": {
                "addCustomerIdentity": {
                  "value": {
                    "tenant_session": "<opaque-session>",
                    "lookup": "subject",
                    "subject": "crm_customer_12345",
                    "subject_type": "customer_id",
                    "record_mode": "fields",
                    "field_data": {
                      "email": "sample@example.test",
                      "phone": "+61000000000"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ProtectedIdentityOperation"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "423": {
            "$ref": "#/components/responses/PiipeClosed"
          },
          "429": {
            "$ref": "#/components/responses/ServicePrincipalRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PiipeScheduleUnavailable"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session",
        "x-piipe-required-controls": [
          "search",
          "add"
        ],
        "x-piipe-retry-policy": "do-not-automatically-retry-after-an-ambiguous-network-failure",
        "x-piipe-rate-limits": {
          "principal": "piipe-api",
          "window_seconds": 60,
          "all_operations": 60,
          "mutations": 20
        }
      }
    },
    "/api/read": {
      "post": {
        "operationId": "retrieveProtectedIdentityFields",
        "tags": [
          "Protected identity"
        ],
        "summary": "Retrieve explicitly requested fields",
        "description": "Retrieves only the requested supported fields. Subject lookup also requires Search; every retrieval requires the Retrieve Piipe Control.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NamedFieldReadRequest"
              },
              "examples": {
                "retrieveEmailAndPhone": {
                  "value": {
                    "tenant_session": "<opaque-session>",
                    "lookup": "subject",
                    "subject": "crm_customer_12345",
                    "subject_type": "customer_id",
                    "record_mode": "fields",
                    "fields": "email,phone"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ProtectedIdentityOperation"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "423": {
            "$ref": "#/components/responses/PiipeClosed"
          },
          "429": {
            "$ref": "#/components/responses/ServicePrincipalRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PiipeScheduleUnavailable"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session",
        "x-piipe-required-controls": [
          "retrieve",
          "search when lookup is subject"
        ],
        "x-piipe-rate-limits": {
          "principal": "piipe-api",
          "window_seconds": 60,
          "all_operations": 60
        }
      }
    },
    "/api/update": {
      "post": {
        "operationId": "editProtectedIdentity",
        "tags": [
          "Protected identity"
        ],
        "summary": "Replace protected identity fields",
        "description": "Intentionally replaces the active named-field manifest. The current encrypted field workflow requires Search, Add and Edit because new ciphertext shards are added before the manifest pointer moves.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NamedFieldWriteRequest"
              },
              "examples": {
                "editCustomerIdentity": {
                  "value": {
                    "tenant_session": "<opaque-session>",
                    "lookup": "subject",
                    "subject": "crm_customer_12345",
                    "subject_type": "customer_id",
                    "record_mode": "fields",
                    "field_data": {
                      "email": "updated@example.test",
                      "phone": "+61000000000"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ProtectedIdentityOperation"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "423": {
            "$ref": "#/components/responses/PiipeClosed"
          },
          "429": {
            "$ref": "#/components/responses/ServicePrincipalRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PiipeScheduleUnavailable"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session",
        "x-piipe-required-controls": [
          "search",
          "add",
          "edit"
        ],
        "x-piipe-retry-policy": "do-not-automatically-retry-after-an-ambiguous-network-failure",
        "x-piipe-rate-limits": {
          "principal": "piipe-api",
          "window_seconds": 60,
          "all_operations": 60,
          "mutations": 20
        }
      }
    },
    "/api/delete": {
      "post": {
        "operationId": "deleteProtectedIdentity",
        "tags": [
          "Protected identity"
        ],
        "summary": "Logically delete a protected identity",
        "description": "Writes a logical tombstone through the Delete path. Subject lookup also requires Search. A successful response is not a claim of immediate physical erasure from flash media or historical copies.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteRequest"
              },
              "examples": {
                "deleteCustomerIdentity": {
                  "value": {
                    "tenant_session": "<opaque-session>",
                    "lookup": "subject",
                    "subject": "crm_customer_12345",
                    "subject_type": "customer_id",
                    "record_mode": "fields"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ProtectedIdentityOperation"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/RequestTimeout"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "423": {
            "$ref": "#/components/responses/PiipeClosed"
          },
          "429": {
            "$ref": "#/components/responses/ServicePrincipalRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PiipeScheduleUnavailable"
          }
        },
        "x-piipe-api-status": "implemented",
        "x-piipe-session-location": "body.tenant_session",
        "x-piipe-required-controls": [
          "delete",
          "search when lookup is subject"
        ],
        "x-piipe-retry-policy": "do-not-automatically-retry-after-an-ambiguous-network-failure",
        "x-piipe-rate-limits": {
          "principal": "piipe-api",
          "window_seconds": 60,
          "all_operations": 60,
          "deletes": 5
        }
      }
    }
  },
  "components": {
    "requestBodies": {
      "TenantSession": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/TenantSessionRequest"
            }
          }
        }
      }
    },
    "responses": {
      "ProtectedIdentityOperation": {
        "description": "The operation reached the Piipe response path. A missing or policy-denied protected identity may be represented by ok false inside this HTTP 200 envelope; inspect response.status and response.decision.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProtectedIdentityOperationResponse"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Malformed, missing or unsupported request data.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Application credentials or the opaque tenant_session are invalid, expired, revoked or no longer authorised.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The principal is not permitted to perform the operation, or the browser origin policy rejected the request.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RequestTimeout": {
        "description": "The bounded request body was not received before the server timeout.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Every documented endpoint requires Content-Type application/json.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "API requests require application/json",
              "error_type": "UnsupportedMediaTypeError"
            }
          }
        }
      },
      "PiipeClosed": {
        "description": "The required global or organisation Piipe Control is closed. The closure is hardware-confirmed and applies to existing sessions.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PiipeClosedError"
            },
            "example": {
              "ok": false,
              "error": "Piipe Search is closed",
              "error_type": "PipeClosedError",
              "source": "fpga",
              "hardware_confirmed": true
            }
          }
        }
      },
      "ServicePrincipalRateLimited": {
        "description": "The fixed piipe-api principal exhausted an applicable request, mutation or delete budget.",
        "headers": {
          "Retry-After": {
            "required": true,
            "description": "Seconds until the current 60-second window resets.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RateLimitError"
            }
          }
        }
      },
      "AuthenticationRateLimited": {
        "description": "The source exhausted the public authentication attempt budget.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PiipeScheduleUnavailable": {
        "description": "A due organisation Piipe schedule could not be confirmed in hardware, so the affected operation stopped safely.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PiipeScheduleError"
            }
          }
        }
      }
    },
    "schemas": {
      "ApplicationLoginRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "organization_id",
          "app_id",
          "client_secret"
        ],
        "properties": {
          "organization_id": {
            "type": "string",
            "pattern": "^org_[A-Za-z0-9_-]+$",
            "minLength": 8,
            "maxLength": 160,
            "description": "Opaque customer-visible Piipe organisation ID. This is not the internal numeric tenant slot."
          },
          "app_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 65535
          },
          "client_secret": {
            "type": "string",
            "minLength": 32,
            "maxLength": 256,
            "writeOnly": true,
            "description": "High-entropy value shown once to the organisation owner and stored by the caller's secret manager."
          }
        }
      },
      "TenantSessionRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "tenant_session"
        ],
        "properties": {
          "tenant_session": {
            "$ref": "#/components/schemas/TenantSession"
          }
        }
      },
      "SubjectTokenRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "tenant_session",
          "subject"
        ],
        "properties": {
          "tenant_session": {
            "$ref": "#/components/schemas/TenantSession"
          },
          "subject": {
            "$ref": "#/components/schemas/Subject"
          },
          "subject_type": {
            "$ref": "#/components/schemas/SubjectType"
          }
        }
      },
      "NamedFieldWriteRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "tenant_session",
          "lookup",
          "record_mode",
          "field_data"
        ],
        "properties": {
          "tenant_session": {
            "$ref": "#/components/schemas/TenantSession"
          },
          "lookup": {
            "$ref": "#/components/schemas/LookupMode"
          },
          "subject": {
            "$ref": "#/components/schemas/Subject"
          },
          "subject_type": {
            "$ref": "#/components/schemas/SubjectType"
          },
          "token": {
            "$ref": "#/components/schemas/RecordToken"
          },
          "record_mode": {
            "type": "string",
            "const": "fields"
          },
          "field_data": {
            "$ref": "#/components/schemas/NamedFieldData"
          }
        },
        "oneOf": [
          {
            "required": [
              "subject"
            ],
            "properties": {
              "lookup": {
                "const": "subject"
              }
            }
          },
          {
            "required": [
              "token"
            ],
            "properties": {
              "lookup": {
                "const": "token"
              }
            }
          }
        ]
      },
      "NamedFieldReadRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "tenant_session",
          "lookup",
          "record_mode",
          "fields"
        ],
        "properties": {
          "tenant_session": {
            "$ref": "#/components/schemas/TenantSession"
          },
          "lookup": {
            "$ref": "#/components/schemas/LookupMode"
          },
          "subject": {
            "$ref": "#/components/schemas/Subject"
          },
          "subject_type": {
            "$ref": "#/components/schemas/SubjectType"
          },
          "token": {
            "$ref": "#/components/schemas/RecordToken"
          },
          "record_mode": {
            "type": "string",
            "const": "fields"
          },
          "fields": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Comma-separated supported field names or all.",
            "examples": [
              "email,phone"
            ]
          }
        },
        "oneOf": [
          {
            "required": [
              "subject"
            ],
            "properties": {
              "lookup": {
                "const": "subject"
              }
            }
          },
          {
            "required": [
              "token"
            ],
            "properties": {
              "lookup": {
                "const": "token"
              }
            }
          }
        ]
      },
      "DeleteRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "tenant_session",
          "lookup"
        ],
        "properties": {
          "tenant_session": {
            "$ref": "#/components/schemas/TenantSession"
          },
          "lookup": {
            "$ref": "#/components/schemas/LookupMode"
          },
          "subject": {
            "$ref": "#/components/schemas/Subject"
          },
          "subject_type": {
            "$ref": "#/components/schemas/SubjectType"
          },
          "token": {
            "$ref": "#/components/schemas/RecordToken"
          },
          "record_mode": {
            "type": "string",
            "const": "fields",
            "default": "fields"
          }
        },
        "oneOf": [
          {
            "required": [
              "subject"
            ],
            "properties": {
              "lookup": {
                "const": "subject"
              }
            }
          },
          {
            "required": [
              "token"
            ],
            "properties": {
              "lookup": {
                "const": "token"
              }
            }
          }
        ]
      },
      "NamedFieldData": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "maxProperties": 3,
        "properties": {
          "email": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "dob": {
            "type": "string"
          },
          "document": {
            "type": "string"
          }
        },
        "description": "One to three supported direct-identity fields. Each encoded name=value pair must fit the current bounded encrypted record payload."
      },
      "LookupMode": {
        "type": "string",
        "enum": [
          "subject",
          "token"
        ]
      },
      "Subject": {
        "type": "string",
        "minLength": 1,
        "maxLength": 1024,
        "description": "Stable application-owned customer reference or another deliberately selected exact subject. Avoid using raw PII when a non-PII customer reference is available."
      },
      "SubjectType": {
        "type": "string",
        "minLength": 1,
        "maxLength": 64,
        "examples": [
          "customer_id"
        ]
      },
      "RecordToken": {
        "type": "integer",
        "minimum": 0,
        "maximum": 4294967295
      },
      "TenantSession": {
        "type": "string",
        "minLength": 32,
        "maxLength": 256,
        "description": "Opaque bearer-like application session returned by POST /api/login. Send only in the JSON body and never log or place it in a URL."
      },
      "OkResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          }
        }
      },
      "ApplicationLoginResponse": {
        "type": "object",
        "required": [
          "ok",
          "session",
          "expires_at",
          "tenant",
          "user"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "session": {
            "$ref": "#/components/schemas/TenantSession"
          },
          "expires_at": {
            "type": "integer",
            "description": "Unix timestamp at which the session expires."
          },
          "tenant": {
            "$ref": "#/components/schemas/PublicOrganisation"
          },
          "user": {
            "$ref": "#/components/schemas/ApplicationPrincipal"
          }
        }
      },
      "CurrentTenantResponse": {
        "type": "object",
        "required": [
          "ok",
          "tenant"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "tenant": {
            "$ref": "#/components/schemas/PublicOrganisation"
          }
        }
      },
      "PublicOrganisation": {
        "type": "object",
        "description": "Public organisation context. Internal protocol fields may be present in the service response but are not login inputs or authority supplied by the client.",
        "required": [
          "organization_id",
          "name",
          "app_id"
        ],
        "properties": {
          "organization_id": {
            "type": "string",
            "pattern": "^org_[A-Za-z0-9_-]+$"
          },
          "name": {
            "type": "string"
          },
          "app_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 65535
          },
          "current_user": {
            "$ref": "#/components/schemas/ApplicationPrincipal"
          },
          "plan_tier_id": {
            "type": "string"
          },
          "protected_identity_count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "additionalProperties": true
      },
      "ApplicationPrincipal": {
        "type": "object",
        "required": [
          "username",
          "principal_type",
          "role",
          "status",
          "piipe_access_enabled"
        ],
        "properties": {
          "username": {
            "type": "string",
            "const": "piipe-api"
          },
          "principal_type": {
            "type": "string",
            "const": "application"
          },
          "role": {
            "type": "string",
            "const": "writer"
          },
          "status": {
            "type": "string",
            "const": "active"
          },
          "access": {
            "type": "string",
            "const": "tenant_authorized"
          },
          "piipe_access_enabled": {
            "type": "boolean"
          },
          "credential_status": {
            "type": "string",
            "const": "application_credential"
          }
        },
        "additionalProperties": true
      },
      "SubjectTokenResponse": {
        "type": "object",
        "required": [
          "ok",
          "canonical_subject",
          "token",
          "token_hex",
          "exists",
          "search_status"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "canonical_subject": {
            "type": "string"
          },
          "token": {
            "$ref": "#/components/schemas/RecordToken"
          },
          "token_hex": {
            "type": "string",
            "pattern": "^0x[0-9a-f]{8}$"
          },
          "exists": {
            "type": "boolean"
          },
          "search_status": {
            "type": "string",
            "enum": [
              "OK",
              "NOT_FOUND"
            ]
          },
          "tenant_context": {
            "$ref": "#/components/schemas/PublicOrganisation"
          }
        },
        "additionalProperties": true
      },
      "ProtectedIdentityOperationResponse": {
        "type": "object",
        "required": [
          "ok",
          "response"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "response": {
            "type": "object",
            "description": "Integrity-checked Piipe operation result. Inspect status, decision and explicitly requested fields.",
            "properties": {
              "status": {
                "type": "string"
              },
              "decision": {
                "type": "string"
              },
              "record_format": {
                "type": "string"
              },
              "fields": {
                "$ref": "#/components/schemas/NamedFieldData"
              },
              "duplicate": {
                "type": "boolean"
              },
              "existing_token": {
                "$ref": "#/components/schemas/RecordToken"
              },
              "derived_token": {
                "$ref": "#/components/schemas/RecordToken"
              },
              "request_id": {
                "type": "integer"
              },
              "audit_id": {
                "type": "integer"
              }
            },
            "additionalProperties": true
          },
          "rate_limit": {
            "$ref": "#/components/schemas/RateLimitUsage"
          }
        },
        "additionalProperties": true
      },
      "RateLimitUsage": {
        "type": "object",
        "required": [
          "used",
          "limit",
          "remaining",
          "window_seconds",
          "resets_at",
          "policies"
        ],
        "properties": {
          "used": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "const": 60
          },
          "remaining": {
            "type": "integer",
            "minimum": 0
          },
          "window_seconds": {
            "type": "integer",
            "const": 60
          },
          "resets_at": {
            "type": "integer"
          },
          "policies": {
            "type": "object",
            "properties": {
              "all_operations": {
                "$ref": "#/components/schemas/RateLimitPolicy"
              },
              "mutations": {
                "$ref": "#/components/schemas/RateLimitPolicy"
              },
              "deletes": {
                "$ref": "#/components/schemas/RateLimitPolicy"
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": true
      },
      "RateLimitPolicy": {
        "type": "object",
        "required": [
          "used",
          "limit",
          "remaining"
        ],
        "properties": {
          "used": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "minimum": 1
          },
          "remaining": {
            "type": "integer",
            "minimum": 0
          }
        },
        "additionalProperties": false
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "ok",
          "error",
          "error_type"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "error_type": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "PiipeClosedError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "error",
          "error_type",
          "source",
          "hardware_confirmed"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "error_type": {
            "type": "string",
            "const": "PipeClosedError"
          },
          "source": {
            "type": "string",
            "const": "fpga"
          },
          "hardware_confirmed": {
            "type": "boolean",
            "const": true
          }
        }
      },
      "RateLimitError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "error",
          "error_type",
          "rate_limit"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "error_type": {
            "type": "string",
            "const": "RateLimitError"
          },
          "rate_limit": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "scope",
              "limit",
              "remaining",
              "window_seconds",
              "resets_at",
              "retry_after"
            ],
            "properties": {
              "scope": {
                "type": "string",
                "enum": [
                  "user",
                  "application",
                  "mutation",
                  "delete"
                ]
              },
              "limit": {
                "type": "integer",
                "minimum": 1
              },
              "remaining": {
                "type": "integer",
                "const": 0
              },
              "window_seconds": {
                "type": "integer",
                "const": 60
              },
              "resets_at": {
                "type": "integer"
              },
              "retry_after": {
                "type": "integer",
                "minimum": 1
              }
            }
          }
        }
      },
      "PiipeScheduleError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "error",
          "error_type",
          "source",
          "hardware_confirmed"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "error_type": {
            "type": "string",
            "const": "PipeScheduleEnforcementError"
          },
          "source": {
            "type": "string",
            "const": "fpga_schedule"
          },
          "hardware_confirmed": {
            "type": "boolean",
            "const": false
          }
        }
      }
    }
  }
}
