import { PeriskopeApi } from '@periskope/periskope-client';
const client = new PeriskopeApi({
authToken: 'YOUR_API_KEY',
phone: '919876543210', // the phone to act with (x-phone)
});
async function main() {
const response = await client.messages.sendMessageSync({
chat_id: '911111111111@c.us',
});
console.log(response);
}
main();curl -X POST 'https://api.periskope.app/v1/message/send-sync' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'x-phone: 919876543210' \
-H 'Content-Type: application/json' \
-d '{
"chat_id": "911111111111@c.us"
}'{
"status": "sent",
"unique_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"message": {
"message_id": "true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"unique_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"org_id": "00000000-0000-0000-0000-000000000000",
"org_phone": "911111111111@c.us",
"chat_id": "120363000000000000@g.us",
"body": "Hello World",
"message_type": "chat",
"timestamp": "2026-01-15T09:30:00+00:00",
"from_me": true,
"ack": "3",
"performed_by": "api",
"sender_phone": "911111111111@c.us",
"quoted_message_id": null,
"broadcast_id": null,
"is_deleted": null,
"media": {
"path": "https://example.com/files/image.png",
"mimetype": "image/png",
"filename": "image.png",
"size": 24576,
"dimensions": {
"width": null,
"height": null,
"ar": null
},
"thumbnail": null
},
"mentioned_ids": [],
"prev_body": null,
"sent_message_id": "00000000-0000-0000-0000-000000000000",
"delivery_info": {
"delivered": {
"911111111111@c.us": 1737967705196
},
"read": {
"911111111111@c.us": 1737967704763
},
"pending": [],
"delivered_count": 1,
"read_count": 1
},
"poll_info": {},
"poll_results": {},
"flag_status": null,
"updated_at": "2026-01-15T09:35:38.221+00:00",
"reactions": [
{
"reaction_id": "true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAA",
"message_id": "true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"unique_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"chat_id": "911111111111@c.us",
"org_id": "00000000-0000-0000-0000-000000000000",
"org_phone": "911111111111@c.us",
"sender_id": "911111111111@c.us",
"reaction": "😄",
"read": true,
"timestamp": "2026-01-15T09:31:57.008+00:00"
}
]
}
}{
"code": "ERROR",
"message": "The phone is off or its server is unreachable",
"status": 400
}{
"code": "UNAUTHORIZED_ERROR",
"message": "Invalid bearer auth token",
"status": 401
}{
"code": "NOT_FOUND_ERROR",
"message": "x-phone omitted and the group chat was not found on any phone of the org",
"status": 404
}{
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"status": 422,
"fields": {
"body.chat_id": {
"message": "chat_id is required"
}
}
}{
"code": "RATE_LIMIT_ERROR",
"message": "You can only make 100 requests per second",
"status": 429
}{
"code": "UNKNOWN_ERROR",
"message": "Internal server error",
"status": 500
}Send Sync Message
Sends a message like POST /message/send (including automatic phone selection for group chats when x-phone is omitted), then waits up to sync_timeout seconds (default 20) for the send confirmation. When confirmed in time the response carries the sent message record; otherwise it falls back to the asynchronous queued response.
import { PeriskopeApi } from '@periskope/periskope-client';
const client = new PeriskopeApi({
authToken: 'YOUR_API_KEY',
phone: '919876543210', // the phone to act with (x-phone)
});
async function main() {
const response = await client.messages.sendMessageSync({
chat_id: '911111111111@c.us',
});
console.log(response);
}
main();curl -X POST 'https://api.periskope.app/v1/message/send-sync' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'x-phone: 919876543210' \
-H 'Content-Type: application/json' \
-d '{
"chat_id": "911111111111@c.us"
}'{
"status": "sent",
"unique_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"message": {
"message_id": "true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"unique_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"org_id": "00000000-0000-0000-0000-000000000000",
"org_phone": "911111111111@c.us",
"chat_id": "120363000000000000@g.us",
"body": "Hello World",
"message_type": "chat",
"timestamp": "2026-01-15T09:30:00+00:00",
"from_me": true,
"ack": "3",
"performed_by": "api",
"sender_phone": "911111111111@c.us",
"quoted_message_id": null,
"broadcast_id": null,
"is_deleted": null,
"media": {
"path": "https://example.com/files/image.png",
"mimetype": "image/png",
"filename": "image.png",
"size": 24576,
"dimensions": {
"width": null,
"height": null,
"ar": null
},
"thumbnail": null
},
"mentioned_ids": [],
"prev_body": null,
"sent_message_id": "00000000-0000-0000-0000-000000000000",
"delivery_info": {
"delivered": {
"911111111111@c.us": 1737967705196
},
"read": {
"911111111111@c.us": 1737967704763
},
"pending": [],
"delivered_count": 1,
"read_count": 1
},
"poll_info": {},
"poll_results": {},
"flag_status": null,
"updated_at": "2026-01-15T09:35:38.221+00:00",
"reactions": [
{
"reaction_id": "true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAA",
"message_id": "true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"unique_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"chat_id": "911111111111@c.us",
"org_id": "00000000-0000-0000-0000-000000000000",
"org_phone": "911111111111@c.us",
"sender_id": "911111111111@c.us",
"reaction": "😄",
"read": true,
"timestamp": "2026-01-15T09:31:57.008+00:00"
}
]
}
}{
"code": "ERROR",
"message": "The phone is off or its server is unreachable",
"status": 400
}{
"code": "UNAUTHORIZED_ERROR",
"message": "Invalid bearer auth token",
"status": 401
}{
"code": "NOT_FOUND_ERROR",
"message": "x-phone omitted and the group chat was not found on any phone of the org",
"status": 404
}{
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"status": 422,
"fields": {
"body.chat_id": {
"message": "chat_id is required"
}
}
}{
"code": "RATE_LIMIT_ERROR",
"message": "You can only make 100 requests per second",
"status": 429
}{
"code": "UNKNOWN_ERROR",
"message": "Internal server error",
"status": 500
}Authorizations
Your Periskope API token, sent as Authorization: Bearer <token>. Generate one from the Periskope dashboard under Settings → API & Webhooks. API access requires an active Pro or Enterprise plan.
Headers
Phone to send from: country code + number without symbols or spaces (e.g. 911111111111), or a phone_id (phone-xxxxxxxxxxxx). Required for 1-1 chats. For group chats it can be omitted — a connected phone that is in the group is selected automatically, within the token's phone scopes.
"919876543210"
Body
Chat to send the message to. For group chats, the chat_id ending with @g.us; for 1-1 chats, country code + number of the contact, optionally suffixed with @c.us (e.g. 911111111111 or 911111111111@c.us).
1"911111111111@c.us"
The text body of the message, or the caption when media is provided. Supports the basic WhatsApp markdown formatting (bold, italic, strikethrough, monospace).
"Hello World"
Media to send — a document, image, video, audio file or voice note. Provide either a public url or base64 filedata. The message text, when given, becomes the caption.
Show child attributes
Show child attributes
Poll to send instead of a plain message. The resulting message has message_type poll_creation.
Show child attributes
Show child attributes
message_id of an existing message in the chat to reply to. The sent message quotes it.
"true_911111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
Additional sending options
Show child attributes
Show child attributes
How long to wait for the send confirmation, in seconds (1-60). When the message is not confirmed within this window the response falls back to the asynchronous shape. Defaults to 20.
1 <= x <= 6020
Response
The sent message when confirmed within sync_timeout, otherwise the queued response
- Option 1
- Option 2
The sent message when confirmed within sync_timeout, otherwise the asynchronous queued response
The message was confirmed sent within the wait window
sent Provisional id assigned when the message was queued
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
A WhatsApp message record. Responses may include additional raw fields of the underlying record (id, author, links, location, vcards, is_forwarded, has_media, message_ticket_id, ...).
Show child attributes
Show child attributes
Was this page helpful?