> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cardinalgray.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sign Title Documents

> Initiate signature process for title documents

Creates a signature request for generated title documents.

You can send an explicit body with `signers` and `documents_to_sign`, or omit the body entirely to let the API build the request from the title entry. Auto-build requires signer `contact_email` values to already be present on the entry, usually via a prior `PATCH /title/{id}`.

`redirect_url` belongs in the request body, not the query string.

## Signing URLs in the response

For Notarize/Proof-based organizations, the response includes per-signer signing URLs at `signers[].transaction_access_url`. Each signer receives their own unique link to access the signing session.

```json theme={null}
{
  "id": "NTRZ::ot_abc123",
  "status": "SENT",
  "signers": [
    {
      "name": "Jane Doe",
      "contact_email": "jane@example.com",
      "transaction_access_url": "https://app.proof.com/activate-transaction?..."
    }
  ]
}
```

The top-level `transaction_access_url` on the `SignatureRequest` object is **not** populated on the initial create response — it is only set after an explicit activate action on a `DRAFT` request. Always read signing URLs from `signers[].transaction_access_url`.

DocuSign-based requests do not include `transaction_access_url` — signing links are delivered directly to signers via email by DocuSign.

Internal signature actions for managing existing requests are not part of the partner-facing API surface.

## Physical title return (`title_collection`)

For organizations enrolled in physical title collection, titles in states that require the original paper title to be shipped back to Cardinal Gray (e.g. Texas) additionally include a `title_collection` object in the sign response, alongside the signature-request fields. The same object is persisted on the entry and returned by subsequent [`GET /title/{id}`](/api-reference/v1/get_title) reads.

```json theme={null}
{
  "id": "NTRZ::ot_abc123",
  "status": "SENT",
  "signers": [
    {
      "name": "Jane Doe",
      "contact_email": "jane@example.com",
      "transaction_access_url": "https://app.proof.com/activate-transaction?..."
    }
  ],
  "title_collection": {
    "collection_id": "11111111-2222-4333-8444-555555555555",
    "mode": "LIVE",
    "carrier": "UPS",
    "service": "UPS Electronic Return Label",
    "tracking_number": "1Z999AA10123456784",
    "label_url": "https://assets.cardinalgray.com/labels/11111111-2222-4333-8444-555555555555.pdf?X-Amz-Signature=...",
    "qr_url": "https://assets.cardinalgray.com/labels/11111111-2222-4333-8444-555555555555-qr.png?X-Amz-Signature=...",
    "qr_verified": true,
    "assets_expires_at": "2026-08-01T12:00:00Z",
    "return_address": "c/o Cardinal Gray, Inc., 8080 Westpark Drive, STE 87808, Houston, TX 77063",
    "instructions": [
      "Place the original vehicle title in an envelope.",
      "Print the UPS return label and attach it to the envelope.",
      "Drop the package off at any UPS location and keep the receipt."
    ],
    "created_at": "2026-07-20T12:00:00Z"
  }
}
```

Contract rules:

* `title_collection` is **additive and may be absent** — for organizations, groups, states, or environments where physical title collection is not enabled, the response is unchanged. Existing clients must tolerate its absence.
* `collection_id` is **stable**: repeated sign actions, bumps, activations, and retries return the same collection rather than creating additional labels.
* `tracking_number` is nullable: it is `null` until a carrier shipment exists. Clients must handle `null`.
* `label_url` is the guaranteed printable-label fallback.
* `instructions` are ready to display to the borrower as-is; render them rather than hardcoding your own copy.
* `mode` distinguishes sandbox (`STUB`) from production (`LIVE`) fulfillment; treat it as informational — the field contract is identical in both.
* `qr_url` is **optional** and only present when `qr_verified` is `true` (a verified UPS mobile drop-off barcode). Clients must not assume `qr_url` exists or that an unverified QR is accepted at UPS.
* Asset URLs are presigned and **expire** at `assets_expires_at` — do not cache them indefinitely.
* The bodyless sign request uses the ruleset-generated document path — no `signers` or `documents_to_sign` are needed when contact emails are already on the entry.

<Note>
  Physical-title label generation is enabled per organization during rollout. In sandbox (`STUB`) responses, `label_url` renders a UPS sample label that is not valid postage, `tracking_number` is `null`, and `qr_url` is absent — the field contract is otherwise identical to production.
</Note>

```bash Bodyless sign request theme={null}
curl -X POST "https://api.cardinalgray.com/title/123e4567-e89b-12d3-a456-426614174000/sign" \
  -H "Authorization: Bearer YOUR_API_KEY"
```


## OpenAPI

````yaml POST /title/{id}/sign
openapi: 3.0.1
info:
  title: Cardinal Gray OpenAPI
  description: OpenAPI for automating vehicle title work
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.cardinalzyn.com
    description: Staging
  - url: https://api.cardinalgray.com
    description: Production
security:
  - bearerAuth: []
  - basicAuth: []
  - cookieAuth: []
paths:
  /title/{id}/sign:
    post:
      description: >-
        Create a signature request for generated title documents. Provide
        explicit signers and documents, or omit the request body to let the API
        build a request from current title owners/borrowers with contact_email
        values already present on the entry.
      parameters:
        - $ref: '#/components/parameters/id'
      requestBody:
        description: >-
          Customization options for the signature request (e.g., in cases where
          you don't want to collect signatures from all titled owners).
        content:
          application/json:
            schema:
              type: object
              properties:
                signers:
                  type: array
                  description: >-
                    List of specific people who should sign the documents. Each
                    signer must include contact_email. If the body is omitted
                    entirely, the API attempts to build signers from current
                    owners/borrowers already stored on the entry.
                  items:
                    $ref: '#/components/schemas/Person'
                  minItems: 1
                documents_to_sign:
                  type: array
                  description: List of specific documents to be signed.
                  items:
                    $ref: '#/components/schemas/DocumentToSign'
                  minItems: 1
                redirect_url:
                  description: >-
                    Optional redirect URL or redirect descriptor used by the
                    signature provider after signing.
                  oneOf:
                    - type: string
                      format: uri
                    - type: object
                      properties:
                        url:
                          type: string
                          format: uri
                        message:
                          type: string
                      required:
                        - url
                requester_email:
                  type: string
                  description: Additional notification email for signature completion
                instructions:
                  type: string
                  description: Special instructions for the signer
        required: false
      responses:
        '200':
          description: >-
            Signature request created successfully. For organizations enrolled
            in physical title collection, titles in states that require the
            original paper title to be returned (e.g. Texas) additionally
            include a title_collection object with return-shipping guidance.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SignatureRequest'
                  - type: object
                    properties:
                      title_collection:
                        $ref: '#/components/schemas/TitleCollection'
        '400':
          description: Missing required fields or invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Response'
        '403':
          description: Organization lacks necessary permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Response'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - bearerAuth: []
        - basicAuth: []
        - cookieAuth: []
components:
  parameters:
    id:
      name: id
      in: path
      required: true
      schema:
        type: string
      description: Unique identifier of the title entry
  schemas:
    Person:
      allOf:
        - $ref: '#/components/schemas/Entity'
        - type: object
          properties:
            type:
              type: string
              enum:
                - PERSON
                - BUSINESS
            dob:
              type: string
            contact_phone:
              type: string
            contact_email:
              type: string
            dlid:
              $ref: '#/components/schemas/DriversLicense'
            ssn:
              type: string
            addr_mailing:
              $ref: '#/components/schemas/Address'
            insurance:
              $ref: '#/components/schemas/Insurance'
            ownership_type:
              type: string
              enum:
                - registered_owner
                - titled_owner
                - co_owner
                - lessor
                - lessee
                - debtor
                - tod_beneficiary
              description: Relationship this person has to the vehicle or transaction
            is_nonobligor:
              type: boolean
              description: Whether this person is a non-obligor on the loan
            transaction_access_url:
              type: string
              format: uri
              readOnly: true
              description: >-
                Per-signer URL for accessing the signature transaction. Present
                on signers in the response from POST /title/{id}/sign when the
                provider is Notarize/Proof. Not applicable to DocuSign-based
                requests.
          required:
            - dob
    DocumentToSign:
      type: object
      properties:
        filename:
          type: string
        id:
          type: string
        signer_id:
          type: array
          items:
            type: string
        signed_copy:
          type: string
    SignatureRequest:
      type: object
      properties:
        transaction_access_url:
          type: string
          format: uri
          readOnly: true
          description: >-
            Top-level transaction URL. Only populated after an explicit activate
            action on a DRAFT Notarize/Proof request. For the initial create
            response, look at each signer's transaction_access_url instead.
        redirect_url:
          type: object
          properties:
            url:
              type: string
            message:
              type: string
          required:
            - url
        requester_email:
          type: string
          description: Additional notification email for signature completion
        id:
          type: string
          description: >-
            Provider-specific ID (NTRZ::id for Notarize, DSGN::id for DocuSign,
            DMNS::id for Documenso, PNDC::id for Pandadoc)
        type:
          type: string
          enum:
            - WET_SIGN
            - WET_NOTARY
            - RON
            - E_SIGN
            - NONE
          description: Type of signature required
        status:
          type: string
          enum:
            - DRAFT
            - SENT
            - OPENED
            - COMPLETED
            - FAILED
            - EXPIRED
          description: Current status of the signature request
        documents_to_sign:
          type: array
          items:
            $ref: '#/components/schemas/DocumentToSign'
        created_at:
          type: string
          description: When the request was created
        updated_at:
          type: string
          description: Last status update
        signers:
          type: array
          description: >-
            Signers on this request. In the response from POST /title/{id}/sign,
            each signer object includes a transaction_access_url field with the
            per-signer signing link (Notarize/Proof provider only).
          items:
            $ref: '#/components/schemas/Person'
        sign_cert:
          type: string
          description: S3 path to signing certification
        collected_dlid:
          type: string
          description: S3 path to collected driver license ID
        full_export:
          type: string
          description: >-
            S3 path to full export consisting of sign cert, collected_dlid, and
            documents_to_sign
        physical_tracking:
          type: object
          properties:
            status:
              type: string
            tracking_url:
              type: string
            label_url:
              type: string
            shipment_id:
              type: string
            return_tracking_url:
              type: string
            return_label_url:
              type: string
            return_shipment_id:
              type: string
        instructions:
          type: string
          description: Any special instructions for the signer
        metadata:
          type: object
          additionalProperties: true
          description: Additional provider-specific metadata
    TitleCollection:
      type: object
      description: >-
        Physical title return guidance. Present when the organization is
        enrolled in physical title collection and the title's signing state
        requires the original paper title to be shipped back to Cardinal Gray
        (e.g. Texas). Additive and may be absent — clients must tolerate its
        absence. Created at most once per title: repeated sign actions and
        retries return the same collection_id rather than creating a new
        collection.
      properties:
        collection_id:
          type: string
          format: uuid
          description: >-
            Stable identifier for this title's collection. Does not change
            across retries or repeated sign requests.
        mode:
          type: string
          enum:
            - STUB
            - LIVE
          description: >-
            Fulfillment mode: LIVE is a real, trackable UPS shipment; STUB is
            the sandbox experience (sample non-postage label, null
            tracking_number, no qr_url). The field contract is identical in both
            modes.
        carrier:
          type: string
          enum:
            - UPS
          description: Shipping carrier for the title return.
        service:
          type: string
          description: Carrier service used, e.g. "UPS Electronic Return Label".
        tracking_number:
          type: string
          nullable: true
          description: >-
            Carrier tracking number. Null until a carrier shipment exists.
            Clients must handle null.
        label_url:
          type: string
          format: uri
          description: >-
            URL of the printable UPS return label. The guaranteed printable
            fallback when present. In sandbox (STUB) responses this renders a
            UPS sample label that is not valid postage.
        qr_url:
          type: string
          format: uri
          description: >-
            Optional URL of a UPS mobile drop-off QR barcode. Present only when
            qr_verified is true. Clients must not assume this field exists.
        qr_verified:
          type: boolean
          description: >-
            True only when qr_url is a verified UPS mobile drop-off barcode
            accepted at UPS locations.
        assets_expires_at:
          type: string
          format: date-time
          description: >-
            Expiry of the presigned label/QR asset URLs. Do not cache asset URLs
            indefinitely.
        return_address:
          type: string
          description: Postal address the original title must be returned to.
        instructions:
          type: array
          items:
            type: string
          description: Ordered, human-readable instructions to present to the borrower.
        created_at:
          type: string
          format: date-time
          description: When the collection was created.
      required:
        - collection_id
        - mode
        - carrier
        - service
        - return_address
        - instructions
        - created_at
    Response:
      type: object
      properties:
        error:
          type: string
          description: Error message
        statusCode:
          type: number
          description: >-
            HTTP status code. Present on selected success responses, such as
            DELETE /title/{id}.
        disallowedFields:
          type: array
          items:
            type: string
          description: >-
            Fields rejected by PATCH /title/{id} when attempting to modify
            restricted top-level fields
    Entity:
      type: object
      properties:
        id:
          type: string
          description: >-
            Use this field to pass your internal uuid for an entity, or let
            Cardinal Gray generate one
        type:
          type: string
          enum:
            - PERSON
            - DEALERSHIP
            - BUSINESS
            - LIENHOLDER
          description: Type of entity
        name:
          type: string
          description: >-
            Full name of owner in First Middle Last format. If found in Last,
            First Middle format, convert it
        name_first:
          type: string
          description: First name component
        name_middle:
          type: string
          description: Middle name component
        name_last:
          type: string
          description: Last name component
        name_suffix:
          type: string
          description: Name suffix (e.g., Jr., Sr., III)
        oats_names:
          type: array
          items:
            type: string
            description: >-
              Each additional name for the owner in First Middle Last format; do
              not confuse separate owners for an oats name
          description: >-
            Sometimes the same document can contain multiple names for the same
            person (i.e. the mailing info says Harper Smith but the section
            under titled or registered owners says John Smith-Avery), please
            list the additional names (in this case the former) in the
            oats_names array
        addr:
          $ref: '#/components/schemas/Address'
          description: Physical/residential address of the owner
        contact_phone:
          type: string
          description: Phone number for the owner
        contact_email:
          type: string
          description: Email address for the owner
      required:
        - type
        - name
        - addr
    DriversLicense:
      type: object
      properties:
        number:
          type: string
          description: Driver's license number
        state:
          type: string
          description: Two-letter code of state that issued the license
        sex:
          type: string
          description: Gender/sex as listed on license (typically 'M' or 'F')
        expiration_date:
          type: string
          description: License expiration date, format MM/DD/YYYY preferred
        first_name:
          type: string
          description: First name as it appears on license
        middle_name:
          type: string
          description: Middle name or initial as it appears on license
        last_name:
          type: string
          description: Last name as it appears on license
        suffix:
          type: string
          description: Name suffix (e.g., Jr., Sr., III)
        addr:
          $ref: '#/components/schemas/Address'
          description: Address as it appears on the driver's license
      required:
        - number
        - state
        - sex
    Address:
      type: object
      properties:
        recipient_name:
          type: string
          description: Name of the recipient at this address
        street1:
          type: string
          description: Primary street address line
        street2:
          type: string
          description: Secondary street address line (apartment, unit, etc.)
        city:
          type: string
          description: City name
        county:
          type: string
          description: County name
        state:
          type: string
          description: State abbreviation
        zip:
          type: string
          description: ZIP/postal code
      required:
        - street1
        - city
        - state
        - zip
    Insurance:
      type: object
      properties:
        provider_name:
          type: string
          description: Insurance company name (e.g., 'GEICO', 'State Farm')
        provider_naic:
          type: string
          description: National Association of Insurance Commissioners code
        policy_number:
          type: string
          description: Insurance policy number
      description: Vehicle insurance information
  responses:
    NotFound:
      description: Not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Response'
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Response'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key or Clerk JWT supplied as Authorization: Bearer <token>'
    basicAuth:
      type: http
      scheme: basic
      description: >-
        Legacy API key authentication supplied with Authorization: Basic
        <api_key>
    cookieAuth:
      type: apiKey
      in: cookie
      name: __session
      description: Clerk session cookie authentication

````