Skip to main content
This page takes you from an API key to a message that you sent and tracked. You need an iSnap account (sign up) and one line whose status is active. A new account has no line, and GET /v1/lines/my returns an empty lines: see Getting a line.
iSnap has no test environment. Every send on this page is a real message to a real recipient, from a real line of your account. An isnap_test_ account key sends too: see Test keys. Send to a phone number of your own.

Create an API key

Create an API key in the iSnap dashboard. The dashboard shows the full key once: store it in a secret manager. The samples of every page read it from the environment variable ISNAP_API_KEY.
Set the variable yourself. Never paste a key into a prompt for an AI agent: start the agent in an environment that already holds the variable. The key is isnap_live_ or isnap_test_ followed by 64 hexadecimal characters. Authentication describes the keys and every refusal.

Make a first call

GET /v1/version needs no key. It tells you that you reach the API.
The response contains the version of the API, for example:
The result of a call is in data: see Conventions. Keep trace_id and request_id when you report a problem. Then list your lines with your key. The TypeScript samples use the SDK (npm install @isnap/sdk), which needs Node.js 20 or later and is ESM only: see the SDK overview. The Python samples use requests (pip install requests).
GET /v1/lines/my returns your lines whose status is active or reserved. Note the id of a line whose status is active: only an active line sends. If inbound_only is true, the line can message a contact only after that contact wrote to it: see Line kinds.

Send a message

POST /v1/messages sends one message to one phone number from one line. Replace the line id with yours, and to with a phone number of your own.
The API returns 202 with the message. A 202 means that iSnap accepted the message, never that it was sent. These are the fields to read first, out of the whole message object:
Send Content-Type: application/json with every body. The Idempotency-Key header makes a retry safe: a second request with the same key and the same body sends nothing and, while the line is active, returns the same message, for as long as iSnap keeps that message, at least 72 hours. Generate one key per message, and reuse it only to retry that message. See Idempotency. The responses to a first send: Sending messages describes the whole request and every refusal.

Read its status

Read the message by its id. status moves from queued to sent when the line’s device reports that it sent the message, then to delivered and read when the device reports them. service then says what the device used: iMessage, SMS or RCS.
Three rules to know before you build on status:
  • iSnap learns “delivered” and “read” only from the line’s device. With no report, a message stays sent.
  • A message stays queued while it waits for the line’s device.
  • iSnap deletes a message at least 72 hours after it recorded it. Once deleted, GET /v1/messages/{id} returns 404 not_found.
Message statuses lists every status, what sets it, and which ones are final. A message carries personal data: the handles in to and from, and the text in body. Request it only when needed. Do not copy it into logs, tickets or other tools. Refer to a contact by an id of your own.

Receive its events

Reading a message repeatedly uses your request-rate limit. Let iSnap call you: create a webhook subscription with the URL of your endpoint and the event types you want. The response contains the signing secret: run the command where its output is not logged, and store the secret in your secret manager.
The response contains the signing secret of the subscription, once. Do not send this request twice: POST /v1/webhooks does not honor Idempotency-Key, and a second request creates a second subscription that receives every event too. If the response does not arrive, list your subscriptions with GET /v1/webhooks and look for your URL before you create one again. If the subscription exists, call POST /v1/webhooks/{id}/rotate-secret to get a signing secret: no other call returns the secret of the first response. For the message you sent, iSnap sends these events to your endpoint: Each event carries the whole message in data.message. Before you rely on events:
  • Verify the signature of every delivery: see Verifying signatures.
  • Deduplicate on event_id. See Duplicates.
  • Delivery order is not guaranteed. Order events by the timestamps inside data, not by arrival. See Order.
  • Events do not announce every change, and an event can be missed: see What events do not announce. Reconcile from GET /v1/messages/{id} and GET /v1/messages.
Webhooks overview says what your endpoint must do.

Next steps

Core concepts

The terms every page uses: lines, line kinds, statuses, services, identifiers.

Sending messages

The whole send request, the statuses over time, failures and cancellation.

Sending limits

Why a message is held, and when it leaves.

Receiving messages

Inbound messages, chats, and messages typed on the line’s device.