Changelog
Only changes that affect your integration are listed here. Those that need action on your side say what to change.
October 2026: failure and storage notices, connect answers
- The
errorofnumber.connect.failedis a fixed sentence: for eachreasonthe field always carries the same English sentence, in place of the free text the field used to carry, which changed from one release to the next. Decide byreasonand useerroronly in your logs. The sentences are listed in Webhooks. The text forpairing_timeoutchanged again. storage.degradedhas closed lists:reasonis alwayshealthcheck_failedanderror_codeis one ofaccess_denied,bucket_unreachable,region_mismatch,endpoint_unreachable,endpoint_url_blocked,network_error,quota_exceeded,object_not_found,provider_unavailableorunknown_error. Each value has what it means and what to do in Webhooks. Treat anerror_codeyou do not know asunknown_error.- Connecting and disconnecting answer
202withalias,statusandat, on all four routes:POST /v1/numbers/{ref}/connectand/disconnectanswered200with an emptyat, and the main number routes answered202without the field. All four now return202 Acceptedwithalias,status(connectingordisconnecting) andat, the moment the request was accepted. If you checked for200on the extra number routes, accept202. The number’s current status and its ownatstay inGET /v1/numbers/{ref}. See Connecting extra numbers.
October 2026: scheduled removal
- Removing does not require disconnecting:
DELETE /v1/numbers/{ref}accepts a connected number and no longer answers400 invalid_status_for_deletion. When the removal is scheduled, the number stays connected and keeps working, with its usualstatus, until the date. See Remove. - The date is the end of the period already paid:
scheduled_deletion_atis now the end of the subscription period (or the moment of the request, when there is no paid period), not a 30-day cycle of the number. pending_deletionis no longer a status, breaking:statusshows only the real connection state, and?status=pending_deletiononGET /v1/numbersanswers422. If you tested that value, readscheduled_deletion_at, which now comes on every item ofGET /v1/numbers(nullon the main number and on extras with no removal) and in thePATCHresponse. See Status.- Connecting and disconnecting never charge or touch the removal:
POST /v1/numbers/{ref}/connectno longer cancels a scheduled removal or charges the activation, andno_payment_method,payment_declined,payment_requires_authenticationandpayment_gateway_unavailableleft its error table.POST /v1/numbers/{ref}/cancel-deletionis what keeps the number, and it only charges what remains of the paid period when the invoice of the next period was already issued without the number. cancel-deletionreturns the real state: the response carriesstatus(the connection state) andat(can benull), in place ofpending_deletion_canceled.- MCP server: no tool creates a charge.
connect_numberis no longer the exception (reconnecting a number with a scheduled deletion used to cancel the deletion and could charge) anddisconnect_numberstill never charges. Cancelling a removal stays outside the catalog. See MCP server.
October 2026: pairing with a QR code
- Pair an extra number with a QR code, through the API:
POST /v1/numbers/{ref}/pairnow acceptsmethod: "qr", besides"pairing_code"(the default, when the body is left out). Any other value answers422. In the launch note,"qr"answered422: that has changed. The dashboard already offered both methods. See Pairing with the API and Pairing in the dashboard. pairing.methodcan beqr: inGET /v1/numbers/{ref}, withmethod: "qr",pairing.datais the QR code image as a PNG data URI (data:image/png;base64,...), to use as thesrcof an<img>, never as text. If your screen only handled codes, checkpairing.methodbefore showingpairing.data.- The QR code renews: WhatsApp replaces the QR code on its own and Turbo Notify keeps
pairing.datacurrent. Read again and replace the image on every read. For both methods,pairing.expires_atis when the whole attempt stops being usable. - Replacing the attempt:
POST /v1/numbers/{ref}/pairwhile the number ispairingreplaces the attempt in progress, including one started in the dashboard, and can switch the method. - Neutral timeout text: the
data.errorofnumber.connect.failedwithreason: "pairing_timeout"no longer says “Pairing code expired”. It now says pairing was not completed in time, for the code and for the QR code. The reasonspairing_timeout,code_generation_failedandpaired_phone_mismatchapply to both methods. See Status.
October 2026: editing captions
- Edit the caption of an image, video or document:
POST /v1/numbers/{ref}/messages/{id}/editnow acceptscaption(1 to 1,024 characters, with the same@<number>mentions as a send). The file stays as it was and the recipient sees the new caption marked as edited. The outcome arrives asmessage.edited(with thecontent_typeof the file and the new caption inpreview) ormessage.edit.failed. See Edit a caption. - What can be changed after sending: text, the caption of an image, video or document, and calendar events can be edited. A location, contact card, link button, sticker or audio message cannot: deleting it is the only change. A body that does not fit the message answers
400 message_not_editableand a text or caption edited more than 15 minutes after sending answers400 edit_window_expired. See What can be changed after sending. - Time limit for editing a text or a caption: WhatsApp gives 15 minutes after sending to change a text or a caption. After that the API answers
400 edit_window_expiredinstead of accepting an edit the recipient may never see. The 15 minutes do not apply to a calendar event, although WhatsApp may still refuse an event edit. - Fixed: a caption edited in the WhatsApp app reached the webhook as
message.editedwith an emptypreview. It now carries the new caption and thecontent_typeof the file. - MCP server, breaking: the
edit_messagetool is removed. Four tools replace it, one per action:edit_text_message,edit_media_caption,edit_calendar_eventandcancel_calendar_event. Each takes only the fields of its own type. The server now has 36 tools. Agents that callededit_messagemust call the tool for their type. See MCP server.
October 2026: calendar events
- Edit and cancel a sent event:
POST /v1/numbers/{ref}/messages/{id}/editnow accepts, besidestext, a calendar event body (name,start_atand the other send fields) and thecanceledfield. The edit replaces the whole event. The outcome arrives asmessage.edited(withcontent_type: "calendar"andcanceled: truewhen canceled) ormessage.edit.failed. Before, editing an event answered400 message_not_editable. See Edit and delete. - Events edited in the WhatsApp app: when the creator of an event edits or cancels it in the app, you receive
message.editedwithorigin: "native". - Guest answers: the new
message.calendar_respondedevent carries the answer (going,not_goingormaybe) and, when there are any, the number of extra guests. See Calendar events. - Read the answers:
GET /v1/numbers/{ref}/messages/{message_id}/responsesreturns the latest answer of each guest and the totals. See Get event responses. - New codes:
message_not_calendar(reading answers on a message that is not an event) andmessage_secret_unavailable(edit failure on an event the number can no longer change). When the platform cannot change or cancel events at the moment,message.edit.failedcarriescalendar_edit_unavailable: send a new event. See Error codes.
October 2026: launch
- WhatsApp API: sending text, media, location, contact, calendar event and link button; replies, reactions, editing and deleting; delivery and read receipts; contacts and groups per number. See the Quickstart.
- Events by signed webhook or by polling, in the same format.
- MCP server with 36 tools for AI agents, which you reach by signing in with your account or with a key. On the hosted address, a call with neither a sign-in nor a key now receives
401with the invitation to sign in (it used to receive200with an error inside the tool), and a value that is neither a sign-in nor a key also receives401. See Build an AI agent. - Resale: extra numbers, the
statusfilter on the number list and the Resale key template. Every number has a fixedid(num_…) that works in place of the alias on any/v1/numbers/...route, comes on events asnumber_id(and asdata.idonnumber.*events) and filters event queries with?number_id=. See Resell to your customers. - Message list filters:
GET /v1/numbers/{ref}/messagesacceptsgroup_id,contact_idanddirection, and each item carries the same envelope as the message’s event (includingnumber_id). See List messages. - Calendar: an event sent as
calendarnow shows up on the recipient’s WhatsApp, in a chat and in a group. Before, the message was delivered but did not appear on the phone. - Interactive API reference, error code index and Insomnia collection.
- Authentication errors: a missing, malformed, unknown, revoked or expired key answers
401 not_authenticated, with theWWW-Authenticate: Bearerheader;403is for a valid key without permission (insufficient_scope). Before launch these cases answered403 not_authorized: if your test integration handled that code, switch it to the401. See the error code index. - Quota warnings:
message.quota.warningandcontact.quota.warningcarry the threshold reached indata.threshold_percent(80,90or95, in percent). Before launch the field was calledthreshold_bps, with the same values: if your test integration read that name, switch tothreshold_percent. See Message quota events. - New extra number and pairing (adjust if your test integration used the old names): the body of
POST /v1/numberstakes the phone asphone_number(the namephoneis no longer accepted and answers422), and the body ofPOST /v1/numbers/{ref}/paironly acceptsmethod: "pairing_code"("qr"used to answer with no effect and now answers422). See Add numbers and Pairing with the API. - Failures of supporting services: when the API cannot reach a service it depends on, the answer is
503 service_unavailable; when an outside service answers with an error (for example, the payment processor when you add an extra number), the answer is502 integration_error. Before, some cases returned internal codes that are not part of the contract. See the error code index. - MCP server: opening a streaming connection without a sign-in or a key answers
401 not_authenticated, withWWW-Authenticate: Bearer, as the API does (the code used to beunauthorized). See MCP server. - Audio transcription: when the transcription provider configured for your account is not supported,
data.transcription.reasonisprovider_not_supported(before launch it wasno_adapter). The otherreasonvalues are unchanged. See Get a message. - Documentation in Portuguese and English.