SignSealShip Partner API Closing Rooms API

Verified Closing Rooms — one shareable page per transaction.

Operations 10

POST /api/rooms Create a room #
GET /api/rooms List your rooms #
GET /api/rooms/{roomCode} Read the room (public) #
POST /api/rooms/{roomCode}/orders Attach an order #
DELETE /api/rooms/{roomCode}/orders/{orderCode} Detach an order #
POST /api/rooms/{roomCode}/rotate Rotate the room link #
GET /api/rooms/{roomCode}/participants List the people on a closing #
POST /api/rooms/{roomCode}/participants Add a person to a closing #
DELETE /api/rooms/{roomCode}/participants/{participantId} Remove a person from a closing #
POST /api/calls/{code}/join Join a closing call #

Documentation

Specifications

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/signsealship-closing-rooms-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

signsealship-closing-rooms-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: SignSealShip Partner Closing Rooms 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: Closing Rooms
  description: Verified Closing Rooms — one shareable page per transaction.
paths:
  /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'
      operationId: postApiRooms
      x-operation-id-source: derived
    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'
      operationId: getApiRooms
      x-operation-id-source: derived
  /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.
      operationId: getApiRoomsByRoomCode
      x-operation-id-source: derived
  /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'
      operationId: postApiRoomsByRoomCodeOrders
      x-operation-id-source: derived
  /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'
      operationId: deleteApiRoomsByRoomCodeOrdersByOrderCode
      x-operation-id-source: derived
  /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'
      operationId: postApiRoomsByRoomCodeRotate
      x-operation-id-source: derived
  /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'
      operationId: getApiRoomsByRoomCodeParticipants
      x-operation-id-source: derived
    post:
      tags:
      - Closing Rooms
      summary: Add a person to a closing
      description: 'Record who this transaction involves — the buyer, the seller, the loan officer.


        **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).


        Idempotent 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'
      operationId: postApiRoomsByRoomCodeParticipants
      x-operation-id-source: derived
  /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'
      operationId: deleteApiRoomsByRoomCodeParticipantsByParticipantId
      x-operation-id-source: derived
  /api/calls/{code}/join:
    post:
      tags:
      - Closing Rooms
      summary: Join a closing call
      description: 'Redeems a party''s call invite.


        The 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.


        Calls are **not recorded**. No recording, transcript, or sealed artifact is produced.


        Invites 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.
      operationId: postApiCallsByCodeJoin
      x-operation-id-source: derived
components:
  schemas:
    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.
    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
    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
    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
    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
    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
    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
    RoomPassportInfo:
      type:
      - object
      - 'null'
      properties:
        version:
          type: integer
        verifyCode:
          type: string
        createdAt:
          type: string
          format: date-time
    Error:
      type: object
      properties:
        error:
          type: string
    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.
    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
    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.
  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'
  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).
  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.