Skip to main content
POST
/
api
/
events
/
webhook
/
:instance
Set Webhook
curl --request POST \
  --url https://api.example.com/api/events/webhook/:instance \
  --header 'Content-Type: <content-type>' \
  --header 'token: <token>' \
  --data '
{
  "label": "<string>",
  "enabled": true,
  "url": "<string>",
  "authorization": {},
  "byEvents": true,
  "events": [
    "<string>"
  ],
  "mediaBase64": true
}
'

Documentation Index

Fetch the complete documentation index at: https://docs.ryzeapi.cloud/llms.txt

Use this file to discover all available pages before exploring further.

Auth: TokenAccount or TokenInstanceRate limit: Global (100/min) • Idempotent: yes (upsert by label)

Description

Creates or updates the (instance, label) row in webhook_configs. Each instance accepts up to 3 simultaneously enabled webhooks, identified by a free-form label. Webhooks with enabled=false are kept in the database but do not count toward the limit and do not receive deliveries. Use cases:
  • Create a new webhook: send a label not used yet.
  • Update existing: send the same label, all new fields overwrite the old ones.
  • Soft-disable: send the same label with {"enabled": false} (clears url, authorization, events, mediaBase64, but preserves the row).
  • Parallel migration: run the old webhook while validating the new one under a different label; once confirmed, disable the old one.

Examples

Minimum

Enables the default webhook pointing to https://meuapp.com/webhook. Without events, it receives the 6 types; without authorization, it sends no auth header.
curl -X POST "https://ryzeapi.cloud/api/events/webhook/$Instance_Name" \
  -H "token: $Token_Instance" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "url":     "https://meuapp.com/webhook"
  }'

With label, filter and Authorization

Creates a webhook named analytics-pipeline that only receives message.exchange and message.status, sends the header Authorization: Bearer svc-token-xyz on each delivery, and turns off the base64 backup.
curl -X POST "https://ryzeapi.cloud/api/events/webhook/$Instance_Name" \
  -H "token: $Token_Instance" \
  -H "Content-Type: application/json" \
  -d '{
    "label":         "analytics-pipeline",
    "enabled":       true,
    "url":           "https://analytics.meuapp.com/events",
    "authorization": "Bearer svc-token-xyz",
    "events":        ["message.exchange", "message.status"],
    "mediaBase64":   false
  }'

byEvents = true (URL-based routing)

Turns on byEvents: true so each delivery is sent with the event name as a URL suffix (e.g., https://meuapp.com/wh/message.exchange), allowing server-side routing per endpoint without inspecting the payload.
curl -X POST "https://ryzeapi.cloud/api/events/webhook/$Instance_Name" \
  -H "token: $Token_Instance" \
  -H "Content-Type: application/json" \
  -d '{
    "label":    "router",
    "enabled":  true,
    "url":      "https://meuapp.com/wh",
    "byEvents": true,
    "events":   []
  }'
# Deliveries go to https://meuapp.com/wh/message.exchange, /group.flow, ...

Soft-disable preserving the label

Disables the analytics-pipeline webhook by sending only enabled: false. The row stays in the database but url, authorization, events and mediaBase64 are cleared, and the entry no longer counts toward the limit of 3 active webhooks.
curl -X POST "https://ryzeapi.cloud/api/events/webhook/$Instance_Name" \
  -H "token: $Token_Instance" \
  -H "Content-Type: application/json" \
  -d '{
    "label":   "analytics-pipeline",
    "enabled": false
  }'

Base64 media (raw backup)

Configures a webhook dedicated to backup that only receives message.exchange with mediaBase64: true, so each message with media includes the binary content base64-encoded inside the payload.
curl -X POST "https://ryzeapi.cloud/api/events/webhook/$Instance_Name" \
  -H "token: $Token_Instance" \
  -H "Content-Type: application/json" \
  -d '{
    "label":       "backup-raw",
    "enabled":     true,
    "url":         "https://backup.meuapp.com/raw",
    "events":      ["message.exchange"],
    "mediaBase64": true
  }'

Success response

The response returns the webhook object with the configuration actually persisted (label, enabled, url, authorization, byEvents, events, mediaBase64), mirrors the request body after the upsert. When enabled=false, the url, authorization, events and mediaBase64 fields come back cleared. The dispatcher starts using the new config immediately (the internal 30s cache is invalidated on save).
200 OK
{
  "success": true,
  "message": "Webhook configured successfully",
  "webhook": {
    "label":         "default",
    "enabled":       true,
    "url":           "https://meuapp.com/webhook",
    "authorization": "Bearer secret-key-123",
    "byEvents":      false,
    "events":        ["message.exchange", "call.update"],
    "mediaBase64":   true
  }
}

Path parameters

instance
string
required
Instance name (e.g., $Instance_Name).

Headers

token
string
required
TokenAccount or TokenInstance.
Content-Type
string
required
application/json

Request body

label
string
default:"default"
Local identifier. Max 50 chars; accepts [a-zA-Z0-9_-]. Empty or omitted becomes "default". Allows multiple webhooks per instance.
enabled
boolean
required
Turns the webhook on/off. When false, the url, authorization, byEvents, events and mediaBase64 fields are cleared before saving.
url
string
Destination URL. Required when enabled=true. Goes through the SSRF guard (see below), blocks localhost, private IPs, link-local, multicast.
authorization
string | null
default:"null"
Literal content of the Authorization header sent on each delivery (e.g., Bearer secret-key-123). Encrypted at rest with AES-256-GCM when ENCRYPTION_KEY is configured.
byEvents
boolean
default:"false"
If true, the URL receives the /<event-name> suffix on each delivery, useful for endpoint-based routing without inspecting the payload (https://app/wh/message.exchange).
events
string[]
default:"[]"
Filter. Empty array = receive all 6 types. Each entry must be in {message.exchange, message.status, call.update, group.flow, instance.state, label.update}.
mediaBase64
boolean
default:"false"
When true, message.exchange events with media include media.base64 (increases payload, may exceed 100KB).

SSRF guard

The url is validated at configuration time and before each delivery. It blocks destinations that point to internal infrastructure:
RangeExample
Loopbacklocalhost, 127.0.0.1, ::1
Private IPv410.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
Link-local IPv4169.254.0.0/16
Link-local IPv6fe80::/10
Multicast / broadcast224.0.0.0/4, 255.255.255.255
If you need to test against a local server in development, expose it through a public tunnel (ngrok, cloudflared, localhost.run), the SSRF guard is active in every environment.

Notes

  • Empty authorization vs. null: send null or omit it to skip the header. An empty string "" would result in an empty Authorization: header, which some proxies reject.
  • enabled=false clears the fields: re-enabling the same label later requires re-sending the url (and any other fields you want to preserve).
  • There is no DELETE: to “remove” a webhook, POST with {"enabled": false} keeping the label. Operators can inspect/clean the row directly in the database when needed.
  • Optional encryption: if ENCRYPTION_KEY is not configured, authorization is stored in plain text. In production, always configure the key.
  • Cache invalidated: the new config becomes visible to the dispatcher immediately (the internal 30s TTL is invalidated on save).

Errors

HTTPerror.message
400Invalid request body
400URL is required when enabled is true
400URL must not target localhost or private network
400invalid event type: <value>
400label too long (max 50 chars)
400label may only contain letters, digits, underscore or dash
401Invalid token
404Instance not found
409webhook limit reached (max 3 enabled per instance)
429Rate limit exceeded. Try again later.
500Failed to get instance
Envelope:
{
  "success": false,
  "error": { "message": "URL must not target localhost or private network" }
}
The 3-webhook limit check is only enforced when creating a new row with enabled=true. Editing an existing row (same label) never triggers the limit.

Next

List webhooks

GET /api/events/getWebhook/:instance, all or by ?label=.

Event catalog

What each event carries in data.