Threadwire by TriTech

← API reference

Linking an instance

An instance is one WhatsApp number linked to Threadwire, the same way WhatsApp Web is linked to a phone. You can do all of this in your panel too; this page is for doing it through the API.

Add and link one

  1. Add it: POST /v1/instances with a name (and, if you like, your own external_ref). The answer has its id: that is the instance_id every other request uses.
  2. Show the QR code: GET /v1/instances/{id}/qr answers JSON with the picture as a data URL: {"data": {"image": "data:image/png;base64,iVBOR…"}}. Put data.image in an <img src> as it is. The phone's owner scans it in WhatsApp → Settings → Linked devices. The code changes, so fetch it again every few seconds. If the codes ran out before anyone scanned one, fetching it starts a fresh session.
  3. Wait for working: the instance's status becomes working in GET /v1/instances/{id}, and an instance.status webhook says so.

A code instead of a QR code: POST /v1/instances/{id}/pairing-code with the phone's number as phone. The person types the code in WhatsApp → Linked devices → Link a device → Link with phone number instead. At most 5 codes an hour per instance, counted together with your panel's "Link with a phone number instead" (then 429 with Retry-After).

What the answers mean while linking:

  • GET …/qr answers 409 while the instance is still starting (try again in a moment) and once it is linked.
  • POST /v1/instances answers 409 with Retry-After while another instance of yours is being added (they are added one at a time), and, rarely, 503 with Retry-After while we add room for more instances. Try again after the wait.

An instance's status is starting, scan_qr, working, failed or stopped.

One WhatsApp number, one instance. A number that belongs to another instance is not linked a second time: the new link is logged out again, and link_refused on the instance says why and what to do. To move a number, link it on the instance that has it, or remove that instance first. This keeps each number's daily limits and warm-up its own. While link_refused is set, GET …/qr and the pairing code answer 409 with the same reason; POST /v1/instances/{id}/logout clears it and starts a new link. In the panel, the link window shows the reason and "Start a new link", which brings the QR code back.

Keep it running

  • POST /v1/instances/{id}/restart reconnects one that seems stuck. It stays linked.
  • POST /v1/instances/{id}/stop takes it offline on purpose (stopped: true); sends answer 409 until you start it again.
  • POST /v1/instances/{id}/start brings it back.
  • POST /v1/instances/{id}/logout unlinks the phone, as removing a linked device in WhatsApp; the instance waits for a new QR code, from the same phone or another. Its id, settings, keys and messages stay; a new link starts warm-up again.
  • DELETE /v1/instances/{id} removes it for good.

To protect the instance, restart, stop and logout answer 409 while WhatsApp is restricting it, and the four together are limited to 5 an hour per instance (429 with Retry-After). DELETE answers 409 only while a linked instance is under WhatsApp's temporary restriction or in the hour after WhatsApp refused a message; the answer says when it can be removed. An instance that is unlinked, disconnected or stopped can always be removed.

Settings

PATCH /v1/instances/{id} changes its name, reject_calls and protection_settings (see How sending protects your number). Send only what changes.

GET /v1/instances/{id} also shows chat_link, a wa.me link that opens a chat with it, and protection: where the instance stands today with its limits and safety score.

Its WhatsApp profile

GET /v1/instances/{id}/profile gives its name and picture_url (WhatsApp does not give the "about" text back). PATCH changes name (up to 25 characters), about (up to 139) or picture (a JPEG or PNG of at most 2 MB, by url or base64 data; null removes it). "WhatsApp profile" on the instance's page in your panel does the same. At most 10 changes a day per instance.

People report numbers without a name and picture more often, so set them before writing to anyone new.

Calls

WhatsApp calls to your instances arrive as call.received webhooks. Set reject_calls: true (PATCH /v1/instances/{id}, or "Settings" on the instance's page) to decline every call at once, or decline one with POST /v1/instances/{id}/calls/reject and the call's id (as call_id) and chat_id (as from). One-to-one calls only.

API keys

Make keys in your panel under Developers → API keys (admins only), one per system that calls the API, so each can be revoked on its own.

  • Access: one of three.
    • Full access may do everything.
    • Send and read sends, and reads everything. That covers messages (edits, deletions, reactions and read marks too), broadcasts, OTPs, statuses, labels, number checks, declining a call, archiving a chat, and a group's name, settings and invite link. It may not manage an instance: add or remove one, link it (QR code or pairing code), change its settings, restart, stop, start or unlink it, or change its WhatsApp profile or AI agent. Nor may it create, join or leave a group, add or remove a group's people, or create or delete a channel.
    • Read only reads instances, messages, chats, events, groups, channels, statuses, labels, broadcasts and OTPs. It sends and changes nothing. One contact's details, and a group's invite link, need a key that may send.
  • One instance: a key can be made for one instance (from that instance's page, or "For" when you make a key). It reaches only that instance's messages, chats, groups, events and settings, as if your account had no others; it cannot add or remove instances (403), and it stops working when its instance is removed. Give that instance its own webhook URL too, and the system behind it gets only its events. Use one per system that serves a single instance, and an account key for systems that use them all.
  • IP addresses: a key can be locked to your servers' addresses or ranges, so a leaked key is useless anywhere else.

A call beyond a key's access, or from another address, answers 403 with the reason.

Plans and limits

Sign up at /app/register for a 7-day free trial; no card needed. Before it ends, pay by card on your Billing page where offered, or by transfer and press "I've paid" there; otherwise the account pauses the day after, until you do. Nothing is charged automatically.

  • Each account may make up to 600 requests a minute; past that, 429 Too Many Requests with Retry-After.
  • A plan sets how many instances you may link (past that, POST /v1/instances answers 403). It may also set usage limits: messages a day, people messaged a month, API requests a month, number checks a day. Your Billing page shows the ones your plan has; where it has none, only each instance's protection limits you. Messages typed on the phone never count. Past a usage limit, the API answers 429 with the reason and Retry-After.
  • If your account is suspended, every request answers 403 with the reason.