{
  "openapi": "3.1.0",
  "info": {
    "title": "AgentPostage staging API",
    "version": "1.0.0",
    "description": "Test Mode only: test payments and provisional test credit. Letters use local simulation or LetterStream test preauthorization, held for authorization with no physical dispatch. No real mailing/delivery evidence, legal-effectiveness claims, or guaranteed delivery. Browser mutations require the application Origin. Agent keys cannot approve or cancel letters, manage keys or buy credit. Prepared content is immutable."
  },
  "servers": [
    {
      "url": "https://staging.agentpostage.com",
      "description": "Staging Test Mode: no physical mail; test payments only"
    }
  ],
  "paths": {
    "/v1/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Read the customer account and staging environment",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/balance": {
      "get": {
        "operationId": "getBalance",
        "summary": "Read available and reserved test credit",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/keys": {
      "get": {
        "operationId": "listKeys",
        "summary": "List named agent keys without raw secrets",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AgentKey"
                      }
                    }
                  },
                  "required": [
                    "keys"
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createKey",
        "summary": "Create a named agent key with a cumulative spend cap",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeyInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedKey"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/keys/{id}": {
      "delete": {
        "operationId": "revokeKey",
        "summary": "Revoke an agent key",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "revoked_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "revoked_at"
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/letters": {
      "post": {
        "operationId": "prepareLetter",
        "summary": "Prepare an immutable PDF and quote; does not send",
        "description": "Prepare immutable text-derived PDF and provisional test-credit quote. Maximum 10 preview pages and 24,000 printable ASCII characters plus line breaks. The server chooses simulation or letterstream_test. LetterStream Test Mode sends the synthetic PDF and addresses to the provider after human approval and a separate send request; coversheet=Y adds an address coversheet absent from the preview. No attachments or live dispatch.",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]+$"
            },
            "description": "Persist before calling. Reuse with an identical body for the same logical operation. Changed content with an existing key yields 409. Use separate keys for prepare and send."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LetterInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing letter returned for an idempotent retry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "201": {
            "description": "New immutable letter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listLetters",
        "summary": "List recent letters for this account",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Use next_cursor from the previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "letters": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Letter"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "letters",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/letters/{id}": {
      "get": {
        "operationId": "getLetter",
        "summary": "Read a letter, quote, status, events and evidence metadata",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/letters/{id}/pdf": {
      "get": {
        "operationId": "getLetterPDF",
        "summary": "Download the authenticated immutable PDF",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "PDF, private/no-store; no public document access.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "private, no-store"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/letters/{id}/approve": {
      "post": {
        "operationId": "approveLetter",
        "summary": "Human approval of exact PDF and quote; does not send",
        "description": "Customer browser session and same-origin mutation required. Agents cannot approve. The human must inspect the exact PDF and quoted amount. Expired or mismatched quotes are rejected. Before approving letterstream_test, the human must understand that the actual synthetic PDF and addresses will be submitted to LetterStream and an address coversheet absent from the preview will be added. This approves a test submission only, never physical dispatch.",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirmed": {
                    "type": "boolean",
                    "const": true
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000
                  }
                },
                "required": [
                  "confirmed",
                  "amount_cents"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/letters/{id}/send": {
      "post": {
        "operationId": "sendLetter",
        "summary": "Reserve credit and enqueue an approved letter once",
        "description": "Requires human approval, an unexpired provisional test-credit quote, available balance and sufficient key cap. Repeats return the existing letter. simulation completes locally as simulated. letterstream_test verifies provider Test Mode and zero provider funds before submitting with preauth=1 and coversheet=Y; a validated receipt completes as provider_test_held. No doauth/dispatch operation is called. Ambiguous submission becomes submission_unknown, keeping funds reserved without a blind retry. LetterStream limits single-file submissions to 50 batches per day; each provider-mode letter uses one batch.",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]+$"
            },
            "description": "Persist before calling. Reuse with an identical body for the same logical operation. Changed content with an existing key yields 409. Use separate keys for prepare and send."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Empty"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/letters/{id}/cancel": {
      "post": {
        "operationId": "cancelLetter",
        "summary": "Human cancellation before submission is claimed",
        "description": "Requires a customer session. Any queued reservation is released exactly once. Cancellation races with sender claim; a claimed submission cannot be cancelled.",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Empty"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/checkout": {
      "post": {
        "operationId": "createTestCheckout",
        "summary": "Create a hosted test payment checkout",
        "description": "Human session only. Test mode; no automatic top-up. Returning from checkout does not credit the account. Verified webhook processing credits the matching payment exactly once. If checkout is unavailable, returns billing_unavailable and starts no payment.",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "enum": [
                      1000,
                      2500,
                      5000,
                      10000
                    ]
                  }
                },
                "required": [
                  "amount_cents"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkout"
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Read minimal environment and health",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "environment": {
                      "type": "string"
                    },
                    "mail_mode": {
                      "$ref": "#/components/schemas/MailMode"
                    },
                    "live_available": {
                      "type": "boolean",
                      "const": false
                    }
                  },
                  "required": [
                    "status",
                    "environment",
                    "mail_mode",
                    "live_available"
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/sign-up/email": {
      "post": {
        "operationId": "signUp",
        "summary": "Create a managed customer account",
        "description": "Managed auth proxy. Email verification by numeric code is required; sign-up returns no session. The human enters the emailed code through /auth/email-otp/verify-email, then signs in. Browser uses credentials: include. Never log verification codes.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 8
                  }
                },
                "required": [
                  "name",
                  "email",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/sign-in/email": {
      "post": {
        "operationId": "signIn",
        "summary": "Sign in through managed customer auth",
        "description": "Same-origin browser fetch with credentials: include. Managed auth sets the session cookie.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/sign-out": {
      "post": {
        "operationId": "signOut",
        "summary": "Sign out of managed auth",
        "security": [
          {
            "CustomerSession": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Empty"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/stripe": {
      "post": {
        "operationId": "stripeWebhook",
        "summary": "Server-to-server test payment webhook",
        "description": "Not a customer or agent endpoint. Requires a valid Stripe signature, matching stored checkout, account, currency, amount and staging environment. Replays cannot credit twice.",
        "security": [
          {
            "StripeSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "Stateless authenticated MCP JSON-RPC endpoint",
        "description": "Authenticated stateless MCP endpoint exposing prepare_letter, get_letter, get_balance, and send_letter. Use an MCP client for initialization and the protocol handshake. HTTP API is authoritative. Agents have no approval, cancellation, key-management or credit-purchase tool. Both modes require human review and use test credit; no physical mail is sent.",
        "security": [
          {
            "AgentKey": []
          },
          {
            "CustomerSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MCP JSON-RPC result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "202": {
            "description": "MCP notification accepted"
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/email-otp/verify-email": {
      "post": {
        "operationId": "verifyEmailCode",
        "summary": "Verify the human's email using the emailed numeric code",
        "description": "Same-origin managed auth proxy. Human account workflow only. Verification is followed by sign-in; email delivery is not guaranteed by this response.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "otp"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "otp": {
                    "type": "string",
                    "pattern": "^[0-9]+$",
                    "description": "Email verification code. Never log, persist, or expose to agents."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Managed auth response; check errors before showing success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/email-otp/send-verification-otp": {
      "post": {
        "operationId": "resendEmailCode",
        "summary": "Request a new email verification code",
        "description": "Same-origin managed auth proxy. Human account workflow only. Verification is followed by sign-in; email delivery is not guaranteed by this response.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "type"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "type": {
                    "type": "string",
                    "const": "email-verification"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Managed auth response; check errors before showing success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Request rejected or failed. Inspect error.code/message; next_action is optional. A timeout can leave a successful mutation unconfirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "AgentKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Agent API key",
        "description": "Named, revocable key with a cumulative spend cap. Raw key is returned once on creation."
      },
      "CustomerSession": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Secure-neon-auth.session_token",
        "description": "Managed browser session cookie accepted by the staging auth integration. Use the same-origin auth UI with credentials: include; do not construct or share cookies with agents."
      },
      "StripeSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "Stripe-Signature",
        "description": "Signed raw-body webhook; not an agent credential."
      }
    },
    "schemas": {
      "Address": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "address_line1": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "address_line2": {
            "type": "string",
            "maxLength": 100
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "state": {
            "type": "string",
            "pattern": "^[A-Z]{2}$"
          },
          "postal_code": {
            "type": "string",
            "pattern": "^[0-9]{5}(-[0-9]{4})?$"
          },
          "country": {
            "type": "string",
            "enum": [
              "US"
            ]
          }
        },
        "required": [
          "name",
          "address_line1",
          "city",
          "state",
          "postal_code",
          "country"
        ],
        "additionalProperties": false,
        "description": "US address. Single-line printable ASCII fields. State must be a supported two-letter US state or DC code. In letterstream_test mode, address fields must not contain colons or pipes."
      },
      "Service": {
        "type": "string",
        "enum": [
          "first_class",
          "certified_return_receipt"
        ],
        "description": "Both services use Test Mode. LetterStream adds an address coversheet not included in the content preview. Neither service dispatches physical mail."
      },
      "LetterInput": {
        "type": "object",
        "properties": {
          "sender": {
            "$ref": "#/components/schemas/Address"
          },
          "recipient": {
            "$ref": "#/components/schemas/Address"
          },
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 24000,
            "pattern": "^[\\x20-\\x7e\\r\\n]*$",
            "description": "Printable ASCII and line breaks. Text-derived PDF only; maximum 10 pages."
          },
          "service": {
            "$ref": "#/components/schemas/Service"
          }
        },
        "required": [
          "sender",
          "recipient",
          "text",
          "service"
        ],
        "additionalProperties": false
      },
      "Quote": {
        "type": "object",
        "properties": {
          "amount_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000,
            "description": "Provisional test-credit quote, separate from provider_cost_cents. Not a live or universal provider rate."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "provisional": {
            "type": "boolean",
            "const": true,
            "description": "Test credit only. Provider-reported cost is separate."
          }
        },
        "required": [
          "amount_cents",
          "currency",
          "expires_at"
        ]
      },
      "Letter": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "description": "Workflow: awaiting_approval, approved, queued, submitting. simulation completes as simulated; letterstream_test completes as provider_test_held. Neither terminal status is real mailing or delivery. Cancellation and failure states remain possible; submission_unknown keeps funds reserved and must not trigger blind retries."
          },
          "service": {
            "$ref": "#/components/schemas/Service"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "quote": {
            "$ref": "#/components/schemas/Quote"
          },
          "page_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "description": "Pages in the immutable content PDF. LetterStream adds an address coversheet not included in this preview count."
          },
          "preview_url": {
            "type": "string",
            "format": "uri-reference"
          },
          "approval_url": {
            "type": "string",
            "format": "uri-reference"
          },
          "next_action": {
            "type": [
              "string",
              "null"
            ]
          },
          "mode": {
            "$ref": "#/components/schemas/MailMode"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string"
                },
                "at": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": [],
              "additionalProperties": true
            },
            "description": "Status history. Local simulation and provider-held Test Mode outcomes are not evidence of mailing or delivery."
          },
          "evidence": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ProviderTestEvidence"
              },
              {
                "$ref": "#/components/schemas/UnknownSubmissionEvidence"
              },
              {
                "$ref": "#/components/schemas/SimulationEvidence"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "maxProperties": 0
              }
            ],
            "description": "Confirmed held test receipt, retained request identifiers for an unknown submission, local simulation evidence, or an empty object. Display only returned fields. Missing confirmation or cost must not be invented; no identifiers establish delivery."
          }
        },
        "required": [
          "id",
          "status",
          "service",
          "created_at",
          "quote",
          "page_count",
          "preview_url",
          "approval_url",
          "next_action",
          "mode"
        ]
      },
      "Balance": {
        "type": "object",
        "properties": {
          "available_cents": {
            "type": "integer",
            "minimum": 0
          },
          "reserved_cents": {
            "type": "integer",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          }
        },
        "required": [
          "available_cents",
          "reserved_cents",
          "currency"
        ]
      },
      "AgentKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "spend_limit_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          },
          "spent_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          },
          "reserved_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "spend_limit_cents",
          "spent_cents",
          "reserved_cents",
          "created_at",
          "revoked_at"
        ]
      },
      "KeyInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "spend_limit_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          }
        },
        "required": [
          "name",
          "spend_limit_cents"
        ],
        "additionalProperties": false
      },
      "CreatedKey": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AgentKey"
          },
          {
            "type": "object",
            "properties": {
              "key": {
                "type": "string",
                "description": "Raw key returned once. Store as a secret."
              }
            },
            "required": [
              "key"
            ]
          }
        ]
      },
      "Me": {
        "type": "object",
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "format": "email"
              }
            },
            "required": [
              "id"
            ]
          },
          "balance": {
            "$ref": "#/components/schemas/Balance"
          },
          "environment": {
            "type": "string",
            "enum": [
              "staging"
            ]
          },
          "mail_mode": {
            "$ref": "#/components/schemas/MailMode"
          },
          "test_mode": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "account_id",
          "user",
          "balance",
          "environment",
          "mail_mode",
          "test_mode"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "next_action": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Checkout": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "checkout_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "environment": {
            "type": "string",
            "enum": [
              "staging"
            ]
          },
          "test_mode": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "url",
          "checkout_id",
          "amount_cents",
          "currency",
          "environment",
          "test_mode"
        ]
      },
      "Empty": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "MailMode": {
        "type": "string",
        "enum": [
          "simulation",
          "letterstream_test"
        ],
        "description": "The server records the mode when a letter is prepared. simulation does not submit to a provider; letterstream_test submits the synthetic PDF and addresses to LetterStream and holds the job for authorization. Existing simulation letters remain local simulations. The client cannot choose or override this field."
      },
      "ProviderTestEvidence": {
        "type": "object",
        "additionalProperties": false,
        "description": "Allowlisted receipt from a validated held LetterStream test submission. No authorization code, raw provider details, or delivery evidence. Provider cost is separate from the provisional test-credit quote.",
        "properties": {
          "provider": {
            "type": "string",
            "const": "letterstream"
          },
          "provider_cost_cents": {
            "type": "integer",
            "minimum": 0,
            "description": "Returned provider cost in USD cents for this test job, including provider-added pages. Not a universal rate or the AgentPostage test-credit debit."
          },
          "provider_job_id": {
            "type": "string",
            "description": "Provider test job identifier; not a tracking number."
          },
          "provider_document_id": {
            "type": "string",
            "description": "Provider test document identifier."
          },
          "provider_batch_id": {
            "type": "string",
            "description": "Provider test batch identifier."
          },
          "test_mode": {
            "type": "boolean",
            "const": true
          },
          "held": {
            "type": "boolean",
            "const": true
          },
          "physical_mail_sent": {
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "provider",
          "provider_cost_cents",
          "provider_job_id",
          "provider_document_id",
          "provider_batch_id",
          "test_mode",
          "held",
          "physical_mail_sent"
        ]
      },
      "SimulationEvidence": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "simulation": {
            "type": "boolean",
            "const": true
          },
          "physical_mail_sent": {
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "simulation",
          "physical_mail_sent"
        ],
        "description": "Local simulation only; no provider submission."
      },
      "UnknownSubmissionEvidence": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "provider",
          "provider_batch_id",
          "provider_document_id"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "const": "letterstream"
          },
          "provider_batch_id": {
            "type": "string",
            "description": "Provider test batch identifier."
          },
          "provider_document_id": {
            "type": "string",
            "description": "Provider test document identifier."
          }
        },
        "description": "Retained request identifiers after an unknown LetterStream submission, for manual review only. They do not prove that provider Test Mode was checked, provider acceptance, or a held job. No cost, held flag or physical-mail result is asserted."
      }
    }
  }
}
