Skip to main content

Formats

Timestamps​

Always RFC 3339, always UTC, on the way out:

"startTime": "2026-08-11T13:20:01Z"

There is no local-time variant and no epoch variant. If you need to show a user their own wall-clock time, GET /users returns each user's IANA timeZone (America/New_York) — convert client-side.

Phone numbers​

On inputFormatting is stripped. "(212) 555-0188", "212-555-0188" and "12125550188" are the same number.
On outputDigits, 11-digit form for US numbers: "12125550188". No +, no punctuation.

Two consequences worth knowing:

Copy output straight into input. number from GET /sms/lines is exactly what POST /sms/messages wants as from. No reformatting step.

Normalized values come back in the response. A send to "(347) 555-0123" returns "13475550123" in messages[].to — what was actually dialled and what the charge is against. The one exception is skipped[].to, which echoes your input, because a skipped recipient may not have normalized at all and you need to match it back to what you sent.

Extensions vs numbers​

Both appear as strings and they are not interchangeable:

  • "204" — an internal extension.
  • "12125550188" — an external number.

On a recording's from/to, an internal leg carries extensions, not phone numbers. Do not assume every value is dialable from outside.

Ids​

IdTypeExample
User idinteger481920
Webhook idinteger2074
SMS message idinteger88214417
Call idstring"1754489201.884213"
Recording leg id (uniqueId)string"1754489201.884213"

A call id is a unix timestamp, a dot, and a sequence number. Keep it a string — parsing it as a float loses precision and silently corrupts the id. Malformed call ids get a 400 naming the expected shape, not a 404.

Money​

{"currency": "USD", "unitPrice": 0.0025, "price": 0.0025, "totalPrice": 0.0025}

Prices are JSON numbers in whole dollars — 0.0025 is a quarter of a cent, not 25 of anything. currency is always USD today and is stated on every response so you never have to assume.

:::caution Do not sum these as floats A per-segment SMS price has four decimal places, and accumulating thousands of them in a float drifts. Convert to a decimal type on arrival, or work in ten-thousandths of a dollar as integers. :::

price = unitPrice × units, always. See SMS billing for what a unit is.

Booleans mean what they say​

No 0/1, no "true" strings. true and false.

The one to watch is billing.billed, which is always true — it describes the endpoint (this costs money), not the individual call. It stays true even when a particular request cost nothing because everything was skipped.