Skip to content

The whole contract, on one page.

Generated from the OpenAPI file the application itself honours, so this page cannot describe an API we do not have. Use your browser's find.

Base address
https://app.talkv.io/api/v1
Version
talkv API v1.0
Endpoints
15

A key from Settings → API, sent as Authorization: Bearer tvk_live_.... The file is at /openapi.yaml if you would rather generate a client than read this.

Reference

Workspace

GET /me

The workspace this key belongs to

Its WhatsApp numbers and, if it is charged, its balance. A quick way to check a key works.

Returns Workspace Statuses 200 · 401 · 403

Messages

POST /messages

Send one message

A template (anyone, any time) or a free-form text (only inside the 24-hour window after the person last wrote). Handed to WhatsApp while the request is open, so the answer says whether it went.

A marketing template records the person's consent with the source api. Somebody who opted out is never sent anything — the answer is opted_out, with the date.

Parameters

Idempotency-Key header
Up to 100 characters. The same key and body within 24 hours returns the first answer instead of acting twice.

Body · SendTemplate · required

to string required
template string required
language string
Needed only when the template exists in more than one language.
variables Variables
The template's {{1}}, {{2}}… in order. A list fills the body; an object fills header and body separately. In a broadcast, a value may also be a contact field with a fallback.
media Media
The photo, video or PDF at the top of a template that has one — an invoice, a ticket, an offer's banner. WhatsApp fetches the link when it sends, so it has to open without signing in; a signed link that lasts an hour is enough. talkv does not keep the file or the link. Left out, the sample the template was written with in talkv is sent, if it has one (media.default on the template).
from string
Which of the workspace's numbers. Needed only when it has more than one.

Body · SendText · required

to string required
text string required
from string
Example · template json
{
  "to": "+91 98250 12345",
  "template": "order_shipped",
  "variables": [
    "Ravi",
    "#4521"
  ]
}
Example · headerAndBody json
{
  "to": "9825012345",
  "template": "festival_sale",
  "language": "hi",
  "variables": {
    "header": [
      "Diwali"
    ],
    "body": [
      "Ravi"
    ]
  }
}
Example · withPdf json
{
  "to": "9825012345",
  "template": "invoice_ready",
  "variables": [
    "Ravi",
    "INV-1042"
  ],
  "media": {
    "link": "https://shop.example/invoices/INV-1042.pdf",
    "filename": "INV-1042.pdf"
  }
}
Example · text json
{
  "to": "+919825012345",
  "text": "We will call you at 4."
}

Returns Message Statuses 201 · 400 · 401 · 402 · 403 · 409 · 422 · 429 · 502

GET /messages/{id}

One message sent through the API, as it stands now

Parameters

id path required

Returns Message Statuses 200 · 404

Broadcasts

GET /broadcasts

Broadcasts, newest first

Parameters

page query

Returns Broadcast Statuses 200

POST /broadcasts

Send one template to many people

To a list of numbers (to) or to a group kept in talkv (group). The answer comes back before anything is sent and already lists who will be left out from to and why; the rest is decided as the broadcast is built, and appears in /broadcasts/{id}/recipients.

Numbers in to are recorded as having consented (source api) unless they opted out. People in a group keep the consent they have in talkv, and anybody without a recorded opt-in is skipped.

Parameters

Idempotency-Key header
Up to 100 characters. The same key and body within 24 hours returns the first answer instead of acting twice.

Body · CreateBroadcast · required

name string required
template string required
language string
variables Variables
The template's {{1}}, {{2}}… in order. A list fills the body; an object fills header and body separately. In a broadcast, a value may also be a contact field with a fallback.
media Media
The photo, video or PDF at the top of a template that has one — an invoice, a ticket, an offer's banner. WhatsApp fetches the link when it sends, so it has to open without signing in; a signed link that lasts an hour is enough. talkv does not keep the file or the link. Left out, the sample the template was written with in talkv is sent, if it has one (media.default on the template).
to array
Numbers to send to. Give this or group.
group integer
A group's id from /groups. Give this or to.
from string
send_at date-time
Schedule it. Nothing is blocked from the balance until it runs.

Statuses 202 · 400 · 402 · 403 · 409 · 422

GET /broadcasts/{id}

One broadcast and its figures

Parameters

id path required

Returns Broadcast Statuses 200 · 404

GET /broadcasts/{id}/recipients

Who a broadcast went to, and what happened

Kept for 18 months after the broadcast finishes; the figures on the broadcast are kept for good.

Parameters

id path required
status query
page query

Returns Recipient Statuses 200 · 404

POST /broadcasts/{id}/cancel

Stop a broadcast

Nothing more is sent. Messages already sent are not recalled, and only the delivered ones are charged.

Parameters

id path required

Returns Broadcast Statuses 200 · 404 · 422

Contacts

GET /contacts

Contacts, most recently changed first

Parameters

updated_since query
Only contacts changed at or after this time
page query

Returns Contact Statuses 200

GET /contacts/{phone}

One contact

Returns Contact Statuses 200 · 404

PUT /contacts/{phone}

Create or update a contact

Only the fields you send are changed. consent: opted_in is refused with opted_out for somebody who opted out — only they can undo that.

Body · ContactInput · required

name string
first_name string
last_name string
email string
city string
state string
postal_code string
company string
birthday string
1990-09-20, or --09-20 without a year. 20/09/1990 is read day first.
anniversary string
fields object
Your own fields by key, as set up in talkv. An unknown key is refused.
people PersonOnNumber[]
Everybody else who uses this number — a family on one phone. The whole list: anybody left out is removed. A broadcast chosen by birthday greets whoever's day it is; any other reaches the number once.
add_tags array
Created if they do not exist.
remove_tags array
add_to_groups array
Group ids or names. A new name creates the group.
remove_from_groups array
consent string
opted_in · opted_out

Returns Contact Statuses 200 · 201 · 400 · 422

POST /contacts/{phone}/opt-out

Record that this person must not be messaged

For an unsubscribe that reached your system rather than WhatsApp. Permanent unless the person writes START.

Returns Contact Statuses 200

GET /opt-outs

Everybody who opted out, for syncing

Parameters

since query
Only opt-outs at or after this time
page query

Statuses 200

Templates

GET /templates

Templates and whether they can be sent

Parameters

status query
page query

Returns Template Statuses 200

Groups

GET /groups

Groups kept in talkv

Parameters

page query

Statuses 200

Objects

What the endpoints above hand back. Every success is {"data": …}; a list adds meta. Times are ISO 8601 in the workspace's timezone, and phone numbers always come back as E.164.

Workspace

id integer
name string
country string
Numbers without a country code are read in this country.
timezone string
numbers array
billing object
Null when talkv does not charge this workspace.

Message

id integer
to string
from string
type string
template · text
template object
text string
What the person sees, with the variables filled in.
status string
sent · delivered · read · failed
error object
charged boolean
Whether this message is charged once delivered. Templates are; replies are not.
created_at date-time
sent_at date-time
delivered_at date-time
read_at date-time

Broadcast

id integer
name string
status string
scheduled · queueing · running · paused · completed · cancelled · failed
status_reason stringnull
Why it paused or failed, in words.
template object
from string
counts object
charged stringnull
What it cost, once settled. Null while running or when the workspace is not charged.
send_at date-time
started_at date-time
completed_at date-time
created_at date-time

Recipient

to string
status string
pending · queued · sending · sent · delivered · read · failed · skipped
reason stringnull
For skipped and failed, in words.
sent_at date-time
delivered_at date-time
read_at date-time

Contact

phone string
name stringnull
first_name stringnull
last_name stringnull
email stringnull
city stringnull
state stringnull
postal_code stringnull
company stringnull
birthday stringnull
ISO 8601; --09-20 when the year is not known.
anniversary stringnull
fields object
Your own fields, by key.
people PersonOnNumber[]
Everybody else who uses this number, each with their own birthday.
tags array
groups array
consent object
last_message_from_them_at date-time
Opens the 24-hour window.
created_at date-time
updated_at date-time

Template

name string
language string
category string
MARKETING · UTILITY · AUTHENTICATION
status string
APPROVED · PENDING · REJECTED · PAUSED · DISABLED
sendable boolean
variables object
text string
The body, with {{1}} placeholders.
media object

Event

id string required
type string required
message.sent · message.delivered · message.read · message.failed · message.received · contact.opted_out · contact.opted_in · broadcast.finished · template.approved · template.rejected · webhook.test
created_at date-time required
data object required
message.* → {message: Message}; message.received → {message: {id, from, type, text, received_at}, contact: Contact}; contact.* → {contact: Contact}; broadcast.finished → {broadcast: Broadcast}; template.* → {template: Template, reason}.

Errors

Every refusal has the same shape and the message is a sentence you can put in front of a person — "this person asked not to be messaged on 3 October", not error 131050. Branch on code, never on the words.

invalid_request HTTP 400
A field is missing or wrong; fields says which
unauthenticated HTTP 401
No key, or a key that was revoked or never existed
insufficient_balance HTTP 402
The balance does not cover it; top up in Billing
api_not_enabled HTTP 403
The API is not switched on for this workspace
workspace_suspended HTTP 403
Sending is stopped; message says why
not_found HTTP 404
No such message, broadcast, contact, template or group
idempotency_conflict HTTP 409
That Idempotency-Key was used with a different body
opted_out HTTP 422
The person opted out; since says when
invalid_number HTTP 422
Not a phone number, or not on WhatsApp
window_closed HTTP 422
A free-form reply outside the 24-hour window; send a template
template_not_found HTTP 422
No approved template by that name (and language)
template_not_sendable HTTP 422
The template is pending, rejected or paused; message says which
missing_variable HTTP 422
The template needs more values than were given
missing_media HTTP 422
The template has a photo, video or PDF at the top; send it as media
unsupported_template HTTP 422
The template has a map location at the top, which talkv cannot send yet
number_not_ready HTTP 422
The WhatsApp number cannot send yet; see Setup in talkv
not_cancellable HTTP 422
The broadcast has already finished, so there is nothing to stop
rate_limited HTTP 429
Too many requests; wait Retry-After seconds
whatsapp_error HTTP 502
WhatsApp refused it; message is its reason in plain words

Next: the events talkv sends back to you.

Webhooks