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

> ## Agent Instructions
> Every Lath operation is POST https://platform.trylath.com/<operation name with dots replaced by slashes>, with a JSON body and `Authorization: Bearer <key>`. `email.send` is POST /email/send.
> Branch on `error.code`, never on `error.message`. Every refusal also carries `error.fix`, which names the next step.
> Send an `Idempotency-Key` header on any operation that is not retry-safe, so a retry cannot run it twice.
> A `lath_test_` key emails only the account's own members and sends no SMS; a `lath_live_` key reaches real recipients and is billed.
> The OpenAPI document, generated from the same registry as the routes, is at https://platform.trylath.com/openapi.json.

# Send your first text

> One call, in the same shape as an email. The two things worth knowing before you send are what a message costs and why your first one is probably not going to arrive yet.

<Steps>
  <Step title="Send it">
    `sms.send` takes one recipient in E.164 — a leading `+` and the country code — and either a template with variables or an inline body.

    `topic` marks a marketing send, which consent governs. Omit it for transactional, which only a suppression stops.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://platform.trylath.com/sms/send \
        -H "Authorization: Bearer lath_live_..." \
        -H "Content-Type: application/json" \
        -d '{"to":"+14155550100","body":"It sent."}'
      ```

      ```ts TypeScript theme={null}
      import { createLath } from "@trylath/sdk";

      const lath = createLath({ key: process.env.LATH_API_KEY });

      const { result } = await lath.sms.send({ to: "+14155550100", body: "It sent." });
      ```

      ```bash CLI theme={null}
      lath sms send --to +14155550100 --body 'It sent.'
      ```
    </CodeGroup>
  </Step>

  <Step title="Your first one is probably blocked, and that is not an error">
    If the environment has no active carrier registration, or no number to send from, the message is **stored** and the reply carries `blocked` saying which. It is not a failure and it is not queued.

    So do not poll its status waiting for it to change — it cannot, until the registration clears. Read `blocked` on the reply and act on that instead. A send API that returned 200 and left you watching a status that will never move is the thing this is written to avoid.

    `sms.registration.*` is where a registration is filed and followed.
  </Step>

  <Step title="Billing counts segments, not messages">
    A text is billed per segment. A body that stays inside the GSM alphabet fits far more characters per segment than one that does not — a single emoji or curly quote switches the whole message to a different encoding and **more than doubles** the per-character cost.

    The reply says how many segments were counted, so the number is visible at send time rather than at the end of the month.
  </Step>

  <Step title="STOP is handled before you are called">
    A number that has replied STOP is recorded as suppressed rather than sent to — the audience policy is asked before the send, not after.

    STOP, HELP and START replies are answered by the carrier and by Lath, and the replies are configurable. You do not have to implement the keywords to be compliant, and you cannot accidentally text someone who opted out.
  </Step>
</Steps>
