{
  "openapi": "3.1.0",
  "info": {
    "title": "SignSealShip Partner API",
    "version": "1.0.0",
    "description": "The SignSealShip partner API: create sign / notarize / ship orders, create Verified Closing Rooms, seal Closing Passports and Proof Passports, and manage webhooks. Partner endpoints authenticate with a bearer key (`Authorization: Bearer sss_pk_...`); public verification endpoints need no key — possession of the verify, room, or order code is the authorization. See the Guides for full prose, rate limits, and signature verification.",
    "contact": {
      "name": "SignSealShip",
      "url": "https://signsealship.com/partner"
    }
  },
  "servers": [
    {
      "url": "https://signsealship.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "partnerKey": []
    }
  ],
  "tags": [
    {
      "name": "Onboarding",
      "description": "Request partner API access."
    },
    {
      "name": "Orders",
      "description": "B2B order intake — create sign / notarize / ship orders, track them, and mint Stripe hosted checkout."
    },
    {
      "name": "Sandbox",
      "description": "Deterministic lifecycle simulation for TEST orders (sss_pk_test_ keys) — real state machine, real signed webhooks, no live money."
    },
    {
      "name": "Launchpad & Analytics",
      "description": "Your workspace's go-live checklist and tenant-scoped analytics."
    },
    {
      "name": "Closing Rooms",
      "description": "Verified Closing Rooms — one shareable page per transaction."
    },
    {
      "name": "Closing Passports",
      "description": "Room-level, hash-chained, KMS-sealed evidence manifests."
    },
    {
      "name": "Proof Passport",
      "description": "Seal and verify a single executed PDF."
    },
    {
      "name": "Webhooks",
      "description": "Signed event delivery and subscription management."
    }
  ],
  "paths": {
    "/api/partner/request": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Request partner access",
        "description": "Request a partner API key self-serve. Public; rate limited to 5 requests per hour per IP. A business-domain work email plus a coherent, on-topic use case is issued a trial key instantly (emailed once); everything else is queued for human review. Both outcomes return 200.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerRequest"
              },
              "example": {
                "firmName": "Maple Title Co.",
                "contactName": "Dana Reyes",
                "workEmail": "dana@mapletitle.com",
                "role": "Escrow officer",
                "expectedVolume": "15 closings/month",
                "useCase": "Create a Verified Closing Room per escrow file and share the live link with buyers, sellers, and lenders."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Request accepted (issued or pending).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerRequestResponse"
                },
                "example": {
                  "status": "issued",
                  "message": "Your Closing Rooms access is ready — check your email."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "description": "More than 5 requests in an hour from one IP."
          }
        }
      }
    },
    "/api/partner/orders": {
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Create an order",
        "description": "Create a sign / notarize / ship order for a client's own completed document. Send the PDF as the multipart part `document`, or reference a fill-online result with `fill_token` — exactly one of the two, never both. Pricing is computed entirely server-side from the B2B price book with your subscription tier's discount applied automatically; there is no client-sent amount anywhere in the API. Order state advances only via the verified Stripe webhook — minting a checkout session (or a payer landing on the success page) never changes state. Rate limited with `partner-write` (60/min per key).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateOrderResponse"
                },
                "example": {
                  "orderCode": "an-order-public-code",
                  "orderUrl": "/orders/an-order-public-code",
                  "status": "QuoteReady",
                  "externalReference": "MATTER-2291",
                  "subtotalCents": 7635,
                  "discountCents": 500,
                  "totalCents": 7135,
                  "lines": [
                    {
                      "type": "WorkflowFee",
                      "label": "Document workflow",
                      "amountCents": 1200
                    },
                    {
                      "type": "NotaryFee",
                      "label": "Online notarization",
                      "amountCents": 2500
                    },
                    {
                      "type": "ShippingCarrierRate",
                      "label": "Carrier postage (rated for your address)",
                      "amountCents": 2440
                    },
                    {
                      "type": "ShippingHandlingFee",
                      "label": "Shipping & handling",
                      "amountCents": 1495
                    },
                    {
                      "type": "Discount",
                      "label": "Code WELCOME5",
                      "amountCents": -500
                    }
                  ],
                  "checkoutUrl": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List your orders",
        "description": "List the orders created with your partner key, newest first. Rate limited with `partner-write` (60/min per key).",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Page size. Default 20, maximum 100."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by order status name (e.g. `QuoteReady`, `Paid`, `Completed`)."
          },
          {
            "name": "external_reference",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter to orders created with this `external_reference`."
          }
        ],
        "responses": {
          "200": {
            "description": "Your orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/OrderSummary"
                      }
                    },
                    "requestId": {
                      "type": "string",
                      "description": "This request's id — quote it in support tickets."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/partner/orders/{code}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Fetch an order",
        "description": "Fetch one of your orders by its public code. Partner-scoped: another partner's order and an unknown code return the identical 404. Rate limited with `partner-write` (60/min per key).",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderCode"
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown code — or another partner's order; the two are indistinguishable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/partner/orders/{code}/checkout": {
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Mint a checkout session",
        "description": "Mint the Stripe hosted-checkout URL for a payable order. Minting never changes order state — state advances only via the verified Stripe webhook after payment clears. Rate limited with `partner-write` (60/min per key).",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderCode"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Checkout session minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkoutUrl": {
                      "type": "string",
                      "description": "The Stripe hosted-checkout URL to hand to the payer."
                    },
                    "requestId": {
                      "type": "string",
                      "description": "This request's id — quote it in support tickets."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown code — or another partner's order; the two are indistinguishable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The order is not payable in its current state (for example, awaiting a manual quote).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Stripe failed to create the session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Payments are not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/partner/sandbox/orders/{code}/checkout": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Simulate a checkout outcome",
        "description": "Deterministically simulate the payment outcome for a TEST order (created with a `sss_pk_test_` key). `success` finishes the payment crossing exactly like the verified Stripe webhook — the order lands in its first purchased segment and the `payment.cleared` webhook fires with real HMAC signing; a replayed success is a no-op. `decline` parks the order at PaymentFailed (retry with a later success), `cancel`/`delayed` park it at AwaitingPayment. No real Stripe session is ever minted for a test order. Requires `orders:write`; a LIVE order here is a 409.",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderCode"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "success",
                      "decline",
                      "cancel",
                      "delayed"
                    ],
                    "default": "success"
                  }
                }
              },
              "example": {
                "outcome": "success"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The simulated outcome was applied.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orderCode": {
                      "type": "string"
                    },
                    "outcome": {
                      "type": "string"
                    },
                    "checkoutUrl": {
                      "type": "string",
                      "description": "A sandbox checkout link — no real payment page."
                    },
                    "status": {
                      "type": "string",
                      "description": "The order's status after the simulation."
                    },
                    "firedEvents": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Webhook milestones this call fired (real signed deliveries)."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown code — or another partner's order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Not a test order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/partner/sandbox/orders/{code}/advance": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Advance a test order one milestone",
        "description": "Walk a TEST order forward along the happy path until the next lifecycle milestone fires — `payment.cleared`, `signature.completed`, or `shipment.delivered` — delivering the real signed webhook for it. Omit `event` (or send null) to cross whichever milestone is next; name one to walk to it. A milestone the order's purchased services can never reach is a 409. Requires `orders:write`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderCode"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "payment.cleared",
                      "signature.completed",
                      "shipment.delivered",
                      null
                    ]
                  }
                }
              },
              "example": {
                "event": "signature.completed"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The order advanced.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orderCode": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "firedEvents": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown code — or another partner's order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Not a test order, or the milestone does not apply to the purchased services.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/rooms": {
      "post": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Create a room",
        "description": "Create a Verified Closing Room. Enforces your tier's active-room quota (trial and PartnerLink: 5 open rooms; ProOffice: 25; ClosingDesk: unlimited).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRoomRequest"
              },
              "example": {
                "name": "1428 Maple St — Refinance",
                "reference": "TC-88412"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Room created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateRoomResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "List your rooms",
        "description": "Returns your own rooms only, newest first.",
        "responses": {
          "200": {
            "description": "Your rooms.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rooms": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RoomSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/rooms/{roomCode}": {
      "get": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Read the room (public)",
        "description": "Public read by possession of the room code — no API key. The same live JSON the room page renders. Codes outside the 24–64 character gate and unknown codes both return an empty 404. Responses are `Cache-Control: no-store`.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          }
        ],
        "responses": {
          "200": {
            "description": "The live room view.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoomView"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or malformed room code."
          }
        }
      }
    },
    "/api/rooms/{roomCode}/orders": {
      "post": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Attach an order",
        "description": "Attach an order to a room. Authorization is possession of the order's public code. Idempotent — re-attaching succeeds with `alreadyAttached: true`. A room holds at most 50 orders.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachOrderRequest"
              },
              "example": {
                "orderCode": "the-orders-public-code",
                "label": "Seller deed package"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Attached (or already attached).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "alreadyAttached": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/rooms/{roomCode}/orders/{orderCode}": {
      "delete": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Detach an order",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          },
          {
            "name": "orderCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The attached order's public code."
          }
        ],
        "responses": {
          "200": {
            "description": "Detached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/rooms/{roomCode}/rotate": {
      "post": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Rotate the room link",
        "description": "Reissue the room's bearer code. Every previously shared link dies instantly — the mitigation for a leaked or over-shared link.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          }
        ],
        "responses": {
          "200": {
            "description": "New code issued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "roomCode": {
                      "type": "string"
                    },
                    "roomUrl": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/rooms/{roomCode}/passport": {
      "post": {
        "tags": [
          "Closing Passports"
        ],
        "summary": "Seal a passport version",
        "description": "Mint the next Closing Passport version for a room — a dated, hash-chained, KMS-sealed snapshot, never an overwrite. Capped at 20 versions per room. Requires your partner key; the room must be yours.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          }
        ],
        "responses": {
          "200": {
            "description": "Passport version sealed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PassportSealResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/verify/room/{verifyCode}": {
      "get": {
        "tags": [
          "Closing Passports"
        ],
        "summary": "Verify a passport (public)",
        "description": "Public verification of a Closing Passport version. `chainOk` is recomputed on every call, never a stored verdict. Malformed and unknown codes return the identical generic 404 `{\"verdict\": \"unknown\"}`.",
        "security": [],
        "parameters": [
          {
            "name": "verifyCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The passport's 26-character verification code."
          }
        ],
        "responses": {
          "200": {
            "description": "The verified passport version and its recomputed chain state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoomPassportVerification"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or malformed code.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verdict": {
                      "type": "string",
                      "example": "unknown"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/verify/room/{verifyCode}/pdf": {
      "get": {
        "tags": [
          "Closing Passports"
        ],
        "summary": "Download the sealed certificate (public)",
        "description": "Streams the sealed Closing Passport certificate PDF. The verify code is the bearer.",
        "security": [],
        "parameters": [
          {
            "name": "verifyCode",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The sealed certificate PDF.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Unknown code or unavailable artifact."
          }
        }
      }
    },
    "/api/passport/seal": {
      "post": {
        "tags": [
          "Proof Passport"
        ],
        "summary": "Seal a document",
        "description": "Submit a finished, signed PDF (multipart part named `file`, up to 35 MB). It returns sealed with Google Cloud KMS, timestamped by independent RFC 3161 and OpenTimestamps authorities, and wrapped in a public verification URL. Bytes are streamed in memory, never to disk, and discarded after sealing.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The executed PDF. Maximum 35 MB."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document sealed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProofSealResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/passport/{id}": {
      "get": {
        "tags": [
          "Proof Passport"
        ],
        "summary": "Fetch a passport",
        "description": "Fetch a Proof Passport you created. Partner isolation is enforced — a passport is visible only to the partner that created it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The passport's UUID from the seal response."
          }
        ],
        "responses": {
          "200": {
            "description": "The passport (seal fields minus timestamps, plus createdAt).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProofPassport"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No such passport (including another partner's).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/verify/{code}": {
      "get": {
        "tags": [
          "Proof Passport"
        ],
        "summary": "Verify a passport (public)",
        "description": "Public, self-contained verification of a Proof Passport. Never exposes the partner identity. Malformed and unknown codes return the identical generic 404 `{\"verdict\": \"unknown\"}`.",
        "security": [],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The 26-character verify code."
          }
        ],
        "responses": {
          "200": {
            "description": "Verification result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProofVerification"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or malformed code."
          }
        }
      }
    },
    "/api/passport/verify/{code}/document": {
      "get": {
        "tags": [
          "Proof Passport"
        ],
        "summary": "Download the sealed document (public)",
        "description": "Streams the byte-identical sealed PDF. Any holder of the code can fetch it; the file also verifies on its own in any PDF reader's signature panel.",
        "security": [],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The sealed PDF.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Unknown code or missing artifact."
          }
        }
      }
    },
    "/api/passport/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Register a passport webhook",
        "description": "Register an https endpoint for `passport.sealed` events using your partner API key. The signing secret is returned exactly once — only its hash is stored. Subscriptions created this way receive only `passport.sealed` (no room events).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Your https webhook endpoint."
                  }
                }
              },
              "example": {
                "url": "https://example.com/hooks/signsealship"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook registered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PassportWebhookResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/passport/webhooks/{id}": {
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a passport webhook",
        "description": "Unregister a subscription created by `POST /api/passport/webhooks`, using your partner API key. Partner-scoped: another partner's id and an unknown id return the identical 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The `webhookId` returned at registration."
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    },
                    "webhookId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown id — or another partner's subscription; the two are indistinguishable."
          }
        }
      }
    },
    "/api/partner/me": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Who am I",
        "description": "The identity behind your API key: firm name, subscription tier, whether live keys are enabled for the account, and whether this key is a `test` or `live` key. Powers connection labels in integrations (e.g. Zapier).",
        "responses": {
          "200": {
            "description": "The key's own account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "firmName": {
                      "type": "string"
                    },
                    "tier": {
                      "type": "string"
                    },
                    "liveEnabled": {
                      "type": "boolean"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "test",
                        "live"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid credential presented — send a partner API key, or sign in and link a session. Returned 403 before 2026-08-01."
          },
          "403": {
            "description": "Your session is valid but is not linked to a partner. Link one at https://signsealship.com/partner with a partner API key."
          }
        }
      }
    },
    "/api/partner/launchpad": {
      "get": {
        "tags": [
          "Launchpad & Analytics"
        ],
        "summary": "Go-live checklist",
        "description": "Your account's activation state: the go-live checklist (each step with a deep link to complete it), the funnel of steps already reached, whether the account is ready for live keys, and the hours from signup to your first live order. Accepts the partner API key or the dashboard session.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "The activation state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "partner": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "tier": {
                          "type": "string"
                        }
                      }
                    },
                    "readyForLive": {
                      "type": "boolean"
                    },
                    "completed": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "checklist": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "done": {
                            "type": "boolean"
                          },
                          "action": {
                            "type": "string"
                          },
                          "deepLink": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "funnel": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "step": {
                            "type": "string"
                          },
                          "reached": {
                            "type": "boolean"
                          },
                          "at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "hoursToFirstLiveOrder": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/partner/analytics": {
      "get": {
        "tags": [
          "Launchpad & Analytics"
        ],
        "summary": "Workspace analytics",
        "description": "A tenant-scoped analytics snapshot over a trailing window: monthly order volume, the created→paid→completed funnel, turnaround hours (median and p90), service mix, evidence coverage, and revenue. Accepts the partner API key (needs `orders:read`) or the dashboard session.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 366,
              "default": 90
            },
            "description": "Trailing window in days."
          }
        ],
        "responses": {
          "200": {
            "description": "The snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "windowDays, volumeByMonth[], funnel {created,paid,inProgress,completed,problem}, turnaroundHours {median,p90}, serviceMix {sign,notarize,ship,fax}, evidence, revenueCents, generatedAt.",
                  "properties": {
                    "windowDays": {
                      "type": "integer"
                    },
                    "generatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The API key lacks the `orders:read` scope."
          }
        }
      }
    },
    "/api/partner/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List subscriptions",
        "description": "List your partner's webhook subscriptions, newest first. Accepts your partner API key (`Authorization: Bearer sss_pk_...`) for server-to-server management, or the SignSealShip dashboard session cookie (`__Host-session`) — link a session once with a partner key at https://signsealship.com/partner.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Your subscriptions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookSubscription"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Session not linked to a partner."
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a subscription",
        "description": "Create a topic-aware webhook subscription. Accepts the partner API key or the dashboard session cookie. The signing secret is shown exactly once. Order topics (`order.created`, `payment.cleared`, `signature.completed`, `shipment.delivered`) deliver only for orders you created through the Order API.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              },
              "example": {
                "url": "https://example.com/hooks/signsealship",
                "topics": [
                  "order.created",
                  "payment.cleared",
                  "room.passport_sealed"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateWebhookResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Session not linked to a partner."
          }
        }
      }
    },
    "/api/partner/webhooks/{id}": {
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a subscription",
        "description": "Delete a subscription. Accepts the partner API key or the dashboard session cookie.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The subscription id."
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Session not linked to a partner."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/partner/webhooks/{id}/rotate": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate a signing secret",
        "description": "Reissue the subscription's signing secret. The new secret is returned exactly once — only its hash is stored. For 24 hours deliveries are signed with both the old and the new secret (one `v1` entry each in the `SignSealShip-Signature` header), so your endpoint can cut over without dropping verification; after the overlap the old secret stops signing. Accepts the partner API key or the dashboard session cookie.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The subscription id."
          }
        ],
        "responses": {
          "200": {
            "description": "New secret issued — shown exactly once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateWebhookResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Session not linked to a partner."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/partner/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List delivery attempts",
        "description": "A metadata-only feed of the subscription's recent delivery attempts — what was attempted, when, and how your endpoint answered. Event payload bodies are never stored or returned. Accepts the partner API key or the dashboard session cookie.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The subscription id."
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery attempt metadata, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "deliveries"
                  ],
                  "properties": {
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "One delivery attempt's metadata (never the payload body)."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Session not linked to a partner."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/partner/webhooks/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Inspect deliveries across subscriptions",
        "description": "The delivery feed across ALL of your subscriptions, filterable. Metadata only — payload bodies are redacted. Accepts the partner API key (needs `webhooks:read`) or the dashboard session.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "topic",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter to one event topic."
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter to one order's public code."
          },
          {
            "name": "external_reference",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter to orders created with this reference."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by delivery state (e.g. `delivered`, `failed`, `retrying`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching deliveries, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "deliveries"
                  ],
                  "properties": {
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "deliveryId": {
                            "type": "string"
                          },
                          "eventName": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string"
                          },
                          "attempts": {
                            "type": "integer"
                          },
                          "lastStatusCode": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "nextAttemptAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "destinationUrl": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Session not linked to a partner, or the key lacks `webhooks:read`."
          }
        }
      }
    },
    "/api/partner/webhooks/deliveries/{deliveryId}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Inspect one delivery",
        "description": "One delivery's detail: the redacted request body, the signature header name, and the full attempt history (status codes, timing). Accepts the partner API key (needs `webhooks:read`) or the dashboard session.",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The delivery id from a delivery list."
          }
        ],
        "responses": {
          "200": {
            "description": "The delivery detail (payload redacted).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Delivery metadata, redacted body preview, and attempt history."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/partner/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a signed test event",
        "description": "Deliver a signed synthetic event to the subscription's endpoint right now — the fastest way to prove your signature verification end to end. Requires `webhooks:write` (or the dashboard session).",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The subscription id."
          }
        ],
        "responses": {
          "200": {
            "description": "Test event queued/delivered.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "deliveryId": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/partner/webhooks/deliveries/{deliveryId}/replay": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Replay a delivery",
        "description": "Re-send a past delivery's event as a brand-new signed delivery to the same subscription. Requires `webhooks:write` (or the dashboard session).",
        "security": [
          {
            "partnerKey": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The delivery id to replay."
          }
        ],
        "responses": {
          "200": {
            "description": "A new delivery was created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "deliveryId": {
                      "type": "string",
                      "description": "The NEW delivery's id."
                    },
                    "replayedFrom": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No such delivery, or its endpoint was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/partner/webhooks/signature-example": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Signature verification recipe",
        "description": "The signature header name and a worked verification example (Node.js). Deliberately public — a static docs recipe with no tenant data, readable before you hold a key.",
        "security": [],
        "responses": {
          "200": {
            "description": "The recipe.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signatureHeader": {
                      "type": "string"
                    },
                    "example": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/rooms/{roomCode}/participants": {
      "get": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "List the people on a closing",
        "description": "The roster for one of YOUR rooms, with real email addresses. The public room view (`GET /api/rooms/{roomCode}`) returns the same people with masked emails, because the room link is a bearer key.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          }
        ],
        "responses": {
          "200": {
            "description": "The live roster. Removed participants are excluded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "participants": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RoomParticipant"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Add a person to a closing",
        "description": "Record who this transaction involves — the buyer, the seller, the loan officer.\n\n**This grants no access.** A participant is a name and an email; the room is still reached by possession of its link, and removing someone here does not revoke a link they already hold (rotate the room code for that).\n\nIdempotent on a live email address (case-insensitive): re-adding someone already on the deal succeeds with `alreadyPresent: true`. A room holds at most 25 participants.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddParticipantRequest"
              },
              "example": {
                "name": "Dana Buyer",
                "email": "dana@example.com",
                "role": "client"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Added (or already present).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "alreadyPresent": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/rooms/{roomCode}/participants/{participantId}": {
      "delete": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Remove a person from a closing",
        "description": "Takes someone off the live roster. The underlying row is retained — who was on a deal at the time a document was executed is part of the record, not a mutable list — so this is not a deletion of history. Re-adding the same person later creates a new entry.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoomCode"
          },
          {
            "name": "participantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The participant's id, from the list response."
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/calls/{code}/join": {
      "post": {
        "tags": [
          "Closing Rooms"
        ],
        "summary": "Join a closing call",
        "description": "Redeems a party's call invite.\n\nThe code is a bearer capability for **calls only** — it never returns the room view, the orders, or any document, and it is **inert unless a call is actually running**. A `live: false` response means the link is genuine but the firm has not started the call yet; a `404` covers wrong, expired, and revoked codes alike, so probing codes reveals nothing.\n\nCalls are **not recorded**. No recording, transcript, or sealed artifact is produced.\n\nInvites are issued from the partner dashboard (session-authenticated); there is no partner-API-key route for starting a call.",
        "security": [],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The invite code from the join link."
          }
        ],
        "responses": {
          "200": {
            "description": "Either LiveKit credentials, or an honest not-started answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallJoinResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown, expired, or revoked invite — deliberately indistinguishable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "invite_not_found"
                      ]
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Calling is not configured on this deployment."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "partnerKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sss_pk_...",
        "description": "Partner API key. Send as `Authorization: Bearer sss_pk_...`."
      },
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Host-session",
        "description": "SignSealShip dashboard login session cookie. Accepted by the `/api/partner/webhooks` management routes as an alternative to the partner key."
      }
    },
    "parameters": {
      "RoomCode": {
        "name": "roomCode",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "The room's bearer code (40 lowercase hex characters; the read endpoint accepts 24–64)."
      },
      "OrderCode": {
        "name": "code",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "The order's public code from the create response."
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 255
        },
        "description": "Optional. Retries carrying the same key replay the original response instead of acting twice. 8–255 characters; scope one key to one logical action."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed, revoked, or unknown partner key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "A valid partner API key is required."
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found. Unknown codes read as a generic not-found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "PartnerRequest": {
        "type": "object",
        "required": [
          "firmName",
          "contactName",
          "workEmail"
        ],
        "properties": {
          "firmName": {
            "type": "string",
            "maxLength": 200,
            "description": "Your firm or company name."
          },
          "contactName": {
            "type": "string",
            "maxLength": 200,
            "description": "The requester's full name."
          },
          "workEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 254,
            "description": "A deliverable work email. The issued key is sent here; a business domain is the strongest signal for instant issue."
          },
          "role": {
            "type": "string",
            "maxLength": 120,
            "description": "Your role at the firm (e.g. \"Escrow officer\")."
          },
          "expectedVolume": {
            "type": "string",
            "maxLength": 120,
            "description": "Rough expected volume (e.g. \"10-20 closings/month\")."
          },
          "useCase": {
            "type": "string",
            "maxLength": 4000,
            "description": "What you plan to build or run on the API."
          },
          "recaptchaToken": {
            "type": "string",
            "description": "Optional bot-screening token; omit when calling the API directly."
          }
        }
      },
      "PartnerRequestResponse": {
        "type": "object",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "issued",
              "pending"
            ],
            "description": "`issued` — a trial key was created and emailed. `pending` — queued for human review."
          },
          "message": {
            "type": "string",
            "description": "A browser-safe confirmation message."
          }
        }
      },
      "CreateOrderRequest": {
        "type": "object",
        "required": [
          "email",
          "byod_confirmed"
        ],
        "description": "Multipart form fields. Send exactly one of `document` or `fill_token` — never both.",
        "properties": {
          "document": {
            "type": "string",
            "format": "binary",
            "description": "The client's own completed PDF, up to 35 MB. Mutually exclusive with `fill_token`."
          },
          "fill_token": {
            "type": "string",
            "pattern": "^[0-9a-f]{40}$",
            "description": "A 40-character lowercase-hex token from the fill-online rail, in place of a `document` upload. Mutually exclusive with `document`."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "The signer / client email. Required."
          },
          "name": {
            "type": "string",
            "description": "The signer / client name."
          },
          "doc_slug": {
            "type": "string",
            "description": "Catalog document slug. When present, the catalog row defines the sign / notary services; shipping stays additive via `svc_ship`."
          },
          "svc_sign": {
            "type": "string",
            "enum": [
              "true",
              "on"
            ],
            "description": "Include e-signing."
          },
          "svc_notary": {
            "type": "string",
            "enum": [
              "true",
              "on"
            ],
            "description": "Include online notarization."
          },
          "svc_ship": {
            "type": "string",
            "enum": [
              "true",
              "on"
            ],
            "description": "Include shipping — send the `ship_*` address fields with it."
          },
          "signer_state": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Two-letter US state where the signer is located."
          },
          "dest_state": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Two-letter US state the shipment is destined for."
          },
          "byod_confirmed": {
            "type": "string",
            "enum": [
              "true",
              "on"
            ],
            "description": "Required. Attests that this is the client's own completed document (bring-your-own-document)."
          },
          "external_reference": {
            "type": "string",
            "maxLength": 120,
            "description": "Your own matter / file number, up to 120 characters. Echoed on webhook events and listings."
          },
          "ship_name": {
            "type": "string",
            "description": "Recipient name (when shipping)."
          },
          "ship_line1": {
            "type": "string",
            "description": "Address line 1 (when shipping)."
          },
          "ship_line2": {
            "type": "string",
            "description": "Address line 2."
          },
          "ship_city": {
            "type": "string",
            "description": "City (when shipping)."
          },
          "ship_state": {
            "type": "string",
            "description": "Two-letter US state (when shipping)."
          },
          "ship_postal": {
            "type": "string",
            "description": "ZIP / postal code (when shipping)."
          },
          "ship_method": {
            "type": "string",
            "enum": [
              "label",
              "print_mail"
            ],
            "description": "Delivery method when shipping is selected. `label` (default) buys a prepaid carrier label; `print_mail` has SignSealShip print and mail the completed document ($12.95 line, replacing the label handling fee). Unrecognized values fall back to `label`."
          },
          "from_name": {
            "type": "string",
            "description": "Optional sender / return address (all of `from_line1`, `from_city`, `from_state`, `from_postal` must accompany it): printed as the return address on print-and-mail letters and used as the ship-from on prepaid labels, so rates price from the true origin and undeliverable mail returns to the actual sender. Absent ⇒ the platform business address."
          },
          "from_line1": {
            "type": "string",
            "description": "Return address street line 1."
          },
          "from_line2": {
            "type": "string",
            "description": "Return address street line 2."
          },
          "from_city": {
            "type": "string",
            "description": "Return address city."
          },
          "from_state": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Return address two-letter US state."
          },
          "from_postal": {
            "type": "string",
            "description": "Return address ZIP / postal code."
          },
          "fax_to": {
            "type": "string",
            "description": "Adds sealed fax delivery ($9.00): a 10-digit US number or an international number in `+country` format, normalized to E.164. An uninterpretable number is rejected with a 400 — never silently dropped."
          },
          "create_checkout": {
            "type": "string",
            "enum": [
              "true",
              "on"
            ],
            "description": "Also mint the Stripe hosted-checkout session in the same call and return it as `checkoutUrl`."
          }
        }
      },
      "OrderLine": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Machine-readable line type."
          },
          "label": {
            "type": "string",
            "description": "Display label for the line."
          },
          "amountCents": {
            "type": "integer",
            "description": "Line amount in USD cents."
          }
        }
      },
      "OrderServices": {
        "type": "string",
        "description": "Which services the order includes, as a comma-separated flags string. Possible flags: `Sign`, `Notarize`, `Ship`, `Fax`. Parse by splitting on `\", \"` — this is NOT an object of booleans (corrected 2026-08-01; the schema previously mis-documented it as one).",
        "example": "Sign, Notarize, Ship"
      },
      "CreateOrderResponse": {
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "This request's id — quote it in support tickets."
          },
          "orderCode": {
            "type": "string",
            "description": "The order's public code."
          },
          "orderUrl": {
            "type": "string",
            "description": "Root-relative path to the order page, `/orders/{orderCode}`."
          },
          "status": {
            "type": "string",
            "description": "The order's status name (e.g. `QuoteReady`)."
          },
          "externalReference": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `external_reference` you sent, or `null`."
          },
          "faxToNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "The normalized E.164 fax destination when `fax_to` was sent, or `null`."
          },
          "subtotalCents": {
            "type": "integer"
          },
          "discountCents": {
            "type": "integer",
            "description": "Your subscription-tier discount, computed and applied server-side."
          },
          "totalCents": {
            "type": "integer"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLine"
            }
          },
          "checkoutUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Stripe hosted-checkout URL. `null` unless `create_checkout=true` was sent, payments are configured, and the order is payable — a ManualQuoteRequired order returns no checkout."
          }
        }
      },
      "OrderSummary": {
        "type": "object",
        "properties": {
          "orderCode": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "services": {
            "$ref": "#/components/schemas/OrderServices"
          },
          "totalCents": {
            "type": "integer"
          },
          "externalReference": {
            "type": [
              "string",
              "null"
            ]
          },
          "customerEmail": {
            "type": "string",
            "description": "The signer / client email from the create call."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "OrderDetail": {
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "This request's id — quote it in support tickets."
          },
          "orderCode": {
            "type": "string"
          },
          "orderUrl": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "services": {
            "$ref": "#/components/schemas/OrderServices"
          },
          "envelopeStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The e-sign envelope's status when the order includes signing, else `null`."
          },
          "externalReference": {
            "type": [
              "string",
              "null"
            ]
          },
          "customerEmail": {
            "type": "string"
          },
          "subtotalCents": {
            "type": "integer"
          },
          "discountCents": {
            "type": "integer"
          },
          "totalCents": {
            "type": "integer"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLine"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateRoomRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Display name shown to every party (e.g. a property address)."
          },
          "reference": {
            "type": "string",
            "maxLength": 200,
            "description": "Your internal file number."
          }
        }
      },
      "CreateRoomResponse": {
        "type": "object",
        "properties": {
          "roomCode": {
            "type": "string",
            "description": "The room's bearer code — 40 lowercase hex characters."
          },
          "roomUrl": {
            "type": "string",
            "description": "Root-relative path to the shareable page, `/rooms/{roomCode}`."
          },
          "name": {
            "type": "string"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "example": "open"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RoomSummary": {
        "type": "object",
        "properties": {
          "roomCode": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "example": "open"
          },
          "orderCount": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AttachOrderRequest": {
        "type": "object",
        "required": [
          "orderCode"
        ],
        "properties": {
          "orderCode": {
            "type": "string",
            "minLength": 24,
            "maxLength": 64,
            "description": "The order's public code."
          },
          "label": {
            "type": "string",
            "description": "A display label for the document card."
          }
        }
      },
      "Branding": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "brandName": {
            "type": [
              "string",
              "null"
            ]
          },
          "accentColor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hex color like `#1a2b3c`."
          },
          "logoUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Public https URL of the partner's logo."
          }
        }
      },
      "RoomView": {
        "type": "object",
        "properties": {
          "roomCode": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "example": "open"
          },
          "partnerName": {
            "type": "string"
          },
          "branding": {
            "$ref": "#/components/schemas/Branding"
          },
          "progress": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "signed": {
                "type": "integer"
              },
              "sealed": {
                "type": "integer"
              },
              "delivered": {
                "type": "integer"
              }
            }
          },
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoomOrderCard"
            }
          },
          "activity": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityItem"
            }
          },
          "passport": {
            "$ref": "#/components/schemas/RoomPassportInfo"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RoomOrderCard": {
        "type": "object",
        "properties": {
          "orderCode": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "Raw platform status (e.g. `EsignPending`). Build logic on `statusGroup`."
          },
          "statusGroup": {
            "type": "string",
            "enum": [
              "signing",
              "signed",
              "notarizing",
              "notarized",
              "shipping",
              "shipped",
              "delivered",
              "complete",
              "attention",
              "open"
            ]
          },
          "services": {
            "type": "object",
            "properties": {
              "sign": {
                "type": "boolean"
              },
              "notarize": {
                "type": "boolean"
              },
              "ship": {
                "type": "boolean"
              },
              "fax": {
                "type": "boolean"
              }
            }
          },
          "signers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "email": {
                  "type": "string",
                  "description": "Masked email."
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "routingOrder": {
                  "type": "integer"
                },
                "signed": {
                  "type": "boolean"
                }
              }
            }
          },
          "evidenceBadge": {
            "type": "string",
            "enum": [
              "sealed",
              "recorded",
              "none"
            ],
            "description": "Locked vocabulary: `sealed` (verifiable artifact hash on record), `recorded` (platform attestation only), `none` (no evidence yet)."
          },
          "verifyCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "Present only when the badge is `sealed` and the envelope verify code exists."
          },
          "trackingNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "carrier": {
            "type": [
              "string",
              "null"
            ]
          },
          "attachedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ActivityItem": {
        "type": "object",
        "properties": {
          "orderCode": {
            "type": "string"
          },
          "action": {
            "type": "string",
            "enum": [
              "order.created",
              "order.transition",
              "order.claimed",
              "order.cancelled",
              "signing_link.issued",
              "room.order_attached"
            ]
          },
          "fromStatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "toStatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RoomPassportInfo": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "version": {
            "type": "integer"
          },
          "verifyCode": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PassportSealResponse": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "description": "The new version number, incrementing per room."
          },
          "verifyCode": {
            "type": "string",
            "description": "26 lowercase base32 characters (128 bits)."
          },
          "verifyUrl": {
            "type": "string",
            "description": "`/v/room/{verifyCode}`."
          },
          "manifestSha256": {
            "type": "string"
          },
          "prevManifestSha256": {
            "type": [
              "string",
              "null"
            ],
            "description": "The prior version's manifestSha256 — the hash-chain link. `null` on version 1."
          },
          "sealedSha256": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RoomPassportVerification": {
        "type": "object",
        "properties": {
          "manifest": {
            "type": "object",
            "description": "The stored canonical manifest, parsed (coverage, documents, passport)."
          },
          "manifestSha256": {
            "type": "string"
          },
          "sealedSha256": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "prevManifestSha256": {
            "type": [
              "string",
              "null"
            ]
          },
          "chainOk": {
            "type": "boolean",
            "description": "Recomputed every call: the stored manifest re-hashes to manifestSha256 AND the chain link is intact."
          },
          "branding": {
            "$ref": "#/components/schemas/Branding"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "downloadUrl": {
            "type": "string",
            "description": "`/api/verify/room/{verifyCode}/pdf`."
          }
        }
      },
      "ProofSealResponse": {
        "type": "object",
        "properties": {
          "passportId": {
            "type": "string",
            "format": "uuid"
          },
          "verifyCode": {
            "type": "string"
          },
          "verifyUrl": {
            "type": "string",
            "description": "Absolute public verification URL."
          },
          "docSha256": {
            "type": "string",
            "description": "SHA-256 of the exact bytes you uploaded (pre-seal)."
          },
          "sealedSha256": {
            "type": "string",
            "description": "SHA-256 of the sealed PDF SignSealShip produced."
          },
          "status": {
            "type": "string",
            "example": "sealed"
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "Environment of the key that sealed it. The public verifier flags test-environment evidence."
          },
          "timestamps": {
            "type": "object",
            "description": "Independent timestamp evidence; either member is `null` when the authority could not be reached.",
            "properties": {
              "rfc3161": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "authority": {
                    "type": "string"
                  },
                  "timestampedAtUtc": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              },
              "openTimestamps": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "calendar": {
                    "type": "string"
                  },
                  "submittedAtUtc": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "status": {
                    "type": "string",
                    "example": "pending"
                  }
                }
              }
            }
          }
        }
      },
      "ProofPassport": {
        "type": "object",
        "properties": {
          "passportId": {
            "type": "string",
            "format": "uuid"
          },
          "verifyCode": {
            "type": "string"
          },
          "verifyUrl": {
            "type": "string"
          },
          "docSha256": {
            "type": "string"
          },
          "sealedSha256": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "example": "sealed"
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "The environment of the API key that sealed it. Sandbox-keyed passports stay visibly sandbox on every surface, including public verification."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProofVerification": {
        "type": "object",
        "properties": {
          "verdict": {
            "type": "string",
            "enum": [
              "verified",
              "verified_test"
            ],
            "example": "verified",
            "description": "`verified_test` marks a passport sealed with a TEST-environment key — it is not production evidence."
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ]
          },
          "verifyCode": {
            "type": "string"
          },
          "sealedSha256": {
            "type": "string"
          },
          "docSha256": {
            "type": "string"
          },
          "sealedAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "type": "string",
            "example": "proof_passport_api"
          },
          "certificateAvailable": {
            "type": "boolean"
          }
        }
      },
      "PassportWebhookResponse": {
        "type": "object",
        "properties": {
          "webhookId": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string"
          },
          "signingSecret": {
            "type": "string",
            "description": "Shown exactly once — store it now. Only its hash is kept."
          },
          "signatureHeader": {
            "type": "string",
            "example": "SignSealShip-Signature"
          },
          "verification": {
            "type": "string",
            "description": "How to verify the HMAC signature."
          }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string"
          },
          "topics": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "passport.sealed",
                "room.order_attached",
                "room.passport_sealed",
                "order.created",
                "payment.cleared",
                "signature.completed",
                "shipment.delivered",
                "trust.assessment_requested",
                "trust.assessment_completed",
                "trust.assessment_superseded",
                "recording.review_required",
                "recording.quote_ready",
                "recording.approved",
                "recording.fulfillment_queued",
                "recording.mailed",
                "recording.delivered_to_recorder",
                "recording.accepted",
                "recording.recorded",
                "recording.rejected",
                "recording.receipt_sealed"
              ]
            }
          },
          "active": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "url",
          "topics"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "An absolute https:// URL."
          },
          "topics": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "passport.sealed",
                "room.order_attached",
                "room.passport_sealed",
                "order.created",
                "payment.cleared",
                "signature.completed",
                "shipment.delivered",
                "trust.assessment_requested",
                "trust.assessment_completed",
                "trust.assessment_superseded",
                "recording.review_required",
                "recording.quote_ready",
                "recording.approved",
                "recording.fulfillment_queued",
                "recording.mailed",
                "recording.delivered_to_recorder",
                "recording.accepted",
                "recording.recorded",
                "recording.rejected",
                "recording.receipt_sealed"
              ]
            },
            "description": "The order topics deliver only for orders created through the Order API."
          }
        }
      },
      "CreateWebhookResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "secret": {
            "type": "string",
            "description": "Signing secret prefixed `sss_whsec_`. Shown exactly once."
          },
          "url": {
            "type": "string"
          },
          "topics": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "signatureHeader": {
            "type": "string",
            "example": "SignSealShip-Signature"
          }
        }
      },
      "RotateWebhookResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The rotated subscription id."
          },
          "secret": {
            "type": "string",
            "description": "The new signing secret, prefixed `sss_whsec_`. Shown exactly once — only its hash is stored. Deliveries are signed with both the old and the new secret for 24 hours, then the old secret stops signing."
          },
          "signatureHeader": {
            "type": "string",
            "description": "Header name carrying the HMAC signature on every delivery."
          },
          "previousSecretExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Until this instant deliveries are signed with BOTH secrets — accept either during the overlap."
          }
        }
      },
      "AddParticipantRequest": {
        "type": "object",
        "required": [
          "name",
          "email"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200,
            "description": "The person's display name, as you'd write it on the file."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Where you would reach them. Stored lowercased; per-room uniqueness is case-insensitive."
          },
          "role": {
            "type": "string",
            "maxLength": 40,
            "default": "client",
            "description": "Their part in the deal — client, signer, agent, lender, attorney, title_officer, observer, or anything else you use. Descriptive only; it grants no authorization."
          }
        }
      },
      "RoomParticipant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "The real address. The PUBLIC room view masks this; only the owning partner reads it unmasked here."
          },
          "role": {
            "type": "string"
          },
          "addedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CallJoinResponse": {
        "oneOf": [
          {
            "type": "object",
            "title": "Call is live",
            "properties": {
              "live": {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              "url": {
                "type": "string",
                "description": "LiveKit websocket URL."
              },
              "token": {
                "type": "string",
                "description": "Short-lived LiveKit access token for this party."
              },
              "room": {
                "type": "string",
                "description": "LiveKit room name, derived server-side from the closing."
              },
              "displayName": {
                "type": "string",
                "description": "What the other participants see."
              },
              "roomName": {
                "type": "string",
                "description": "The closing's name."
              },
              "startedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          {
            "type": "object",
            "title": "Call has not started",
            "properties": {
              "live": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "roomName": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        ]
      }
    }
  }
}
