openapi: 3.1.0
info:
  title: Hail
  description:
    "Give your AI agent a voice, a real phone number, and an inbox.\n\n\
    This file is the source of truth for the Go CLI. Regenerate it after\nchanging\
    \ API routes \u2014 see docs/public/contributing.md.\n"
  version: 0.1.0
servers:
  - url: https://api.hail.so
    description: Hail Cloud
paths:
  /v1/calls:
    post:
      tags:
        - calls
      summary: Create Call
      description:
        "Place an outbound AI voice call.\n\nThe call is placed asynchronously\
        \ \u2014 this returns as soon as the call is\nqueued, not when it completes.\
        \ Poll GET /v1/calls/{call_id} or configure a\nwebhook to get the final status\
        \ and transcript. Requires\nrecipient_consent=true on the request body; Hail\
        \ does not verify lawful\nbasis to contact the recipient, the caller warrants\
        \ it."
      operationId: create_call_v1_calls_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Idempotency-Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CallCreate"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CallResponse"
        "429":
          description:
            Rate limited. The agent-origin workspace exceeded a per-channel
            velocity cap, or the platform kill switch is on. Retry after the Retry-After
            header (seconds). Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - calls
      summary: List Calls
      description: "List calls for the caller's organization, newest first.


        Cursor-paginated: pass the returned next_cursor to fetch the next page;

        a null next_cursor means there are no more results. Filter by status or

        destination number (to) to narrow the list."
      operationId: list_calls_v1_calls_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: status
          in: query
          required: false
          schema:
            anyOf:
              - enum:
                  - queued
                  - dialing
                  - ringing
                  - in_progress
                  - completed
                  - failed
                  - busy
                  - no_answer
                  - canceled
                type: string
              - type: "null"
            title: Status
        - name: to
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: To
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CallListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/calls/{call_id}:
    get:
      tags:
        - calls
      summary: Get Call
      description:
        "Fetch one call by id, including its current status and end reason.


        Org-scoped: returns 404 for a call belonging to a different organization

        (not 403, to avoid confirming the id exists). Use this to poll for the

        final outcome of a call placed with POST /v1/calls."
      operationId: get_call_v1_calls__call_id__get
      parameters:
        - name: call_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Call Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CallResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/email-attachments:
    post:
      tags:
        - email-attachments
      summary: Create Email Attachment
      description: "Upload a file and get back a reusable attachment id.


        The returned id can be referenced from attachment_ids on many later

        POST /v1/emails calls until it is garbage-collected for being unused; it is

        not deleted immediately after first use. Uploads are size-limited and

        scoped to the caller's organization."
      operationId: upload_email_attachment
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: "#/components/schemas/Body_upload_email_attachment"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailAttachmentUploadResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/emails:
    post:
      tags:
        - emails
      summary: Create Email
      description:
        "Send an outbound email through SES.\n\nSends synchronously \u2014\
        \ the response reports the final status (sent or\nfailed), not a queued placeholder;\
        \ no separate poll is needed for the\nhappy path, though a bounce or complaint\
        \ can still arrive later as a\nwebhook or GET /v1/emails/{email_id}/events\
        \ entry. Requires\nrecipient_consent=true on the request body; Hail does not\
        \ verify lawful\nbasis to contact the recipient, the caller warrants it."
      operationId: create_email_v1_emails_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Idempotency-Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EmailCreate"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailResponse"
        "429":
          description:
            Rate limited. The agent-origin workspace exceeded a per-channel
            velocity cap, or the platform kill switch is on. Retry after the Retry-After
            header (seconds). Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - emails
      summary: List Emails
      description:
        "List emails for the caller's organization, newest first.\n\nCursor-paginated:\
        \ pass the returned next_cursor to fetch the next page;\na null next_cursor\
        \ means there are no more results. Filter by status or\ndirection (outbound/inbound).\
        \ List entries omit body_text/body_html \u2014\nfetch GET /v1/emails/{email_id}\
        \ for the full body."
      operationId: list_emails_v1_emails_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: status
          in: query
          required: false
          schema:
            anyOf:
              - enum:
                  - queued
                  - sent
                  - delivered
                  - failed
                  - bounced
                  - complained
                  - received
                type: string
              - type: "null"
            title: Status
        - name: direction
          in: query
          required: false
          schema:
            anyOf:
              - enum:
                  - outbound
                  - inbound
                type: string
              - type: "null"
            title: Direction
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/emails/{email_id}/events:
    get:
      tags:
        - emails
      summary: List Email Events
      description: "Chronological lifecycle events for one email (org-scoped).


        Cursor-paginated with the same forward-walk shape as ``GET /events``:

        strictly-greater on ``(occurred_at, id)``, ascending."
      operationId: list_email_events_v1_emails__email_id__events_get
      parameters:
        - name: email_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Email Id
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 1000
            minimum: 1
            default: 100
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailEventListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/emails/stats:
    get:
      tags:
        - emails
      summary: Get Email Stats
      description:
        'Aggregate send/delivery/open/click/bounce counts and rates over
        a range.


        Defaults to the last 7 days, bucketed by day. bucket=hour is limited to

        an 8-day range; any bucket size is limited to a 92-day range. Registered

        above GET /v1/emails/{email_id} so "stats" is not swallowed by the id path
        param.'
      operationId: get_email_stats_v1_emails_stats_get
      parameters:
        - name: from
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date-time
              - type: "null"
            title: From
        - name: to
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date-time
              - type: "null"
            title: To
        - name: bucket
          in: query
          required: false
          schema:
            enum:
              - hour
              - day
            type: string
            default: day
            title: Bucket
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailStatsResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/emails/{email_id}:
    get:
      tags:
        - emails
      summary: Get Email
      description:
        "Fetch one email by id, including attachments and last event time.


        Org-scoped: returns 404 for an email belonging to a different

        organization. For an inbound email with a stored raw MIME, raw_url

        points at GET /v1/emails/{email_id}/raw."
      operationId: get_email_v1_emails__email_id__get
      parameters:
        - name: email_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Email Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/emails/{email_id}/raw:
    get:
      tags:
        - emails
      summary: Get Email Raw
      description:
        "302 \u2192 presigned S3 URL for the raw inbound MIME (404 for\
        \ outbound)."
      operationId: get_email_raw_v1_emails__email_id__raw_get
      parameters:
        - name: email_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Email Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema: {}
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/emails/{email_id}/attachments/{attachment_id}:
    get:
      tags:
        - emails
      summary: Get Email Attachment
      description: "302 \u2192 presigned S3 URL for one attachment."
      operationId: get_email_attachment_v1_emails__email_id__attachments__attachment_id__get
      parameters:
        - name: email_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Email Id
        - name: attachment_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Attachment Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema: {}
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/events:
    get:
      tags:
        - events
      summary: List Events
      description:
        "Cursor-paginated forward stream of call, email, and SMS events.\n\
        \nScoped to the caller's organization. Pass id (typed \"<type>:<uuid>\",\n\
        e.g. \"call:<uuid>\") to narrow to one resource's events, or kind to\nnarrow\
        \ to one event kind. Walks forward in time \u2014 pass the returned\nnext_cursor\
        \ to continue tailing where you left off."
      operationId: list_events_v1_events_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 1000
            minimum: 1
            default: 100
            title: Limit
        - name: id
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Id
        - name: kind
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Kind
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventStreamResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/email-domains:
    post:
      tags:
        - email-domains
      summary: Create Email Domain
      description:
        "Register a sender identity to send outbound email through.\n\n\
        kind=\"hail_mail\" mints an address on the shared hail-mail domain and is\n\
        immediately verified \u2014 no DNS work needed. kind=\"custom\" registers\
        \ your\nown domain with SES and returns DKIM records; the domain stays\nunverified\
        \ (POST /v1/email-domains/{domain_id}/verify) until you publish\nthose DNS\
        \ records and Hail confirms them."
      operationId: create_email_domain_v1_email_domains_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EmailDomainCreate"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailDomainResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - email-domains
      summary: List Email Domains
      description:
        "List sender domains/identities for the caller's organization.\n\
        \nCursor-paginated, newest first. The response also includes\ndefault_from\
        \ \u2014 the address a from-less POST /v1/emails would use right\nnow given\
        \ the org's current verified senders."
      operationId: list_email_domains_v1_email_domains_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailDomainListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/email-domains/check-domain:
    get:
      tags:
        - email-domains
      summary: Check Domain
      description: Does this domain already receive mail? Drives apex-vs-prefix onboarding.
      operationId: check_domain_v1_email_domains_check_domain_get
      parameters:
        - name: domain
          in: query
          required: true
          schema:
            type: string
            title: Domain
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DomainCheckResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/email-domains/{domain_id}:
    get:
      tags:
        - email-domains
      summary: Get Email Domain
      description:
        "Fetch one sender domain/identity by id, including its DNS records.


        Org-scoped: returns 404 for a domain belonging to a different

        organization. For a pending custom domain, dns_records lists the DKIM

        records still to publish."
      operationId: get_email_domain_v1_email_domains__domain_id__get
      parameters:
        - name: domain_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Domain Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailDomainResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    patch:
      tags:
        - email-domains
      summary: Patch Email Domain
      description:
        "Edit hail-mail prefixes and/or inbound action settings.\n\nTwo\
        \ modes, mutually compatible:\n\n* **Prefix edit** (``local_prefix_user``\
        \ / ``local_prefix_org``):\n  hail_mail rows only. The managed-cloud console\
        \ writes here when\n  an org admin changes the visible hail-mail address.\n\
        * **Inbound action edit** (``inbound_enabled`` / ``forward_to`` /\n  ``forward_rate_per_hour``):\
        \ any row kind."
      operationId: patch_email_domain_v1_email_domains__domain_id__patch
      parameters:
        - name: domain_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Domain Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EmailDomainPatch"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailDomainResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    delete:
      tags:
        - email-domains
      summary: Delete Email Domain
      description:
        "Permanently remove a sender domain/identity.\n\nIrreversible \u2014\
        \ for a custom domain, also deletes the SES identity, so\nthe domain can no\
        \ longer send until re-registered and re-verified.\nFails with 409 if any\
        \ Email rows still reference this domain; delete\nor wait for those to age\
        \ out first."
      operationId: delete_email_domain_v1_email_domains__domain_id__delete
      parameters:
        - name: domain_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Domain Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/email-domains/{domain_id}/verify:
    post:
      tags:
        - email-domains
      summary: Verify Email Domain
      description:
        "Re-poll the email provider for the current verification status.\n\
        \nOn-demand only \u2014 there is no background poller in v1. Operators /\n\
        tenants hit this after publishing DNS to flip the row to ``verified``.\nHail-mail\
        \ rows are no-ops (they're already verified by construction)."
      operationId: verify_email_domain_v1_email_domains__domain_id__verify_post
      parameters:
        - name: domain_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Domain Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailDomainResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/numbers:
    post:
      tags:
        - numbers
      summary: Acquire Number
      description:
        "Buy a dedicated phone number for the caller's organization.\n\n\
        This purchases a real number at the carrier and starts a recurring\nmonthly\
        \ fee immediately \u2014 it is not a reservation. The number is usable\nfor\
        \ voice, SMS, or both depending on the requested capabilities and\nwhat the\
        \ carrier offers for the given country_code/number_type."
      operationId: acquire_number_v1_numbers_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Idempotency-Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/NumberAcquireRequest"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PhoneNumberResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - numbers
      summary: List Numbers
      description:
        "List dedicated numbers owned by the caller's organization.\n\n\
        Cursor-paginated, newest first. Only org-owned numbers are listed \u2014\n\
        shared pool numbers used for outbound calls never appear here."
      operationId: list_numbers_v1_numbers_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PhoneNumberListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/numbers/{number_id}:
    delete:
      tags:
        - numbers
      summary: Release Number
      description:
        "Release a dedicated number. The monthly fee stops accruing after
        the

        release month; months already accrued stay owed (the rater bills late,

        never forgives)."
      operationId: release_number_v1_numbers__number_id__delete
      parameters:
        - name: number_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Number Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - numbers
      summary: Get Number
      description:
        "Fetch one dedicated number by id, including its capabilities and
        state.


        Org-scoped: returns 404 for a number belonging to a different

        organization."
      operationId: get_number_v1_numbers__number_id__get
      parameters:
        - name: number_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Number Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PhoneNumberResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/numbers/{number_id}/enable-sms:
    post:
      tags:
        - numbers
      summary: Enable Sms
      description:
        "Attach a dedicated number to the org's shared SMS Messaging Service.\n\
        \nRequired once per number before it can send/receive SMS; the number\nmust\
        \ already have been acquired with sms capability. Idempotent \u2014\ncalling\
        \ this again on an already-enabled number just returns its\ncurrent state.\
        \ Fails with 422 for a released number or one that lacks\nsms capability."
      operationId: enable_sms_v1_numbers__number_id__enable_sms_post
      parameters:
        - name: number_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Number Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PhoneNumberResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/webhooks:
    post:
      tags:
        - webhooks
      summary: Create Subscription
      description:
        "Create a webhook subscription for one or more event types.\n\n\
        The response includes the plaintext signing secret \u2014 this is the only\n\
        time it is ever returned; store it now. Every later GET omits it. Use\nPOST\
        \ /v1/webhooks/{sub_id}/rotate-secret to get a new plaintext secret if\nit\
        \ is lost or compromised."
      operationId: create_subscription_v1_webhooks_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookSubscriptionCreate"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookSubscriptionResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - webhooks
      summary: List Subscriptions
      description:
        "List webhook subscriptions for the caller's organization.\n\n\
        Cursor-paginated, newest first. The signing secret is never included \u2014\
        \nonly POST /v1/webhooks and POST /v1/webhooks/{sub_id}/rotate-secret return\
        \ it."
      operationId: list_subscriptions_v1_webhooks_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookSubscriptionListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/webhooks/{sub_id}:
    get:
      tags:
        - webhooks
      summary: Get Subscription
      description: Fetch one webhook subscription by id. The signing secret is omitted.
      operationId: get_subscription_v1_webhooks__sub_id__get
      parameters:
        - name: sub_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sub Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookSubscriptionResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    patch:
      tags:
        - webhooks
      summary: Patch Subscription
      description:
        'Update a webhook subscription''s target_url, event_types, and/or
        status.


        Only fields present in the request body are changed. Setting

        status="active" resets the consecutive-failure counter, so a

        subscription that was auto-disabled after 50 straight delivery

        failures does not immediately re-disable itself.'
      operationId: patch_subscription_v1_webhooks__sub_id__patch
      parameters:
        - name: sub_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sub Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookSubscriptionPatch"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookSubscriptionResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    delete:
      tags:
        - webhooks
      summary: Delete Subscription
      description:
        "Permanently remove a webhook subscription.\n\nIrreversible \u2014\
        \ no further events are delivered to it, and its\ndelivery history is deleted\
        \ with it."
      operationId: delete_subscription_v1_webhooks__sub_id__delete
      parameters:
        - name: sub_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sub Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/webhooks/{sub_id}/rotate-secret:
    post:
      tags:
        - webhooks
      summary: Rotate Secret
      description:
        "Generate a new signing secret and immediately invalidate the old\
        \ one.\n\nThe response includes the new plaintext secret \u2014 this is the\
        \ only\ntime it is returned; update your verification code with it right away,\n\
        since the old secret stops validating new deliveries immediately."
      operationId: rotate_secret_v1_webhooks__sub_id__rotate_secret_post
      parameters:
        - name: sub_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sub Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookSubscriptionResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/webhooks/{sub_id}/deliveries:
    get:
      tags:
        - webhooks
      summary: List Deliveries
      description:
        "List delivery attempts for one webhook subscription, newest first.\n\
        \nCursor-paginated. Each entry shows the attempt count, response status,\n\
        and response body Hail recorded \u2014 use POST /v1/webhooks/{sub_id}/\ndeliveries/{delivery_id}/redeliver\
        \ to retry a failed one."
      operationId: list_deliveries_v1_webhooks__sub_id__deliveries_get
      parameters:
        - name: sub_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sub Id
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDeliveryListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/webhooks/{sub_id}/deliveries/{delivery_id}/redeliver:
    post:
      tags:
        - webhooks
      summary: Redeliver
      description:
        "Retry one webhook delivery attempt.\n\nResets it to pending with\
        \ a fresh attempt counter \u2014 the delivery\nworker picks it up and re-sends\
        \ the same event payload to target_url\nshortly after. Useful after fixing\
        \ an endpoint that was returning\nerrors."
      operationId: redeliver_v1_webhooks__sub_id__deliveries__delivery_id__redeliver_post
      parameters:
        - name: sub_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sub Id
        - name: delivery_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Delivery Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDeliveryResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/unsubscribe:
    get:
      tags:
        - unsubscribe
      summary: Unsubscribe
      description:
        "One-click email opt-out (RFC 8058), reached by clicking a link\
        \ in a sent email.\n\nPublic and unauthenticated \u2014 the signed token query\
        \ param is the sole\ncredential, proving the caller holds a link Hail sent\
        \ to that address.\nOn success, the address is added to the org's suppression\
        \ list and all\nfuture outbound email to it is blocked. Returns an HTML page,\
        \ not JSON."
      operationId: unsubscribe_v1_unsubscribe_get
      parameters:
        - name: token
          in: query
          required: true
          schema:
            type: string
            title: Token
      responses:
        "200":
          description: Successful Response
          content:
            text/html:
              schema:
                type: string
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/sms:
    post:
      tags:
        - sms
      summary: Create Sms
      description:
        "Send an outbound SMS.\n\nSends synchronously \u2014 the response\
        \ reports the final status (sent or\nfailed), not a queued placeholder, though\
        \ delivery confirmation from\nthe carrier can still arrive later as a webhook\
        \ or GET /v1/sms/{sms_id}\nupdate. An explicit from resolves a dedicated number;\
        \ otherwise Hail\npicks an alphanumeric sender ID where the destination corridor\
        \ allows\nit, or requires a dedicated SMS-capable number otherwise. Requires\n\
        recipient_consent=true on the request body; Hail does not verify\nlawful basis\
        \ to contact the recipient, the caller warrants it."
      operationId: create_sms_v1_sms_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Idempotency-Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SmsCreate"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmsResponse"
        "429":
          description:
            Rate limited. The agent-origin workspace exceeded a per-channel
            velocity cap, or the platform kill switch is on. Retry after the Retry-After
            header (seconds). Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    get:
      tags:
        - sms
      summary: List Sms
      description:
        "List SMS messages for the caller's organization, newest first.


        Cursor-paginated: pass the returned next_cursor to fetch the next page;

        a null next_cursor means there are no more results. Filter by status or

        destination number (to) to narrow the list."
      operationId: list_sms_v1_sms_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: status
          in: query
          required: false
          schema:
            anyOf:
              - enum:
                  - queued
                  - sent
                  - delivered
                  - failed
                  - undelivered
                  - received
                type: string
              - type: "null"
            title: Status
        - name: to
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: To
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmsListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/sms/suppressions:
    get:
      tags:
        - sms
      summary: List Sms Suppressions
      description:
        "List SMS numbers suppressed from receiving messages, newest first.


        Cursor-paginated. A suppressed number blocks POST /v1/sms sends to it

        with a 403 until removed via DELETE /v1/sms/suppressions/{number}."
      operationId: list_sms_suppressions_v1_sms_suppressions_get
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            default: 50
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuppressionListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/sms/suppressions/{number}:
    delete:
      tags:
        - sms
      summary: Delete Sms Suppression
      description:
        "Remove one number from the SMS suppression list, re-allowing sends\
        \ to it.\n\nDoes not itself constitute renewed consent \u2014 the caller is\
        \ responsible\nfor having a lawful basis (e.g. a fresh opt-in) before sending\
        \ again.\nReturns 404 if the number was not suppressed."
      operationId: delete_sms_suppression_v1_sms_suppressions__number__delete
      parameters:
        - name: number
          in: path
          required: true
          schema:
            type: string
            title: Number
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/sms/sender-id:
    get:
      tags:
        - sms
      summary: Get Sender Id
      description:
        "Get the org's custom alphanumeric SMS sender ID, if any is set.


        effective_default is the platform sender id used for

        alphanumeric-eligible corridors when custom_sender_id is null."
      operationId: get_sender_id_v1_sms_sender_id_get
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SenderIdResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    patch:
      tags:
        - sms
      summary: Patch Sender Id
      description:
        "Set or clear the org's custom alphanumeric SMS sender ID.\n\n\
        Pass custom_sender_id=null to clear it and fall back to the platform\ndefault\
        \ sender id. Only affects alphanumeric-eligible corridors \u2014 a\ncorridor\
        \ requiring a dedicated number is unaffected."
      operationId: patch_sender_id_v1_sms_sender_id_patch
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SenderIdPatch"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SenderIdResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/sms/{sms_id}:
    get:
      tags:
        - sms
      summary: Get Sms
      description: "Fetch one SMS by id, including its current status.


        Org-scoped: returns 404 for an SMS belonging to a different

        organization."
      operationId: get_sms_v1_sms__sms_id__get
      parameters:
        - name: sms_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Sms Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmsResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/contacts:
    get:
      tags:
        - contacts
      summary: List Contacts
      description:
        "List contacts for the caller's organization, newest first.\n\n\
        Merges two sources into one list: org members (kind=\"member\", ids\nprefixed\
        \ \"member:\", managed via membership \u2014 not editable here) and\nmanually-created\
        \ contacts (kind=\"manual\", editable via PATCH/DELETE\n/contacts/{contact_id}).\
        \ Cursor-paginated; q does a substring search\nover name/phone/email."
      operationId: list_contacts_v1_contacts_get
      parameters:
        - name: q
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Q
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Cursor
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 500
            minimum: 1
            default: 100
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    post:
      tags:
        - contacts
      summary: Create Contact
      description: "Create a manual contact with a phone and/or an email.


        Requires at least one of phone_e164 or email. Fails with 409 if a

        contact with the same phone or email already exists in this

        organization."
      operationId: create_contact_v1_contacts_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactCreate"
      responses:
        "201":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactEntry"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/contacts/{contact_id}:
    patch:
      tags:
        - contacts
      summary: Patch Contact
      description:
        "Update a manual contact's fields. Only fields present in the body\
        \ change.\n\nManual contacts only \u2014 a member: id (org members synced\
        \ from\nmembership) returns 422; edit those via the membership APIs instead.\n\
        The contact must still have at least one of phone_e164 or email after\nthe\
        \ update. Fails with 409 on a duplicate phone/email."
      operationId: patch_contact_v1_contacts__contact_id__patch
      parameters:
        - name: contact_id
          in: path
          required: true
          schema:
            type: string
            title: Contact Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactPatch"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactEntry"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    delete:
      tags:
        - contacts
      summary: Delete Contact
      description:
        "Permanently remove a manual contact.\n\nManual contacts only \u2014\
        \ a member: id returns 422; org members are\nremoved via the membership APIs,\
        \ not this route. Irreversible."
      operationId: delete_contact_v1_contacts__contact_id__delete
      parameters:
        - name: contact_id
          in: path
          required: true
          schema:
            type: string
            title: Contact Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/members/{user_id}/phone:
    put:
      tags:
        - contacts
      summary: Put Member Phone
      description:
        "Set an org member's phone number.\n\nPass user_id=\"me\" to set\
        \ your own, or a member's user id \u2014 setting\nanother member's phone requires\
        \ the caller to be an org owner or\nadmin. Returns 404 if the target is not\
        \ a member of this organization."
      operationId: put_member_phone_v1_members__user_id__phone_put
      parameters:
        - name: user_id
          in: path
          required: true
          schema:
            type: string
            title: User Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MemberPhonePut"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
                title: Response Put Member Phone V1 Members  User Id  Phone Put
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
    delete:
      tags:
        - contacts
      summary: Delete Member Phone
      description:
        "Clear an org member's phone number.\n\nPass user_id=\"me\" to\
        \ clear your own, or a member's user id \u2014 clearing\nanother member's\
        \ phone requires the caller to be an org owner or\nadmin. Returns 404 if the\
        \ target is not a member of this organization."
      operationId: delete_member_phone_v1_members__user_id__phone_delete
      parameters:
        - name: user_id
          in: path
          required: true
          schema:
            type: string
            title: User Id
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/whoami:
    get:
      tags:
        - whoami
      summary: Get Whoami
      description:
        "Identify the caller: auth kind, organization, and (if resolvable)
        user.


        Useful for an agent that needs the human's address to put in

        Reply-To, since the bearer token itself only carries an organization.

        user_id/email/name come back null for a shared-key

        (HAIL_API_KEY) call, which has no individual user behind it."
      operationId: get_whoami_v1_whoami_get
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WhoamiResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/providers:
    get:
      tags:
        - providers
      summary: List Providers
      description: Every saved provider row for the caller's organization, all layers.
      operationId: list_providers
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProviderConfigListResponse"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/providers/{layer}:
    put:
      tags:
        - providers
      summary: Upsert Provider
      description:
        "Save a provider for ``layer`` and make it the active one.\n\n\
        A partial write: anything you omit keeps its saved value. Omitting\n``api_key``\
        \ keeps the stored key, ``params`` keys you don't send are\npreserved, and\
        \ omitting ``fallback_enabled`` leaves the flag alone\n(``false`` on a new\
        \ row). The merged result \u2014 not the partial input \u2014\nis validated\
        \ against the layer's schema (422 on a mismatch). 404 on an\nunknown layer."
      operationId: upsert_provider
      parameters:
        - name: layer
          in: path
          required: true
          schema:
            type: string
            title: Layer
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProviderConfigUpsert"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProviderConfigEntry"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/providers/{layer}/{provider}:
    delete:
      tags:
        - providers
      summary: Delete Provider
      description:
        "Delete one provider row. Deleting the active row promotes the

        most-recently-updated sibling. Idempotent: deleting a row that isn't

        there is a 204 too. 404 on an unknown layer."
      operationId: delete_provider
      parameters:
        - name: layer
          in: path
          required: true
          schema:
            type: string
            title: Layer
        - name: provider
          in: path
          required: true
          schema:
            type: string
            title: Provider
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      responses:
        "204":
          description: Successful Response
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/providers/{layer}/activate:
    post:
      tags:
        - providers
      summary: Activate Provider
      description:
        "Switch which saved provider is active for ``layer``. 404 when
        that

        provider has no saved config."
      operationId: activate_provider
      parameters:
        - name: layer
          in: path
          required: true
          schema:
            type: string
            title: Layer
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProviderActivateRequest"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProviderConfigEntry"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /v1/providers/{layer}/validate:
    post:
      tags:
        - providers
      summary: Validate Provider
      description: "Probe a provider key against the real provider.


        Empty body tests the layer's active provider with its stored key; send

        ``provider`` to test a specific saved row, or ``api_key`` (plus

        ``provider``/``params``) to test a key before saving it."
      operationId: validate_provider
      parameters:
        - name: layer
          in: path
          required: true
          schema:
            type: string
            title: Layer
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: "null"
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProviderValidateRequest"
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProviderValidateResult"
        "429":
          description:
            Rate limited. This caller exceeded the general request-rate
            ceiling. Retry after the Retry-After header (seconds).
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            RateLimit-Limit:
              description: The request ceiling for the current window.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
  /healthz:
    get:
      summary: Healthz
      description: 'Liveness check. Returns {"status": "ok"} with no auth required.'
      operationId: healthz_healthz_get
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                additionalProperties:
                  type: string
                type: object
                title: Response Healthz Healthz Get
components:
  schemas:
    Body_upload_email_attachment:
      properties:
        file:
          type: string
          contentMediaType: application/octet-stream
          title: File
          description:
            The file to upload, as multipart/form-data. Size-limited; an
            oversize upload is rejected with 422.
      type: object
      required:
        - file
      title: Body_upload_email_attachment
    CallCreate:
      properties:
        recipient_consent:
          type: boolean
          title: Recipient Consent
          description:
            "Attestation that you have obtained the lawful consent required\
            \ to contact this recipient. Hail does not verify consent itself \u2014\
            \ you are responsible for a lawful basis under TCPA/ePrivacy/PECR/CAN-SPAM/GDPR\
            \ as applicable. Rejected (422) if not true."
        consent_source:
          anyOf:
            - type: string
            - type: "null"
          title: Consent Source
          description:
            Where/how consent was obtained (e.g. 'signup form', 'prior
            customer relationship'). Required (non-empty) when message_type is 'marketing'.
        consent_obtained_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Consent Obtained At
          description: When consent was obtained, if known.
        message_type:
          type: string
          enum:
            - marketing
            - informational
          title: Message Type
          description:
            "'marketing' additionally requires a non-empty consent_source.
            Use 'informational' for transactional/service communications."
          default: informational
        to:
          type: string
          title: To
          description: Recipient phone number, E.164 format (e.g. +14155551234).
        from:
          anyOf:
            - type: string
            - type: "null"
          title: From
          description:
            "Caller-id phone number, E.164 format. Must be a number owned
            by the organization with the voice capability. Omitted: an active org-owned
            number is used if one exists, else a number is claimed from the shared
            pool."
        system_prompt:
          anyOf:
            - type: string
            - type: "null"
          title: System Prompt
          description:
            Task instructions for the agent, sent as its leading system
            message. At least one of system_prompt or llm is required; both together
            is also valid.
        llm:
          anyOf:
            - $ref: "#/components/schemas/LLMConfig"
            - type: "null"
          description:
            BYO LLM endpoint the call runs on instead of Hail's default
            model. At least one of system_prompt or llm is required; both together
            is also valid.
        first_message:
          anyOf:
            - type: string
            - type: "null"
          title: First Message
          description:
            "Opening line the agent speaks first. Omitted: the agent waits
            for the callee to speak first."
        ai_disclosure:
          type: boolean
          title: Ai Disclosure
          description:
            "Speak the AI self-disclosure line ('Hi, this is an AI assistant\
            \ calling on behalf of ...') as the first thing on the call. Enabled by\
            \ default. Disable only if you have verified the disclosure is not required\
            \ for this call \u2014 47 CFR 64.1200(b)(1) requires identifying the initiating\
            \ business at the start of artificial-voice calls in the US, and several\
            \ jurisdictions have AI bot-disclosure laws. Hail does not verify this\
            \ for you. The agent still identifies itself as an AI if asked."
          default: true
        voice_config:
          $ref: "#/components/schemas/VoiceConfig"
          description:
            TTS voice, VAD, turn-detection, and spoken-language settings
            for this call.
        conversation_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Conversation Id
          description:
            "Groups this call with other calls/emails/SMS into one conversation
            thread. Omitted: the call is not linked to a conversation."
        metadata:
          additionalProperties: true
          type: object
          title: Metadata
          description:
            Free-form JSON object attached to the call and echoed back
            on reads. Not interpreted by Hail.
        tools:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Tools
          description:
            "Agent tools to allow on this call. Omitted: every tool the
            organization's configured channels support (new channels appear automatically).
            Empty list: no tools. Tool names are validated against the server's registry."
      additionalProperties: false
      type: object
      required:
        - recipient_consent
        - to
      title: CallCreate
    CallListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/CallResponse"
          type: array
          title: Items
          description: Calls in this page, newest first.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: CallListResponse
    CallResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this call.
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization that placed or received this call.
        conversation_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Conversation Id
          description:
            Conversation thread this call is grouped into, if any. Null
            when the call was not linked to a conversation.
        from_e164:
          type: string
          title: From E164
          description: Caller-id phone number used, E.164 format.
        to_e164:
          type: string
          title: To E164
          description: Recipient phone number, E.164 format.
        direction:
          type: string
          enum:
            - outbound
            - inbound
          title: Direction
          description: "'outbound' for calls Hail placed, 'inbound' for calls
            received."
        status:
          type: string
          enum:
            - queued
            - dialing
            - ringing
            - in_progress
            - completed
            - failed
            - busy
            - no_answer
            - canceled
          title: Status
          description:
            "Current call-progress state: 'queued', 'dialing', 'ringing',
            'in_progress', or one of the terminal states 'completed', 'failed',
            'busy', 'no_answer', 'canceled'."
        end_reason:
          anyOf:
            - type: string
            - type: "null"
          title: End Reason
          description:
            Machine-readable reason the call reached a terminal status
            (e.g. 'normal_hangup', 'user_rejected', 'sip_trunk_failure'). Null while
            the call is still in progress.
        provider_call_sid:
          anyOf:
            - type: string
            - type: "null"
          title: Provider Call Sid
          description: The telephony provider's identifier for this call leg, if assigned.
        livekit_room:
          anyOf:
            - type: string
            - type: "null"
          title: Livekit Room
          description:
            Name of the LiveKit room hosting this call's media session,
            if one was created.
        initial_prompt:
          anyOf:
            - type: string
            - type: "null"
          title: Initial Prompt
          description: The system_prompt this call was created with, if any.
        recording_s3_key:
          anyOf:
            - type: string
            - type: "null"
          title: Recording S3 Key
          description:
            Internal storage key for the call recording. Not a directly
            fetchable URL.
        requested_at:
          type: string
          format: date-time
          title: Requested At
          description: When the call was requested, ISO 8601 timestamp.
        started_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Started At
          description:
            When dialing began, ISO 8601 timestamp. Null until the call
            starts.
        answered_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Answered At
          description:
            When the callee answered, ISO 8601 timestamp. Null if never
            answered.
        ended_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Ended At
          description:
            When the call ended, ISO 8601 timestamp. Null while still in
            progress.
      type: object
      required:
        - id
        - organization_id
        - conversation_id
        - from_e164
        - to_e164
        - direction
        - status
        - end_reason
        - provider_call_sid
        - livekit_room
        - initial_prompt
        - recording_s3_key
        - requested_at
        - started_at
        - answered_at
        - ended_at
      title: CallResponse
    ContactCreate:
      properties:
        name:
          type: string
          maxLength: 200
          minLength: 1
          title: Name
          description: Display name for the contact.
        phone_e164:
          anyOf:
            - type: string
            - type: "null"
          title: Phone E164
          description:
            Phone number, E.164 format. At least one of phone_e164 or email
            is required.
        email:
          anyOf:
            - type: string
            - type: "null"
          title: Email
          description:
            Email address, stored lowercased. At least one of phone_e164
            or email is required.
      additionalProperties: false
      type: object
      required:
        - name
      title: ContactCreate
    ContactEntry:
      properties:
        id:
          type: string
          title: Id
          description:
            "'member:<user_id>' for an org member, or the contact row's
            UUID (as a string) for a manual contact."
        kind:
          type: string
          enum:
            - member
            - manual
          title: Kind
          description:
            "'member' if this row is a member of the organization, 'manual'
            if it was added as a contact."
        name:
          type: string
          title: Name
          description: Display name.
        phone_e164:
          anyOf:
            - type: string
            - type: "null"
          title: Phone E164
          description: Phone number, E.164 format. Null if none on file.
        email:
          anyOf:
            - type: string
            - type: "null"
          title: Email
          description: Email address. Null if none on file.
        role:
          anyOf:
            - type: string
            - type: "null"
          title: Role
          description:
            Organization role (e.g. 'owner', 'admin', 'member') for kind='member'.
            Always null for kind='manual'.
      type: object
      required:
        - id
        - kind
        - name
      title: ContactEntry
      description:
        "One row in the computed contacts union \u2014 an org member or\
        \ a manual\ncontact. ``id`` is ``member:<user_id>`` for members, the contact\
        \ row's\nUUID (as str) for manual rows."
    ContactListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/ContactEntry"
          type: array
          title: Items
          description: Contacts in this page.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: ContactListResponse
    ContactPatch:
      properties:
        name:
          anyOf:
            - type: string
              maxLength: 200
              minLength: 1
            - type: "null"
          title: Name
          description:
            New display name. Omit to leave unchanged; cannot be set to
            null.
        phone_e164:
          anyOf:
            - type: string
            - type: "null"
          title: Phone E164
          description:
            New phone number, E.164 format. Omit to leave unchanged; explicit
            null clears it. The contact must keep at least one of phone_e164 or email.
        email:
          anyOf:
            - type: string
            - type: "null"
          title: Email
          description:
            New email address, stored lowercased. Omit to leave unchanged;
            explicit null clears it. The contact must keep at least one of phone_e164
            or email.
      additionalProperties: false
      type: object
      title: ContactPatch
    DnsRecordSchema:
      properties:
        name:
          type: string
          title: Name
          description: DNS record name/host to publish (e.g. a CNAME's subdomain).
        value:
          type: string
          title: Value
          description: DNS record value to publish (e.g. a CNAME target or TXT content).
        type:
          type: string
          enum:
            - CNAME
            - MX
            - TXT
          title: Type
          description: "DNS record type: 'CNAME' (DKIM), 'MX' (MAIL FROM), or
            'TXT' (SPF)."
          default: CNAME
        priority:
          anyOf:
            - type: integer
            - type: "null"
          title: Priority
          description: MX priority. Only present for type='MX'; null otherwise.
      additionalProperties: true
      type: object
      required:
        - name
        - value
      title: DnsRecordSchema
      description: "One DNS record the tenant must publish for a sending domain.


        Covers DKIM CNAMEs, MAIL FROM MX, and SPF TXT records."
    DomainCheckResponse:
      properties:
        domain:
          type: string
          title: Domain
          description: The apex domain that was checked, lowercased.
        in_use:
          type: boolean
          title: In Use
          description:
            "True if the domain already has MX records \u2014 it receives\
            \ mail elsewhere."
        existing_mx:
          items:
            type: string
          type: array
          title: Existing Mx
          description:
            MX hostnames currently published for the domain. Empty when
            in_use is false.
        suggested_domain:
          type: string
          title: Suggested Domain
          description:
            "Domain to use for a custom sending identity: the apex domain
            if it is not already receiving mail, or an 'inbox.' subdomain if it
            is (so setup doesn't collide with existing mail)."
      type: object
      required:
        - domain
        - in_use
        - existing_mx
        - suggested_domain
      title: DomainCheckResponse
    EmailAttachmentResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this attachment.
        filename:
          type: string
          title: Filename
          description: Original filename of the attachment.
        content_type:
          type: string
          title: Content Type
          description: MIME type of the attachment.
        size_bytes:
          type: integer
          title: Size Bytes
          description: Size of the attachment in bytes.
        content_id:
          anyOf:
            - type: string
            - type: "null"
          title: Content Id
          description:
            MIME Content-ID, present when this attachment is referenced
            inline (cid:) from the HTML body. Null otherwise.
        url:
          type: string
          title: Url
          description:
            API endpoint that 302-redirects to a presigned download URL
            for this attachment.
      type: object
      required:
        - id
        - filename
        - content_type
        - size_bytes
        - url
      title: EmailAttachmentResponse
      description:
        "One inbound MIME attachment as exposed to API consumers.\n\n``url``\
        \ is the stable Hail API endpoint that 302-redirects to a\npresigned S3 URL\
        \ on access \u2014 see GET /emails/{id}/attachments/{aid}."
    EmailAttachmentUploadResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description:
            "Reusable attachment id \u2014 pass it in EmailCreate.attachment_ids\
            \ to attach it to a send."
        filename:
          type: string
          title: Filename
          description: Original filename of the uploaded file.
        content_type:
          type: string
          title: Content Type
          description: MIME type of the uploaded file.
        size_bytes:
          type: integer
          title: Size Bytes
          description: Size of the uploaded file in bytes.
      type: object
      required:
        - id
        - filename
        - content_type
        - size_bytes
      title: EmailAttachmentUploadResponse
      description: "Returned by POST /email-attachments.


        ``id`` is reusable across many ``POST /emails`` calls via

        ``EmailCreate.attachment_ids`` until Hail garbage-collects it (24h

        if never referenced by a send)."
    EmailCreate:
      properties:
        recipient_consent:
          type: boolean
          title: Recipient Consent
          description:
            "Attestation that you have obtained the lawful consent required\
            \ to contact this recipient. Hail does not verify consent itself \u2014\
            \ you are responsible for a lawful basis under TCPA/ePrivacy/PECR/CAN-SPAM/GDPR\
            \ as applicable. Rejected (422) if not true."
        consent_source:
          anyOf:
            - type: string
            - type: "null"
          title: Consent Source
          description:
            Where/how consent was obtained (e.g. 'signup form', 'prior
            customer relationship'). Required (non-empty) when message_type is 'marketing'.
        consent_obtained_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Consent Obtained At
          description: When consent was obtained, if known.
        message_type:
          type: string
          enum:
            - marketing
            - informational
          title: Message Type
          description:
            "'marketing' additionally requires a non-empty consent_source.
            Use 'informational' for transactional/service communications."
          default: informational
        from:
          anyOf:
            - type: string
            - type: "null"
          title: From
          description:
            "Sender email address. Must be a verified identity on the organization's
            email domains. Omitted: the org's resolved default sending address, if
            one exists."
        from_name:
          anyOf:
            - type: string
              maxLength: 256
            - type: "null"
          title: From Name
          description: "Display name for the From: header (e.g. 'Acme Billing').
            Omitted: no display name."
        to:
          items:
            type: string
          type: array
          minItems: 1
          title: To
          description: Recipient email addresses. At least one required.
        cc:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Cc
          description: CC recipient email addresses.
        bcc:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Bcc
          description: BCC recipient email addresses.
        reply_to:
          anyOf:
            - type: string
            - type: "null"
          title: Reply To
          description: "Reply-To email address. Omitted: replies go to the From address."
        subject:
          type: string
          maxLength: 998
          minLength: 1
          title: Subject
          description: Email subject line.
        body_text:
          anyOf:
            - type: string
            - type: "null"
          title: Body Text
          description:
            Plain-text body. Either body_text or body_html (or both) is
            required. A plain-text-only email cannot be tracked for opens or clicks;
            include body_html to get those events.
        body_html:
          anyOf:
            - type: string
            - type: "null"
          title: Body Html
          description:
            "HTML body. Either body_text or body_html (or both) is required.
            Prefer including body_html: open and click tracking only works for emails
            with an HTML body. Plain-text-only emails still get sent, delivered, and
            bounce events, but opens and clicks are never tracked."
        conversation_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Conversation Id
          description:
            "Groups this email with other calls/emails/SMS into one conversation
            thread. Omitted: the email is not linked to a conversation."
        metadata:
          additionalProperties: true
          type: object
          title: Metadata
          description:
            Free-form JSON object attached to the email and echoed back
            on reads. Not interpreted by Hail.
        attachment_ids:
          anyOf:
            - items:
                type: string
                format: uuid
              type: array
            - type: "null"
          title: Attachment Ids
          description:
            "Ids returned by POST /email-attachments to attach to this
            send. Omitted: no attachments."
      additionalProperties: false
      type: object
      required:
        - recipient_consent
        - to
        - subject
      title: EmailCreate
    EmailDomainCreate:
      properties:
        kind:
          type: string
          enum:
            - hail_mail
            - custom
          title: Kind
          description:
            "'hail_mail' for a Hail-hosted address (domain omitted, composed
            from the prefix fields), or 'custom' to send from your own domain (domain
            required, prefix fields omitted)."
        domain:
          anyOf:
            - type: string
            - type: "null"
          title: Domain
          description:
            DNS domain to send from (e.g. 'acme.com'). Required for kind='custom';
            must be omitted for kind='hail_mail'.
        local_prefix_user:
          anyOf:
            - type: string
            - type: "null"
          title: Local Prefix User
          description:
            User-chosen local-part prefix for a hail_mail address. Only
            valid for kind='hail_mail'. Falls back to HAIL_MAIL_DEFAULT_USER_PREFIX
            if omitted.
        local_prefix_org:
          anyOf:
            - type: string
            - type: "null"
          title: Local Prefix Org
          description:
            Org-chosen local-part prefix for a hail_mail address. Only
            valid for kind='hail_mail'. Falls back to HAIL_MAIL_DEFAULT_ORG_PREFIX
            if omitted.
      additionalProperties: false
      type: object
      required:
        - kind
      title: EmailDomainCreate
      description: "Request body for POST /email-domains.


        For ``kind='hail_mail'`` ``domain`` is omitted; the server composes

        the full address as ``<local_prefix_user>+<local_prefix_org>@<base>``.

        Both prefixes are optional in the body and fall back to the

        ``HAIL_MAIL_DEFAULT_*_PREFIX`` env vars; the server returns 503 if

        neither is supplied. For ``kind='custom'`` ``domain`` is required and

        the prefix fields must be omitted."
    EmailDomainListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/EmailDomainResponse"
          type: array
          title: Items
          description: Email domains in this page.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
        default_from:
          anyOf:
            - type: string
            - type: "null"
          title: Default From
          description:
            The From address used when a send omits 'from'. Null when no
            such default can be resolved (e.g. multiple verified identities, or none
            that can send yet). Computed across the whole organization, not just this
            page.
      type: object
      required:
        - items
      title: EmailDomainListResponse
    EmailDomainPatch:
      properties:
        local_prefix_user:
          anyOf:
            - type: string
            - type: "null"
          title: Local Prefix User
          description:
            New user local-part prefix. Only valid on kind='hail_mail'
            rows. Omit to leave unchanged.
        local_prefix_org:
          anyOf:
            - type: string
            - type: "null"
          title: Local Prefix Org
          description:
            New org local-part prefix. Only valid on kind='hail_mail' rows.
            Omit to leave unchanged.
        inbound_enabled:
          anyOf:
            - type: boolean
            - type: "null"
          title: Inbound Enabled
          description:
            Whether to accept inbound mail on this domain. Requires forward_to
            (or an existing one) when true. Omit to leave unchanged.
        forward_to:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Forward To
          description: Email addresses to forward inbound mail to. Omit to leave unchanged.
        forward_rate_per_hour:
          anyOf:
            - type: integer
            - type: "null"
          title: Forward Rate Per Hour
          description: Cap on forwarded messages per hour. Omit to leave unchanged.
      additionalProperties: false
      type: object
      title: EmailDomainPatch
      description:
        "Body for PATCH /email-domains/{id}.\n\nTwo clusters of mutable\
        \ fields:\n\n* Hail-mail addressing \u2014 the user/org prefix pair (only\
        \ valid on\n  ``kind='hail_mail'`` rows; the handler returns 422 if a tenant\
        \ tries\n  to PATCH these on a custom row).\n* Inbound action \u2014 ``inbound_enabled``\
        \ + ``forward_to`` + the optional\n  ``forward_rate_per_hour`` cap. These\
        \ apply to either kind, but this\n  milestone routes inbound only to ``hail_mail``\
        \ rows; custom-domain\n  inbound (MX delegation) is the next milestone.\n\n\
        Every field is independently optional so ``PATCH`` semantics work the\nway\
        \ callers expect: send only what you want to change. The route\nenforces the\
        \ cross-field rules (the CHECK constraint on the table\nrequires an action\
        \ when ``inbound_enabled`` is true) \u2014 we don't\nre-implement it here\
        \ because the patch may merge with existing row\nstate to satisfy the invariant."
    EmailDomainResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this email domain.
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization that owns this domain.
        kind:
          type: string
          enum:
            - hail_mail
            - custom
          title: Kind
          description: "'hail_mail' (Hail-hosted address) or 'custom' (your own
            domain)."
        domain:
          type: string
          title: Domain
          description: The DNS domain mail is sent from.
        local_prefix_user:
          anyOf:
            - type: string
            - type: "null"
          title: Local Prefix User
          description: User local-part prefix for a hail_mail address. Null for kind='custom'.
        local_prefix_org:
          anyOf:
            - type: string
            - type: "null"
          title: Local Prefix Org
          description: Org local-part prefix for a hail_mail address. Null for kind='custom'.
        verification_status:
          type: string
          enum:
            - pending
            - verified
            - failed
          title: Verification Status
          description:
            "'pending' (not yet verified), 'verified' (ready to send),
            or 'failed'."
        dns_records:
          items:
            $ref: "#/components/schemas/DnsRecordSchema"
          type: array
          title: Dns Records
          description:
            DNS records (DKIM, MAIL FROM MX, SPF) the tenant must publish
            to verify this domain.
        mail_from_domain:
          anyOf:
            - type: string
            - type: "null"
          title: Mail From Domain
          description:
            Custom MAIL FROM domain, if configured. Null when using the
            provider default.
        mail_from_status:
          anyOf:
            - type: string
            - type: "null"
          title: Mail From Status
          description:
            Verification status of the custom MAIL FROM domain, if one
            is configured. Secondary to verification_status.
        provider:
          type: string
          title: Provider
          description: Email sending provider for this domain (currently always 'ses').
        verified_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Verified At
          description:
            When the domain became verified, ISO 8601 timestamp. Null until
            it is.
        inbound_enabled:
          type: boolean
          title: Inbound Enabled
          description: Whether this domain accepts and forwards inbound mail.
          default: false
        forward_to:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Forward To
          description:
            Email addresses inbound mail is forwarded to, if inbound is
            enabled.
        forward_rate_per_hour:
          anyOf:
            - type: integer
            - type: "null"
          title: Forward Rate Per Hour
          description: Configured cap on forwarded messages per hour, if set.
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When this domain was added, ISO 8601 timestamp.
        updated_at:
          type: string
          format: date-time
          title: Updated At
          description: When this domain was last modified, ISO 8601 timestamp.
        receive_ready:
          anyOf:
            - type: boolean
            - type: "null"
          title: Receive Ready
          description:
            True when the domain's published MX points at Hail's inbound
            host. Only populated by POST /{id}/verify on custom domains; null everywhere
            else.
      type: object
      required:
        - id
        - organization_id
        - kind
        - domain
        - local_prefix_user
        - local_prefix_org
        - verification_status
        - dns_records
        - mail_from_domain
        - provider
        - verified_at
        - created_at
        - updated_at
      title: EmailDomainResponse
      description: "Read view for an email domain.


        The inbound-action fields (``inbound_enabled``, ``forward_to``,

        ``forward_rate_per_hour``) surface what the row has configured for

        incoming mail."
    EmailEventListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/EmailEventResponse"
          type: array
          title: Items
          description: Events for this email, oldest first.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: EmailEventListResponse
    EmailEventResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this event.
        email_id:
          type: string
          format: uuid
          title: Email Id
          description: The email this event belongs to.
        kind:
          type: string
          enum:
            - sent
            - delivered
            - delivery_delayed
            - bounced
            - complained
            - rejected
            - opened
            - clicked
          title: Kind
          description: "Event kind: 'sent', 'delivered', 'delivery_delayed',
            'bounced', 'complained', 'rejected', 'opened', or 'clicked'.
            'opened' and 'clicked' only occur for emails sent with an HTML body;
            plain-text-only emails never produce them."
        payload:
          additionalProperties: true
          type: object
          title: Payload
          description: Event-kind-specific detail, as a free-form JSON object.
        occurred_at:
          type: string
          format: date-time
          title: Occurred At
          description: When this event occurred, ISO 8601 timestamp.
      type: object
      required:
        - id
        - email_id
        - kind
        - payload
        - occurred_at
      title: EmailEventResponse
    EmailListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/EmailSummary"
          type: array
          title: Items
          description: Emails in this page, newest first.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: EmailListResponse
    EmailResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this email.
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization that sent or received this email.
        conversation_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Conversation Id
          description:
            Conversation thread this email is grouped into, if any. Null
            when it was not linked to a conversation.
        email_domain_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Email Domain Id
          description:
            The sending domain used, if from_address belongs to one of
            the org's configured domains.
        direction:
          type: string
          enum:
            - outbound
            - inbound
          title: Direction
          description: "'outbound' for emails Hail sent, 'inbound' for emails
            received."
          default: outbound
        from_address:
          type: string
          title: From Address
          description: Sender email address.
        from_name:
          anyOf:
            - type: string
            - type: "null"
          title: From Name
          description:
            "Display name used on the From: header, when the sender supplied
            one. Always null on inbound rows."
        to_addresses:
          items:
            type: string
          type: array
          title: To Addresses
          description: Recipient email addresses.
        cc_addresses:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Cc Addresses
          description: CC recipient email addresses, if any.
        bcc_addresses:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Bcc Addresses
          description: BCC recipient email addresses, if any.
        reply_to:
          anyOf:
            - type: string
            - type: "null"
          title: Reply To
          description: Reply-To email address, if set.
        subject:
          type: string
          title: Subject
          description: Email subject line.
        status:
          type: string
          enum:
            - queued
            - sent
            - delivered
            - failed
            - bounced
            - complained
            - received
          title: Status
          description:
            "Delivery status: 'queued', 'sent', 'delivered', 'failed',
            'bounced', 'complained', or 'received' (inbound emails)."
        end_reason:
          anyOf:
            - type: string
            - type: "null"
          title: End Reason
          description:
            Reason delivery failed or bounced, if applicable. Null on success
            or while pending.
        provider_message_id:
          anyOf:
            - type: string
            - type: "null"
          title: Provider Message Id
          description: The email provider's identifier for this message, if assigned.
        requested_at:
          type: string
          format: date-time
          title: Requested At
          description: When the send was requested, ISO 8601 timestamp.
        sent_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Sent At
          description:
            When the message was handed to the provider, ISO 8601 timestamp.
            Null until sent.
        failed_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Failed At
          description: When the send failed, ISO 8601 timestamp. Null unless it failed.
        metadata:
          additionalProperties: true
          type: object
          title: Metadata
          description:
            Free-form JSON object attached to the email, as sent on create.
            Not interpreted by Hail.
        body_text:
          anyOf:
            - type: string
            - type: "null"
          title: Body Text
          description: Plain-text body, if any.
        body_html:
          anyOf:
            - type: string
            - type: "null"
          title: Body Html
          description: HTML body, if any.
        message_id:
          anyOf:
            - type: string
            - type: "null"
          title: Message Id
          description:
            RFC 5322 Message-ID header. Inbound emails only; null on outbound
            rows.
        in_reply_to:
          anyOf:
            - type: string
            - type: "null"
          title: In Reply To
          description:
            RFC 5322 In-Reply-To header. Inbound emails only; null on outbound
            rows.
        references_ids:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: References Ids
          description:
            RFC 5322 References header, split into ids. Inbound emails
            only; null on outbound rows.
        spam_verdict:
          anyOf:
            - type: string
            - type: "null"
          title: Spam Verdict
          description:
            Provider spam-scan verdict (e.g. 'PASS'/'FAIL'). Inbound emails
            only; null on outbound rows.
        virus_verdict:
          anyOf:
            - type: string
            - type: "null"
          title: Virus Verdict
          description:
            Provider virus-scan verdict (e.g. 'PASS'/'FAIL'). Inbound emails
            only; null on outbound rows.
        dkim_verdict:
          anyOf:
            - type: string
            - type: "null"
          title: Dkim Verdict
          description:
            Provider DKIM-authentication verdict (e.g. 'PASS'/'FAIL').
            Inbound emails only; null on outbound rows.
        spf_verdict:
          anyOf:
            - type: string
            - type: "null"
          title: Spf Verdict
          description:
            Provider SPF-authentication verdict (e.g. 'PASS'/'FAIL'). Inbound
            emails only; null on outbound rows.
        dmarc_verdict:
          anyOf:
            - type: string
            - type: "null"
          title: Dmarc Verdict
          description:
            Provider DMARC-authentication verdict (e.g. 'PASS'/'FAIL').
            Inbound emails only; null on outbound rows.
        provider_received_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Provider Received At
          description:
            When the provider received this email, ISO 8601 timestamp.
            Inbound emails only.
        raw_url:
          anyOf:
            - type: string
            - type: "null"
          title: Raw Url
          description:
            API endpoint that redirects to the original MIME blob. Inbound
            emails only; null on outbound rows.
        attachments:
          items:
            $ref: "#/components/schemas/EmailAttachmentResponse"
          type: array
          title: Attachments
          description: Inbound MIME attachments on this email. Empty on outbound rows.
          default: []
        last_event_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Last Event At
          description:
            When the most recent delivery event for this email occurred,
            ISO 8601 timestamp.
      type: object
      required:
        - id
        - organization_id
        - conversation_id
        - email_domain_id
        - from_address
        - to_addresses
        - cc_addresses
        - bcc_addresses
        - reply_to
        - subject
        - status
        - end_reason
        - provider_message_id
        - requested_at
        - sent_at
        - failed_at
        - body_text
        - body_html
      title: EmailResponse
    EmailStatsBucket:
      properties:
        sent:
          type: integer
          title: Sent
          description: Emails sent in the window.
          default: 0
        delivered:
          type: integer
          title: Delivered
          description: Emails confirmed delivered in the window.
          default: 0
        delivery_delayed:
          type: integer
          title: Delivery Delayed
          description: Emails with a delivery-delayed event in the window.
          default: 0
        bounced:
          type: integer
          title: Bounced
          description: Emails bounced (soft or hard) in the window.
          default: 0
        bounced_hard:
          type: integer
          title: Bounced Hard
          description: Emails hard-bounced in the window. Subset of bounced.
          default: 0
        complained:
          type: integer
          title: Complained
          description: Emails that received a spam complaint in the window.
          default: 0
        rejected:
          type: integer
          title: Rejected
          description: Emails rejected by the provider before sending, in the window.
          default: 0
        opened:
          type: integer
          title: Opened
          description:
            Total open events in the window, including repeat opens by
            the same recipient. HTML emails only; plain-text-only emails are never
            tracked for opens.
          default: 0
        clicked:
          type: integer
          title: Clicked
          description:
            Total click events in the window, including repeat clicks by
            the same recipient. HTML emails only; plain-text-only emails are never
            tracked for clicks.
          default: 0
        unique_opened:
          type: integer
          title: Unique Opened
          description:
            Distinct emails opened at least once in the window (HTML emails
            only).
          default: 0
        unique_clicked:
          type: integer
          title: Unique Clicked
          description:
            Distinct emails clicked at least once in the window (HTML emails
            only).
          default: 0
        bucket_start:
          type: string
          format: date-time
          title: Bucket Start
          description: Start of this bucket, ISO 8601 timestamp.
      type: object
      required:
        - bucket_start
      title: EmailStatsBucket
    EmailStatsCounts:
      properties:
        sent:
          type: integer
          title: Sent
          description: Emails sent in the window.
          default: 0
        delivered:
          type: integer
          title: Delivered
          description: Emails confirmed delivered in the window.
          default: 0
        delivery_delayed:
          type: integer
          title: Delivery Delayed
          description: Emails with a delivery-delayed event in the window.
          default: 0
        bounced:
          type: integer
          title: Bounced
          description: Emails bounced (soft or hard) in the window.
          default: 0
        bounced_hard:
          type: integer
          title: Bounced Hard
          description: Emails hard-bounced in the window. Subset of bounced.
          default: 0
        complained:
          type: integer
          title: Complained
          description: Emails that received a spam complaint in the window.
          default: 0
        rejected:
          type: integer
          title: Rejected
          description: Emails rejected by the provider before sending, in the window.
          default: 0
        opened:
          type: integer
          title: Opened
          description:
            Total open events in the window, including repeat opens by
            the same recipient. HTML emails only; plain-text-only emails are never
            tracked for opens.
          default: 0
        clicked:
          type: integer
          title: Clicked
          description:
            Total click events in the window, including repeat clicks by
            the same recipient. HTML emails only; plain-text-only emails are never
            tracked for clicks.
          default: 0
        unique_opened:
          type: integer
          title: Unique Opened
          description:
            Distinct emails opened at least once in the window (HTML emails
            only).
          default: 0
        unique_clicked:
          type: integer
          title: Unique Clicked
          description:
            Distinct emails clicked at least once in the window (HTML emails
            only).
          default: 0
      type: object
      title: EmailStatsCounts
    EmailStatsRates:
      properties:
        delivery:
          anyOf:
            - type: number
            - type: "null"
          title: Delivery
          description: delivered / sent for the window. Null when sent == 0.
        bounce:
          anyOf:
            - type: number
            - type: "null"
          title: Bounce
          description: bounced_hard / sent for the window. Null when sent == 0.
        complaint:
          anyOf:
            - type: number
            - type: "null"
          title: Complaint
          description: complained / sent for the window. Null when sent == 0.
        open:
          anyOf:
            - type: number
            - type: "null"
          title: Open
          description:
            unique_opened / sent for the window. Null when sent == 0. Only
            HTML emails can be opened-tracked, so plain-text sends lower this rate.
        click:
          anyOf:
            - type: number
            - type: "null"
          title: Click
          description:
            unique_clicked / sent for the window. Null when sent == 0.
            Only HTML emails can be click-tracked, so plain-text sends lower this
            rate.
      type: object
      title: EmailStatsRates
      description: All None when sent == 0 in the window.
    EmailStatsResponse:
      properties:
        from:
          type: string
          format: date-time
          title: From
          description: Start of the queried window, ISO 8601 timestamp (inclusive).
        to:
          type: string
          format: date-time
          title: To
          description: End of the queried window, ISO 8601 timestamp (exclusive).
        bucket:
          type: string
          enum:
            - hour
            - day
          title: Bucket
          description: Time-bucket size used for the series.
        totals:
          $ref: "#/components/schemas/EmailStatsCounts"
          description: Event counts summed across the whole window.
        rates:
          $ref: "#/components/schemas/EmailStatsRates"
          description:
            Derived rates (delivery, bounce, complaint, open, click) for
            the whole window. Each individual rate is null when sent == 0.
        series:
          items:
            $ref: "#/components/schemas/EmailStatsBucket"
          type: array
          title: Series
          description:
            Per-bucket event counts across the window, in chronological
            order.
      type: object
      required:
        - from
        - to
        - bucket
        - totals
        - rates
        - series
      title: EmailStatsResponse
    EmailSummary:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this email.
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization that sent or received this email.
        conversation_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Conversation Id
          description:
            Conversation thread this email is grouped into, if any. Null
            when it was not linked to a conversation.
        email_domain_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Email Domain Id
          description:
            The sending domain used, if from_address belongs to one of
            the org's configured domains.
        direction:
          type: string
          enum:
            - outbound
            - inbound
          title: Direction
          description: "'outbound' for emails Hail sent, 'inbound' for emails
            received."
          default: outbound
        from_address:
          type: string
          title: From Address
          description: Sender email address.
        from_name:
          anyOf:
            - type: string
            - type: "null"
          title: From Name
          description:
            "Display name used on the From: header, when the sender supplied
            one. Always null on inbound rows."
        to_addresses:
          items:
            type: string
          type: array
          title: To Addresses
          description: Recipient email addresses.
        cc_addresses:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Cc Addresses
          description: CC recipient email addresses, if any.
        bcc_addresses:
          anyOf:
            - items:
                type: string
              type: array
            - type: "null"
          title: Bcc Addresses
          description: BCC recipient email addresses, if any.
        reply_to:
          anyOf:
            - type: string
            - type: "null"
          title: Reply To
          description: Reply-To email address, if set.
        subject:
          type: string
          title: Subject
          description: Email subject line.
        status:
          type: string
          enum:
            - queued
            - sent
            - delivered
            - failed
            - bounced
            - complained
            - received
          title: Status
          description:
            "Delivery status: 'queued', 'sent', 'delivered', 'failed',
            'bounced', 'complained', or 'received' (inbound emails)."
        end_reason:
          anyOf:
            - type: string
            - type: "null"
          title: End Reason
          description:
            Reason delivery failed or bounced, if applicable. Null on success
            or while pending.
        provider_message_id:
          anyOf:
            - type: string
            - type: "null"
          title: Provider Message Id
          description: The email provider's identifier for this message, if assigned.
        requested_at:
          type: string
          format: date-time
          title: Requested At
          description: When the send was requested, ISO 8601 timestamp.
        sent_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Sent At
          description:
            When the message was handed to the provider, ISO 8601 timestamp.
            Null until sent.
        failed_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Failed At
          description: When the send failed, ISO 8601 timestamp. Null unless it failed.
        metadata:
          additionalProperties: true
          type: object
          title: Metadata
          description:
            Free-form JSON object attached to the email, as sent on create.
            Not interpreted by Hail.
      type: object
      required:
        - id
        - organization_id
        - conversation_id
        - email_domain_id
        - from_address
        - to_addresses
        - cc_addresses
        - bcc_addresses
        - reply_to
        - subject
        - status
        - end_reason
        - provider_message_id
        - requested_at
        - sent_at
        - failed_at
      title: EmailSummary
      description:
        "Trimmed view for list endpoints \u2014 drops the message bodies.\n\
        \nBodies can be large and contain PII; paging through a year of mail\nshouldn't\
        \ return every byte of every message just to render a list.\nUse ``EmailResponse``\
        \ (via ``GET /emails/{id}``) for the full row."
    EventResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this event.
        source:
          type: string
          enum:
            - call
            - email
            - sms
          title: Source
          description: "Which channel this event belongs to: 'call', 'email',
            or 'sms'."
        call_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Call Id
          description: The call this event belongs to. Set only when source='call'.
        email_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Email Id
          description: The email this event belongs to. Set only when source='email'.
        sms_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Sms Id
          description: The message this event belongs to. Set only when source='sms'.
        kind:
          type: string
          title: Kind
          description:
            Event kind within the source (e.g. 'queued', 'delivered', 'bounced').
            Vocabulary differs per source.
        payload:
          additionalProperties: true
          type: object
          title: Payload
          description: Event-kind-specific detail, as a free-form JSON object.
        occurred_at:
          type: string
          format: date-time
          title: Occurred At
          description: When this event occurred, ISO 8601 timestamp.
      type: object
      required:
        - id
        - source
        - kind
        - payload
        - occurred_at
      title: EventResponse
      description: One event on the unified GET /events stream (call, email, or SMS).
    EventStreamResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/EventResponse"
          type: array
          title: Items
          description: Events in this page, oldest first.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
        call_status:
          anyOf:
            - type: string
              enum:
                - queued
                - dialing
                - ringing
                - in_progress
                - completed
                - failed
                - busy
                - no_answer
                - canceled
            - type: "null"
          title: Call Status
          description:
            Current status of the call named by the id filter (e.g. id=call:<uuid>).
            Null for org-wide tails and non-call filters, since there is no single
            call to report a status for.
      type: object
      required:
        - items
      title: EventStreamResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: "#/components/schemas/ValidationError"
          type: array
          title: Detail
          description:
            "List of validation errors: each entry gives the field location
            (loc), the problem (msg), and the error type (type)."
      type: object
      title: HTTPValidationError
    LLMConfig:
      properties:
        base_url:
          type: string
          title: Base Url
          description:
            "Public HTTPS base URL of the BYO LLM endpoint the call runs\
            \ on. Must resolve to a public address \u2014 private/internal hosts are\
            \ rejected."
        api_key:
          type: string
          title: Api Key
          description:
            "API key sent to the BYO LLM endpoint. Write-only \u2014 never\
            \ echoed back."
        model:
          type: string
          title: Model
          description: Model name to request from the BYO LLM endpoint.
      additionalProperties: false
      type: object
      required:
        - base_url
        - api_key
        - model
      title: LLMConfig
    MemberPhonePut:
      properties:
        phone_e164:
          type: string
          title: Phone E164
          description: Phone number to save for the caller, E.164 format.
      additionalProperties: false
      type: object
      required:
        - phone_e164
      title: MemberPhonePut
    NumberAcquireRequest:
      properties:
        country_code:
          type: string
          maxLength: 2
          minLength: 2
          title: Country Code
          description:
            ISO alpha-2 country code to acquire a number in (e.g. 'US').
            Case-insensitive.
        number_type:
          type: string
          enum:
            - local
            - mobile
            - toll_free
            - national
          title: Number Type
          description:
            "Kind of number to acquire: 'local', 'mobile', 'toll_free',
            or 'national'."
          default: local
      additionalProperties: false
      type: object
      required:
        - country_code
      title: NumberAcquireRequest
    PhoneNumberListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/PhoneNumberResponse"
          type: array
          title: Items
          description: Numbers in this page.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: PhoneNumberListResponse
    PhoneNumberResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this number.
        e164:
          type: string
          title: E164
          description: The phone number, E.164 format.
        country_code:
          type: string
          title: Country Code
          description: ISO alpha-2 country code this number belongs to.
        number_type:
          type: string
          title: Number Type
          description: "Kind of number: 'local', 'mobile', 'toll_free', or 'national'."
        capabilities:
          items:
            type: string
          type: array
          title: Capabilities
          description:
            Channels this number supports, e.g. ['voice'], ['sms'], or
            both.
        provisioning_state:
          type: string
          title: Provisioning State
          description: "'pending', 'active', 'failed', or 'released'."
        is_dedicated:
          type: boolean
          title: Is Dedicated
          description:
            True if this number is owned by the organization. False for
            shared-pool numbers.
        messaging_service_sid:
          anyOf:
            - type: string
            - type: "null"
          title: Messaging Service Sid
          description:
            Provider messaging-service identifier once SMS has been enabled
            on this number. Null until then.
      type: object
      required:
        - id
        - e164
        - country_code
        - number_type
        - capabilities
        - provisioning_state
        - is_dedicated
      title: PhoneNumberResponse
    ProviderActivateRequest:
      properties:
        provider:
          type: string
          title: Provider
          description: Previously saved provider to make active for this layer.
      additionalProperties: false
      type: object
      required:
        - provider
      title: ProviderActivateRequest
      description: Body of ``POST /providers/{layer}/activate``.
    ProviderConfigEntry:
      properties:
        layer:
          type: string
          enum:
            - llm
            - tts
            - stt
          title: Layer
          description: Voice-pipeline layer this config applies to.
        provider:
          type: string
          title: Provider
          description: Provider name (e.g. 'openai', 'cartesia').
        key_last4:
          anyOf:
            - type: string
            - type: "null"
          title: Key Last4
          description:
            Last 4 characters of the saved API key, for display. Null if
            no key is saved.
        key_set_at:
          anyOf:
            - type: string
            - type: "null"
          title: Key Set At
          description:
            When the API key was last set, ISO 8601 timestamp. Null if
            no key is saved.
        params:
          additionalProperties: true
          type: object
          title: Params
          description: Saved provider-specific config for this row.
        fallback_enabled:
          type: boolean
          title: Fallback Enabled
          description:
            Whether Hail's default provider is used as a fallback if this
            one fails.
        is_active:
          type: boolean
          title: Is Active
          description: True if this is the row currently used by calls on this layer.
      type: object
      required:
        - layer
        - provider
        - key_last4
        - key_set_at
        - params
        - fallback_enabled
        - is_active
      title: ProviderConfigEntry
      description: "One saved provider row. Write-only key: ``key_last4`` and

        ``key_set_at`` are the only key-derived fields that leave the API.


        Every field is required (``key_last4``/``key_set_at`` nullable): the

        serializer always emits all of them, and required response fields

        generate plain values instead of pointers in the Go CLI's client."
    ProviderConfigListResponse:
      properties:
        providers:
          items:
            $ref: "#/components/schemas/ProviderConfigEntry"
          type: array
          title: Providers
          description: Every saved provider row for the organization, across all layers.
      type: object
      required:
        - providers
      title: ProviderConfigListResponse
    ProviderConfigUpsert:
      properties:
        provider:
          type: string
          title: Provider
          description:
            Provider name to save/activate for this layer (e.g. 'openai',
            'cartesia').
        api_key:
          anyOf:
            - type: string
            - type: "null"
          title: Api Key
          description:
            "API key for this provider. Omit to edit params without resending\
            \ the key. Write-only \u2014 never echoed back."
        params:
          additionalProperties: true
          type: object
          title: Params
          description:
            Provider-specific config, validated against the layer's schema
            (LLMParams/TTSParams/STTParams). Only the keys you send are changed; other
            saved keys are kept.
        fallback_enabled:
          anyOf:
            - type: boolean
            - type: "null"
          title: Fallback Enabled
          description:
            Whether to fall back to Hail's default provider on failure.
            Omit to leave unchanged; defaults to false on a new row.
      additionalProperties: false
      type: object
      required:
        - provider
      title: ProviderConfigUpsert
      description:
        "Body of ``PUT /providers/{layer}`` \u2014 save and activate one\
        \ provider.\n\nA partial write. Fields you omit keep the value already saved\
        \ for this\n``(layer, provider)`` pair: omit ``api_key`` to edit params without\n\
        resending the key, send only the ``params`` keys you want to change,\nand\
        \ omit ``fallback_enabled`` to leave the flag as it is. The merged\nresult\
        \ is what gets validated against the layer's schema (422 on a\nmismatch),\
        \ so a partial write can never leave an invalid config behind.\n\nRows are\
        \ keyed by ``(organization, layer, provider)``, so writing a\n*different*\
        \ provider for the same layer starts from scratch rather than\ninheriting\
        \ the previous provider's params. On a brand-new row\n``fallback_enabled``\
        \ defaults to ``false``.\n\nKeys are write-only: no response ever echoes one\
        \ back."
    ProviderValidateRequest:
      properties:
        api_key:
          anyOf:
            - type: string
            - type: "null"
          title: Api Key
          description: Key to test instead of the stored one. Not persisted.
        provider:
          anyOf:
            - type: string
            - type: "null"
          title: Provider
          description: "Provider to test. Omitted: the layer's currently active provider."
        params:
          additionalProperties: true
          type: object
          title: Params
          description: Provider-specific config to test alongside the key.
      additionalProperties: false
      type: object
      title: ProviderValidateRequest
      description:
        "Body of ``POST /providers/{layer}/validate`` \u2014 a live key\
        \ probe.\n\nAll fields optional: with an empty body the layer's active provider\
        \ and\nits stored key are tested. ``provider`` tests that provider's stored\
        \ key\ninstead. ``api_key`` tests a key that has not been saved yet."
    ProviderValidateResult:
      properties:
        status:
          type: string
          title: Status
          description: "Probe outcome: 'valid', 'invalid', or 'indeterminate'
            (the provider could not be reached)."
        message:
          anyOf:
            - type: string
            - type: "null"
          title: Message
          description:
            Human-readable detail about the outcome. 'ok' on success, an
            error description otherwise.
      type: object
      required:
        - status
        - message
      title: ProviderValidateResult
      description: Outcome of a live provider-key probe.
    SenderIdPatch:
      properties:
        custom_sender_id:
          anyOf:
            - type: string
            - type: "null"
          title: Custom Sender Id
          description:
            Alphanumeric sender id (2-11 characters, letters/digits only)
            to use on alphanumeric-eligible corridors instead of a phone number. Explicit
            null clears it, reverting to the platform default.
      additionalProperties: false
      type: object
      title: SenderIdPatch
    SenderIdResponse:
      properties:
        custom_sender_id:
          anyOf:
            - type: string
            - type: "null"
          title: Custom Sender Id
          description:
            The organization's configured alphanumeric sender id. Null
            if none is set.
        effective_default:
          type: string
          title: Effective Default
          description:
            The platform's alphanumeric sender id, used on eligible corridors
            when custom_sender_id is null.
          default: HAIL
      type: object
      required:
        - custom_sender_id
      title: SenderIdResponse
    SmsCreate:
      properties:
        recipient_consent:
          type: boolean
          title: Recipient Consent
          description:
            "Attestation that you have obtained the lawful consent required\
            \ to contact this recipient. Hail does not verify consent itself \u2014\
            \ you are responsible for a lawful basis under TCPA/ePrivacy/PECR/CAN-SPAM/GDPR\
            \ as applicable. Rejected (422) if not true."
        consent_source:
          anyOf:
            - type: string
            - type: "null"
          title: Consent Source
          description:
            Where/how consent was obtained (e.g. 'signup form', 'prior
            customer relationship'). Required (non-empty) when message_type is 'marketing'.
        consent_obtained_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Consent Obtained At
          description: When consent was obtained, if known.
        message_type:
          type: string
          enum:
            - marketing
            - informational
          title: Message Type
          description:
            "'marketing' additionally requires a non-empty consent_source.
            Use 'informational' for transactional/service communications."
          default: informational
        to:
          type: string
          title: To
          description: Recipient phone number, E.164 format (e.g. +14155551234).
        from:
          anyOf:
            - type: string
            - type: "null"
          title: From
          description:
            "Sender phone number, E.164 format. Must be a number owned
            by the organization with the SMS capability. Omitted: an active org-owned
            number is used if one exists, else a number is claimed from the shared
            pool."
        body:
          type: string
          maxLength: 1600
          minLength: 1
          title: Body
          description: Message text. Long bodies are split into multiple carrier segments.
        metadata:
          additionalProperties: true
          type: object
          title: Metadata
          description:
            Free-form JSON object attached to the message and echoed back
            on reads. Not interpreted by Hail.
      additionalProperties: false
      type: object
      required:
        - recipient_consent
        - to
        - body
      title: SmsCreate
    SmsListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/SmsResponse"
          type: array
          title: Items
          description: Messages in this page, newest first.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: SmsListResponse
    SmsResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this message.
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization that sent or received this message.
        from_e164:
          type: string
          title: From E164
          description: Sender phone number, E.164 format.
        to_e164:
          type: string
          title: To E164
          description: Recipient phone number, E.164 format.
        direction:
          type: string
          enum:
            - outbound
            - inbound
          title: Direction
          description:
            "'outbound' for messages Hail sent, 'inbound' for messages
            received."
        status:
          type: string
          enum:
            - queued
            - sent
            - delivered
            - failed
            - undelivered
            - received
          title: Status
          description:
            "Delivery status: 'queued', 'sent', 'delivered', 'failed',
            'undelivered', or 'received' (inbound messages)."
        body:
          type: string
          title: Body
          description: Message text.
        provider_message_sid:
          anyOf:
            - type: string
            - type: "null"
          title: Provider Message Sid
          description: The carrier/provider's identifier for this message, if assigned.
        segment_count:
          type: integer
          title: Segment Count
          description: Number of carrier SMS segments the body was split into.
        error_code:
          anyOf:
            - type: string
            - type: "null"
          title: Error Code
          description:
            Carrier error code if delivery failed. Null on success or while
            pending.
        requested_at:
          type: string
          format: date-time
          title: Requested At
          description: When the send was requested, ISO 8601 timestamp.
        sent_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Sent At
          description:
            When the message was handed to the carrier, ISO 8601 timestamp.
            Null until sent.
      type: object
      required:
        - id
        - organization_id
        - from_e164
        - to_e164
        - direction
        - status
        - body
        - provider_message_sid
        - segment_count
        - error_code
        - requested_at
        - sent_at
      title: SmsResponse
    SuppressionListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/SuppressionResponse"
          type: array
          title: Items
          description: Suppressed recipients in this page.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: SuppressionListResponse
    SuppressionResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this suppression entry.
        recipient:
          type: string
          title: Recipient
          description:
            "The suppressed recipient \u2014 E.164 phone number for voice/sms,\
            \ lowercased email address for email."
        channel:
          type: string
          title: Channel
          description: "Channel this entry blocks sends on: 'voice', 'email',
            'sms', or 'all' (every channel)."
        reason:
          type: string
          title: Reason
          description:
            Why the recipient was suppressed (e.g. an unsubscribe or a
            bounce).
        source:
          type: string
          title: Source
          description: "How this entry was created: 'unsubscribe_link', 'manual'
            (an operator action), or 'bounce'."
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When this entry was created, ISO 8601 timestamp.
      type: object
      required:
        - id
        - recipient
        - channel
        - reason
        - source
        - created_at
      title: SuppressionResponse
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
          description:
            Path to the invalid field within the request, as a list of
            keys/indices (e.g. ['body', 'to']).
        msg:
          type: string
          title: Message
          description: Human-readable description of the validation failure.
        type:
          type: string
          title: Error Type
          description: Machine-readable error type code (e.g. 'missing', 'string_type').
        input:
          title: Input
          description: The value that was actually provided and failed validation.
        ctx:
          type: object
          title: Context
          description:
            Additional machine-readable context for the error, when the
            error type provides one.
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    VoiceConfig:
      properties:
        tts:
          type: string
          const: cartesia
          title: Tts
          description: Text-to-speech provider. Currently only 'cartesia'.
          default: cartesia
        vad:
          type: string
          const: silero
          title: Vad
          description: Voice-activity-detection engine. Currently only 'silero'.
          default: silero
        turn_detection:
          type: string
          const: livekit
          title: Turn Detection
          description: Turn-detection engine. Currently only 'livekit'.
          default: livekit
        voice_id:
          anyOf:
            - type: string
            - type: "null"
          title: Voice Id
          description:
            "Per-call TTS voice override, applied to whichever TTS provider
            serves the call. Omitted: the organization's or environment's default
            voice."
        language:
          anyOf:
            - type: string
              enum:
                - ar
                - bg
                - bn
                - cs
                - da
                - de
                - el
                - en
                - es
                - fi
                - fr
                - gu
                - he
                - hi
                - hr
                - hu
                - id
                - it
                - ja
                - kn
                - ko
                - mr
                - ms
                - nl
                - "no"
                - pl
                - pt
                - ro
                - ru
                - sk
                - sv
                - ta
                - te
                - th
                - tl
                - tr
                - uk
                - vi
                - zh
            - type: "null"
          title: Language
          description:
            "Spoken language for the call as a lowercase ISO 639-1 code\
            \ (e.g. 'da'). One of the 39 supported codes \u2014 see docs/languages.md.\
            \ Applied to STT, TTS, and turn detection. Omitted: the providers' defaults\
            \ (English)."
      additionalProperties: false
      type: object
      title: VoiceConfig
    WebhookDeliveryListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/WebhookDeliveryResponse"
          type: array
          title: Items
          description: Delivery attempts in this page.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: WebhookDeliveryListResponse
    WebhookDeliveryResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this delivery attempt.
        subscription_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Subscription Id
          description: Subscription this delivery belongs to.
        email_domain_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: Email Domain Id
          description:
            "Email domain the triggering event relates to, if any. Informational\
            \ only (surfaced as the X-Hail-Email-Domain header) \u2014 not a routing\
            \ target."
        event_type:
          type: string
          title: Event Type
          description: The event type being delivered (e.g. 'call.completed').
        event_id:
          type: string
          format: uuid
          title: Event Id
          description: Identifier of the underlying event that triggered this delivery.
        attempt:
          type: integer
          title: Attempt
          description:
            Number of delivery attempts made so far for this event, starting
            at 0.
        status:
          type: string
          enum:
            - pending
            - succeeded
            - failed
            - dead
          title: Status
          description: "'pending' (queued/retrying), 'succeeded', 'failed' (will
            retry), or 'dead' (retries exhausted)."
        response_status:
          anyOf:
            - type: integer
            - type: "null"
          title: Response Status
          description:
            HTTP status code returned by the target URL on the last attempt.
            Null before any attempt.
        response_body:
          anyOf:
            - type: string
            - type: "null"
          title: Response Body
          description:
            Response body returned by the target URL on the last attempt,
            if any. Null before any attempt.
        next_attempt_at:
          type: string
          format: date-time
          title: Next Attempt At
          description: When the next delivery attempt is scheduled, ISO 8601 timestamp.
        succeeded_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Succeeded At
          description:
            When this delivery succeeded, ISO 8601 timestamp. Null until
            it does.
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When this delivery was queued, ISO 8601 timestamp.
      type: object
      required:
        - id
        - subscription_id
        - email_domain_id
        - event_type
        - event_id
        - attempt
        - status
        - next_attempt_at
        - created_at
      title: WebhookDeliveryResponse
    WebhookSubscriptionCreate:
      properties:
        target_url:
          type: string
          minLength: 1
          title: Target Url
          description: HTTPS URL Hail POSTs event payloads to.
        event_types:
          items:
            type: string
            enum:
              - email.received
              - email.delivered
              - email.delivery_delayed
              - email.bounced
              - email.complained
              - email.opened
              - email.clicked
              - email.received.suppressed
              - email.send_failed
              - sms.received
              - sms.delivered
              - sms.undelivered
              - sms.failed
              - call.answered
              - call.completed
              - call.failed
              - call.busy
              - call.no_answer
          type: array
          minItems: 1
          title: Event Types
          description:
            Event types to subscribe to (e.g. 'call.completed', 'email.bounced').
            At least one required.
      type: object
      required:
        - target_url
        - event_types
      title: WebhookSubscriptionCreate
    WebhookSubscriptionListResponse:
      properties:
        items:
          items:
            $ref: "#/components/schemas/WebhookSubscriptionResponse"
          type: array
          title: Items
          description: Subscriptions in this page.
        next_cursor:
          anyOf:
            - type: string
            - type: "null"
          title: Next Cursor
          description:
            Opaque cursor for the next page. Null when there are no more
            results.
      type: object
      required:
        - items
      title: WebhookSubscriptionListResponse
    WebhookSubscriptionPatch:
      properties:
        target_url:
          anyOf:
            - type: string
            - type: "null"
          title: Target Url
          description: New delivery URL. Omit to leave unchanged.
        event_types:
          anyOf:
            - items:
                type: string
                enum:
                  - email.received
                  - email.delivered
                  - email.delivery_delayed
                  - email.bounced
                  - email.complained
                  - email.opened
                  - email.clicked
                  - email.received.suppressed
                  - email.send_failed
                  - sms.received
                  - sms.delivered
                  - sms.undelivered
                  - sms.failed
                  - call.answered
                  - call.completed
                  - call.failed
                  - call.busy
                  - call.no_answer
              type: array
            - type: "null"
          title: Event Types
          description: New set of subscribed event types. Omit to leave unchanged.
        status:
          anyOf:
            - type: string
              enum:
                - active
                - disabled
            - type: "null"
          title: Status
          description:
            Set to 'disabled' to pause deliveries, or 'active' to resume.
            Omit to leave unchanged.
      type: object
      title: WebhookSubscriptionPatch
    WebhookSubscriptionResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: Unique identifier for this subscription.
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization that owns this subscription.
        target_url:
          type: string
          title: Target Url
          description: HTTPS URL event payloads are POSTed to.
        event_types:
          items:
            type: string
          type: array
          title: Event Types
          description: Event types this subscription receives.
        status:
          type: string
          enum:
            - active
            - disabled
          title: Status
          description: "'active' (delivering) or 'disabled' (paused)."
        consecutive_failures:
          type: integer
          title: Consecutive Failures
          description:
            Consecutive failed delivery attempts since the last success.
            Resets to 0 on success.
        last_success_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Last Success At
          description:
            When a delivery last succeeded, ISO 8601 timestamp. Null if
            never.
        last_failure_at:
          anyOf:
            - type: string
              format: date-time
            - type: "null"
          title: Last Failure At
          description: When a delivery last failed, ISO 8601 timestamp. Null if never.
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When this subscription was created, ISO 8601 timestamp.
        updated_at:
          type: string
          format: date-time
          title: Updated At
          description: When this subscription was last modified, ISO 8601 timestamp.
        secret:
          anyOf:
            - type: string
            - type: "null"
          title: Secret
          description:
            Plaintext signing secret for verifying delivery payloads. Only
            present in the create and rotate-secret responses; every later read returns
            null.
      type: object
      required:
        - id
        - organization_id
        - target_url
        - event_types
        - status
        - consecutive_failures
        - created_at
        - updated_at
      title: WebhookSubscriptionResponse
      description: "Subscription as returned by the API.


        ``secret`` is populated **only** by create + rotate-secret responses;

        later GETs return ``None`` so the plaintext never round-trips."
    WhoamiResponse:
      properties:
        auth_kind:
          type: string
          enum:
            - apikey
            - jwt
            - shared
          title: Auth Kind
          description:
            "How the caller authenticated: 'apikey' (org API key), 'jwt'
            (logged-in user session), or 'shared' (the shared HAIL_API_KEY, which
            carries no human identity)."
        organization_id:
          type: string
          format: uuid
          title: Organization Id
          description: Organization the caller belongs to.
        user_id:
          anyOf:
            - type: string
              format: uuid
            - type: "null"
          title: User Id
          description: The authenticated user's id. Null for 'shared' callers.
        email:
          anyOf:
            - type: string
            - type: "null"
          title: Email
          description: The authenticated user's email. Null for 'shared' callers.
        name:
          anyOf:
            - type: string
            - type: "null"
          title: Name
          description: The authenticated user's display name. Null for 'shared' callers.
      type: object
      required:
        - auth_kind
        - organization_id
      title: WhoamiResponse
      description:
        "Who the caller is \u2014 the answer ``GET /whoami`` gives.\n\n\
        ``user_id``/``email``/``name`` are ``None`` for shared-key\n(``HAIL_API_KEY``)\
        \ callers: that key carries no human identity. An\nagent that wants to put\
        \ the operator's address in ``Reply-To`` reads\n``email`` and skips the header\
        \ when it is ``None``."
