Skip to main content

GET /sms/conversations/{line}/{number}

Read a conversation's messages

Scopemessages:read
Role permissionPhone numbers — line must be one of theirs
CostFree

Reading does NOT mark anything read. markRead defaults to false, which differs from the portal, where opening a thread clears it. An integration polling for new messages would otherwise silently empty the unread badges your staff work from, with nothing to explain it. Pass markRead=true when a person has actually seen the messages.

Media URLs in the response are publicly readable — the URL is the only thing protecting the file. Treat them as secrets and do not log them.

Path parameters

NameTypeRequiredExampleDescription
linestringyes12125550188One of your account's numbers — the line the thread is on. Digits.
numberstringyes13475550123The other party's number. Digits.

Query parameters

NameTypeRequiredExampleDescription
markReadbooleannoAlso mark the returned messages read for you. Default false.
groupParticipantsstringnoComma-separated participants, to address a group thread rather than a 1:1.
limitintegernoPage size. An out-of-range value is a 400 rather than a silent clamp — a client asking for 5000 and receiving 200 with no explanation concludes the account only has 200 messages.
offsetintegerno

Responses

200

The conversation's messages.

FieldTypeDescription
linestring
numberstring
messagesobject[]
messages[].idinteger
messages[].directionin | outin = they texted you, out = you texted them. Spelled this way rather than the carrier's MO/MT, which reads backwards to everyone the first time.
messages[].fromstring
messages[].tostring
messages[].textstringThe body. Empty is legal and normal for an MMS that carries only an image.
messages[].mediastring[]Attachment URLs. Publicly readable — the URL is the only thing protecting the file. Treat them as secrets and do not log them.
messages[].sentAtstring (RFC 3339)
messages[].readbooleanWhether YOU have read it.
messages[].readByinteger[]Every user who has read it, matching id in GET /users.
messages[].sentByintegerThe user who sent it. Absent when an integration sent it rather than a person.
messages[].deliveryobjectThe carrier's receipt. Absent means the carrier has not reported yet — normal for a message sent seconds ago, and permanent for an inbound one. Absent is NOT "failed"; a client that treats it that way shows a false failure on every fresh send.
messages[].delivery.statusstringThe carrier's own word for the outcome, passed through unmapped so the detail that makes a failure diagnosable survives.
messages[].delivery.errorstringThe carrier's failure detail. Empty on success.
messages[].delivery.atstring (RFC 3339)
messages[].groupParticipantsstring[]
messages[].scheduledbooleanQueued for future delivery — in the thread, but not sent yet.
messages[].scheduledAtstring (RFC 3339)
messages[].blockedbooleanNot delivered because the other party is on this line's blocked-sender list. The message exists and was charged for.
messages[].blockReasonstring
markedReadbooleanWhether this request also marked the messages read. Only ever true when you passed markRead=true.

Errors

StatusMeaning
400invalid_request — a missing or malformed field, an unknown enum value, or an unknown field in the body. Nothing was charged.
401unauthenticated — no credential, or one that is invalid, revoked or expired. The WWW-Authenticate header names the scope the endpoint wanted.
403Two different failures share this status, and the type tells them apart:
500internal_error — something failed on our side. For a send, nothing was charged, guaranteed, which is what makes a retry safe.

See Errors for the full catalog and what to do about each.

Example

curl -X GET 'https://api.account.telebroad.com/api/public/v1/sms/conversations/12125550188/13475550123' \
-H "Authorization: Bearer $TB_KEY"

Try it in the playground →