import { PeriskopeApi } from '@periskope/periskope-client';
const client = new PeriskopeApi({
authToken: 'YOUR_API_KEY',
});
async function main() {
const response = await client.webhooks.createWebhook({
hookUrl: 'https://example.com/webhooks/periskope',
integrationName: [
'ticket.created',
'message.created',
],
});
console.log(response);
}
main();curl -X POST 'https://api.periskope.app/v1/webhooks' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"hookUrl": "https://example.com/webhooks/periskope",
"integrationName": [
"ticket.created",
"message.created"
]
}'[
{
"id": "00000000-0000-0000-0000-000000000000",
"org_id": "00000000-0000-0000-0000-000000000000",
"hook_url": "https://example.com/webhooks/periskope",
"integration_name": "ticket.created",
"integration_type": "webhook",
"type": "webhook",
"is_subscribed": true,
"integration_id": "00000000-0000-0000-0000-000000000000",
"integration_metadata": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "Ticket webhook"
},
"phone_scopes": [
"911111111111"
],
"subscribed_at": "2026-01-15T09:30:00.000Z"
}
]{
"code": "UNAUTHORIZED_ERROR",
"message": "Invalid bearer auth token",
"status": 401
}{
"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
}Create Webhook
Subscribes an endpoint URL to one or more event types — one subscription row per event type, sharing an integration_id.
import { PeriskopeApi } from '@periskope/periskope-client';
const client = new PeriskopeApi({
authToken: 'YOUR_API_KEY',
});
async function main() {
const response = await client.webhooks.createWebhook({
hookUrl: 'https://example.com/webhooks/periskope',
integrationName: [
'ticket.created',
'message.created',
],
});
console.log(response);
}
main();curl -X POST 'https://api.periskope.app/v1/webhooks' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"hookUrl": "https://example.com/webhooks/periskope",
"integrationName": [
"ticket.created",
"message.created"
]
}'[
{
"id": "00000000-0000-0000-0000-000000000000",
"org_id": "00000000-0000-0000-0000-000000000000",
"hook_url": "https://example.com/webhooks/periskope",
"integration_name": "ticket.created",
"integration_type": "webhook",
"type": "webhook",
"is_subscribed": true,
"integration_id": "00000000-0000-0000-0000-000000000000",
"integration_metadata": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "Ticket webhook"
},
"phone_scopes": [
"911111111111"
],
"subscribed_at": "2026-01-15T09:30:00.000Z"
}
]{
"code": "UNAUTHORIZED_ERROR",
"message": "Invalid bearer auth token",
"status": 401
}{
"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.
Body
HTTP or HTTPS endpoint that will receive the subscribed events as JSON POST requests. Each delivery is signed with an HMAC-SHA256 signature of the body computed with the workspace signing key.
"https://example.com/webhooks/periskope"
Event type(s) to subscribe the endpoint to — a single event type or an array. One subscription row is created per event type; the rows share the same hookUrl and integration_id. Deliverable event types: chat.created, chat.notification.created, message.created, message.updated, message.deleted, message.ack.updated, message.flagged, message.unflagged, reaction.created, ticket.created, ticket.updated, ticket.deleted, org.phone.connected, org.phone.disconnected, org.phone.updated, org.phone.qr, note.created, chat.custom_properties.updated. The legacy names org.created, org.updated, org.member.created, org.member.updated, org.subscription.trial_will_end, org.integrations.updated, org.phone.created, chat.updated, chat.label.updated, reaction.updated, reaction.added, message.ticket.attached are also accepted for compatibility, but events are never delivered for them.
chat.created, chat.notification.created, message.created, message.updated, message.deleted, message.ack.updated, message.flagged, message.unflagged, reaction.created, ticket.created, ticket.updated, ticket.deleted, org.phone.connected, org.phone.disconnected, org.phone.updated, org.phone.qr, note.created, chat.custom_properties.updated, org.created, org.updated, org.member.created, org.member.updated, org.subscription.trial_will_end, org.integrations.updated, org.phone.created, chat.updated, chat.label.updated, reaction.updated, reaction.added, message.ticket.attached ["ticket.created", "message.created"]
Arbitrary JSON object stored with the subscription. Two keys are special: id (a non-empty string becomes the integration_id shared by the created rows; otherwise a UUID is generated) and name (used as the display name unless the name field is passed).
{ "name": "Ticket webhook", "description": "Webhook for ticket creation events" }
Label stored as integration_type on the created rows. Defaults to 'webhook' — leave it unset unless an integration guide instructs otherwise.
"webhook"
Kind of integration record to create. Defaults to 'webhook'. Any other value makes the subscription invisible to this API — GET, PATCH and DELETE /webhooks/{id} and the list endpoint only address records of type 'webhook'.
zapier, pabbly, api, webhook, hubspot, freshdesk, slack, jira, salesforce, zohodesk, gsheets, zohocrm "webhook"
Display name of the webhook, stored as integration_metadata.name on every created row. Defaults to integrationMetadata.name, or to hookUrl when neither is given.
"Ticket webhook"
Response
The created subscription rows — one per event type in integrationName
Unique id of the webhook subscription (UUID). Use it as the id path parameter when fetching, updating or deleting the subscription.
"00000000-0000-0000-0000-000000000000"
Id of the workspace (org) the webhook belongs to
"00000000-0000-0000-0000-000000000000"
HTTP(S) endpoint that receives the subscribed events as JSON POST requests, signed with an HMAC-SHA256 signature of the body computed with the workspace signing key
"https://example.com/webhooks/periskope"
The event type this subscription row delivers. One row exists per subscribed event type. Deliverable event types: chat.created, chat.notification.created, message.created, message.updated, message.deleted, message.ack.updated, message.flagged, message.unflagged, reaction.created, ticket.created, ticket.updated, ticket.deleted, org.phone.connected, org.phone.disconnected, org.phone.updated, org.phone.qr, note.created, chat.custom_properties.updated. The legacy names org.created, org.updated, org.member.created, org.member.updated, org.subscription.trial_will_end, org.integrations.updated, org.phone.created, chat.updated, chat.label.updated, reaction.updated, reaction.added, message.ticket.attached are also accepted for compatibility, but events are never delivered for them.
chat.created, chat.notification.created, message.created, message.updated, message.deleted, message.ack.updated, message.flagged, message.unflagged, reaction.created, ticket.created, ticket.updated, ticket.deleted, org.phone.connected, org.phone.disconnected, org.phone.updated, org.phone.qr, note.created, chat.custom_properties.updated, org.created, org.updated, org.member.created, org.member.updated, org.subscription.trial_will_end, org.integrations.updated, org.phone.created, chat.updated, chat.label.updated, reaction.updated, reaction.added, message.ticket.attached "ticket.created"
Label of the integration that created the subscription. Webhooks created via this API default to 'webhook'.
"webhook"
Kind of integration record. This API only lists, fetches, updates and deletes records of type 'webhook' — other values belong to built-in integrations (Zapier, Slack, ...) managed from the dashboard.
zapier, pabbly, api, webhook, hubspot, freshdesk, slack, jira, salesforce, zohodesk, gsheets, zohocrm "webhook"
Whether event delivery is active. false pauses delivery without deleting the subscription — set it via PATCH isSubscribed, or automatically by Periskope when the endpoint keeps failing (workspace admins are emailed when that happens).
true
Groups the subscription rows created together: every row created by the same POST /webhooks call shares this id (taken from integrationMetadata.id when provided, otherwise generated). null on some legacy rows.
"00000000-0000-0000-0000-000000000000"
Metadata stored with the subscription. Webhooks created via this API always carry id (mirrors integration_id) and name (display name); any other keys sent in integrationMetadata are stored as-is.
Show child attributes
Show child attributes
{ "id": "00000000-0000-0000-0000-000000000000", "name": "Ticket webhook" }
Phone numbers whose events this webhook receives. Webhooks created via this API are unscoped (they receive events from every phone in the workspace); for unscoped rows this field is materialized in responses as the workspace's current full list of phone numbers.
["911111111111"]
When the subscription was created, as an ISO 8601 timestamp. Re-creating the same event type + hookUrl pair refreshes it.
"2026-01-15T09:30:00.000Z"
Was this page helpful?