HCC Docs

Texts

Send a Text

POST /v1/texts texts:write

We carry Texts on your own carrier account, and consent, registration, content and hours are yours: see the Texts guide. We refuse a number on Do Not Call or with texts revoked, and not one with no grant. A refused attempt still has its row, named by error.details.textId. A 201 means we asked the carrier: status says how that went, and unknown is never sent again automatically. Use an Idempotency-Key: a retry without one sends another Text.

Headers

  • Idempotency-Key string

    Makes the request safe to retry. For 24h, a request with the same key and body replays the stored response (with Idempotent-Replayed: true); the same key with a different request is a 422 idempotency_key_reused, and while the first request is still running a 409 idempotency_key_in_use. Server errors, 409s and 429s are not stored, except one that says Hcc-Should-Retry: false, such as 504 call_outcome_unknown.

Body

  • to string required
  • body string required
  • from string

    One of your numbers. Without one, the workspace's caller ID default

Responses

  • 201

    The carrier was asked

    Fields
    • data Text required

      One SMS, inbound or outbound, including a refused attempt: the audit row of that attempt.

      Fields
      • id string required
      • threadId string | null required
      • direction "inbound" | "outbound" required
      • source "desk" | "api" | "campaign" | "flow" | null required

        Who started it. An inbound Text has none

      • decision string required

        sent, received, or the refusal that stopped it (do_not_call, …)

      • status "pending" | "unknown" | "accepted" | "sent" | "delivered" | "undelivered" | "failed" | "refused" | "received" required
      • from string | null required
      • to string required
      • body string | null required

        Null once retention has cleared it

      • segments integer required

        An estimate of the carrier's message count

      • keyword "stop" | "start" | "help" | null required
      • possibleOptOut boolean required

        Free text that may be an opt-out. Nothing was revoked: deciding is your duty, by code or a person

      • leadId string | null required

        Only when one Lead is on the number

      • consentId string | null required

        The texts grant on file when this went, if any

      • timezone string | null required

        The Lead's time zone, if known

      • failureReason "recipient_blocked" | "invalid_recipient" | "sender_not_registered" | "filtered" | "unreachable" | "rejected" | "unknown" | null required
      • errorCode string | null required

        The carrier's own code

      • createdAt string required
      • sentAt string | null required
      • deliveredAt string | null required
      • failedAt string | null required
      • receivedAt string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 402

    A billing stop: outbound only. Inbound and STOP keep working

  • 404

    Not found

  • 409

    idempotency_key_in_use: a request with this key is still running

  • 422

    do_not_call, opted_out, caller_id_not_owned, no_caller_id, messaging_unavailable or number_not_registered, or an Idempotency-Key reused with a different request

  • 429

    rate_limited, or another limit named by error.code

Get one Text, with its body

GET /v1/texts/{id} texts:read

Path

  • id string required

Responses

  • 200

    The Text

    Fields
    • data Text required

      One SMS, inbound or outbound, including a refused attempt: the audit row of that attempt.

      Fields
      • id string required
      • threadId string | null required
      • direction "inbound" | "outbound" required
      • source "desk" | "api" | "campaign" | "flow" | null required

        Who started it. An inbound Text has none

      • decision string required

        sent, received, or the refusal that stopped it (do_not_call, …)

      • status "pending" | "unknown" | "accepted" | "sent" | "delivered" | "undelivered" | "failed" | "refused" | "received" required
      • from string | null required
      • to string required
      • body string | null required

        Null once retention has cleared it

      • segments integer required

        An estimate of the carrier's message count

      • keyword "stop" | "start" | "help" | null required
      • possibleOptOut boolean required

        Free text that may be an opt-out. Nothing was revoked: deciding is your duty, by code or a person

      • leadId string | null required

        Only when one Lead is on the number

      • consentId string | null required

        The texts grant on file when this went, if any

      • timezone string | null required

        The Lead's time zone, if known

      • failureReason "recipient_blocked" | "invalid_recipient" | "sender_not_registered" | "filtered" | "unreachable" | "rejected" | "unknown" | null required
      • errorCode string | null required

        The carrier's own code

      • createdAt string required
      • sentAt string | null required
      • deliveredAt string | null required
      • failedAt string | null required
      • receivedAt string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

List Threads, the latest first

GET /v1/text-threads texts:read

Query

  • phone string

    The Threads of one number

  • channel "sms" | "email"

    The Threads of one Channel. Without it, all

  • limit integer
  • cursor string

Responses

  • 200

    A page of Threads

    Fields
    • data TextThread[] required
      Fields
      • id string required
      • channel "sms" | "email" required

        Where the conversation happens. Only sms today

      • contactAddress string required

        The other party: their E.164 number, for SMS

      • ourAddress string required

        Our end: your number, for SMS

      • phone string | null required

        Their number, on a Channel with phones

      • ourNumber string | null required

        Your number, on a Channel with phones

      • leadId string | null required
      • ownerRepId string | null required
      • status "open" | "closed" required
      • possibleOptOutAt string | null required

        The last time a Text here read like an opt-out. Nothing acts on it but you

      • lastTextAt string required
      • createdAt string required
    • nextCursor string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

List Text flows

GET /v1/text-flows flows:read

Responses

  • 200

    The Text flows deployed

    Fields
    • data TextFlow[] required
      Fields
      • id string required
      • name string required
      • version string required
      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Register Text flows

PUT /v1/text-flows flows:write

What hcc deploy sends (mode: "deploy"). A Text flow is its name and version; the logic is in your code. Inbound Texts reach one bound to their number with PATCH /v1/numbers/{id}. hcc.serve sends mode: "report" on startup, which deploys nothing: it sets the flow endpoint and answers with what is deployed. A deploy never removes a flow, or unbinds a number.

Body

  • flows object[] required
    Fields
    • name string required
    • version string required
    • hosting "hcc" | "self"
  • mode "report" | "deploy"

    Default "report".

  • endpointUrl string
  • uploadId string

    From POST /v1/hosting/uploads: the hosted code that serves this deploy's definitions with hosting: 'hcc'. Required when there are any. The first PUT that carries it makes it the running hosted code.

  • testUploadId string

    With alsoTest: the upload's test.id, which runs the test copy's hosting: 'hcc' definitions.

  • alsoTest boolean

    Default false.

Responses

  • 200

    The registered Text flows

    Fields
    • data TextFlow[] required
      Fields
      • id string required
      • name string required
      • version string required
      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code