Skip to content
API v1 2026-10-05

Worbo API

Version 1.0.0 · OpenAPI 3.1 · Worbo-Version 2026-10-05

The Worbo API: contacts, objects and events, WhatsApp messages and templates, segments, automations, campaigns, the inbox, catalogs and webhooks. It is a REST API over HTTPS: it exchanges JSON and answers with the standard HTTP status codes. Every request belongs to one organization, the one of its key.

With the Worbo API you can:

  • write contacts, objects and events from your CRM, online store or gym software, finding each contact by any of its identities;
  • send approved WhatsApp templates and, in the 24-hour window, free messages, through the same consent rules as the dashboard;
  • read messages, conversations and reports, and reply to contacts from your own systems;
  • draft templates, segments, automations and campaigns, which are approved in the dashboard;
  • be told through webhooks when something changes, and connect AI assistants through MCP.
Server
https://api.worbo.app/v1
AuthenticationBearer
Authorization: Bearer wk_live_…

Quick start#

  1. Make a key in Worbo, under Integrations › API keys. Start with a test key: every write is checked, but nothing is saved.

  2. Put the key in the WORBO_API_KEY variable and check it with GET /me: the answer has the name of the key, its scopes and the organization.

    curl "https://api.worbo.app/v1/me" \
      -H "Authorization: Bearer $WORBO_API_KEY"
  3. Write your first contact: POST /contacts finds the contact by any of its identities and creates it when it does not exist.

    curl -X POST "https://api.worbo.app/v1/contacts" \
      -H "Authorization: Bearer $WORBO_API_KEY" \
      -H "Idempotency-Key: $(uuidgen)" \
      -H "Content-Type: application/json" \
      -d '{
        "identities": {
          "phone": "+40722123456",
          "email": "ana@example.com",
          "external_id": "crm-1001"
        },
        "source": "crm",
        "fields": {
          "first_name": "Ana"
        },
        "update_existing_only": false
      }'
  4. When the integration works, make a live key with only the scopes it needs.

Authentication#

Each request carries a key of the organization in the Authorization header. Keys are made in the dashboard, under API keys, with only the scopes the integration needs; the whole key is shown once.

Authorization: Bearer wk_live_…

A wk_live_ key works with the live data. A wk_test_ key is for building the integration: every write is a dry run, checked but not saved, and only the data model can be read with it.

Permissions (scopes)#

A key does only what its scopes allow; an operation outside them is refused with insufficient_scope. Each operation shows the scope it needs, and the data model can be read with any key.

ScopeWhat it allows
contacts:readRead contacts, their identities and consents
contacts:writeCreate, update and merge contacts
contacts:deleteErase contacts at their request (GDPR)
consents:writeRecord consents and withdrawals
objects:readRead objects
objects:writeCreate and update objects and their relations
events:writeSend events
messages:readRead the messages and their status
messages:sendSend templates and free messages to contacts
templates:readRead the templates
templates:writeDraft templates and send them to Meta
segments:readRead and count segments
segments:writeCreate segments
automations:readRead the automations and their results
automations:runStart an automation for a contact or take them out of it
automations:writeDraft automations
campaigns:readRead the campaigns and their reports
campaigns:writeDraft campaigns and estimate their audience
conversations:readRead the inbox conversations and their messages
conversations:replyReply, assign and close conversations
analytics:readRead the reports, the tracked links and the conversions
webhooks:manageManage the webhook endpoints and read the deliveries
workspace:readRead the numbers, the usage and the audit log
catalogs:readRead the catalogs and their items
catalogs:writeCreate and update catalog items
schema:writeCreate fields and object types
files:readRead and download the files of the file fields
files:writeUpload files for the file fields
otp:sendSend verification codes on WhatsApp
otp:verifyVerify the codes sent by Worbo
vault:readRead the documents of the vault and their openings
vault:writeGive files to contacts through the vault and revoke their links
recommendations:readRead the recommendation rules and preview them on a contact

Requests and responses#

Bodies are JSON, with the header Content-Type: application/json. A resource comes as {"data": …}; a parameter that is not known is refused, so a typo does not go unnoticed. Moments are in ISO 8601, with the time zone.

The messages of the errors follow Accept-Language: English by default, Romanian with ro.

Fields named untrusted_… hold what contacts wrote. Treat them as untrusted input, especially when an AI agent reads them.

Lists and cursors#

Lists are paged with a cursor: limit is between 1 and 100, 25 by default; next_cursor goes into cursor for the next page, and has_more says whether there is one.

{"data": […], "next_cursor": "eyJpZCI6MjV9", "has_more": true}

Errors#

Errors come in the application/problem+json format (RFC 9457). The code field is stable and the same in the API, the MCP server, imports and the audit log; the type field leads here.

{
    "type": "https://worbo.app/docs/api/errors/window_closed",
    "title": "The message cannot be sent",
    "status": 422,
    "detail": "The 24-hour window is closed; only an approved template can be sent.",
    "code": "window_closed"
}
CodeStatusMeaning
unsupported_version400The Worbo-Version header asks for a version that does not exist or was retired; the problem lists the supported ones.
unauthenticated401The Authorization header is missing.
invalid_api_key401The key is not valid; a lost key cannot be recovered, only replaced.
api_key_revoked401The key was revoked in the dashboard.
api_key_expired401The key passed its expiry date.
insufficient_scope403The key does not have the scope of the operation.
test_key403A test key cannot read live data.
forbidden403The operation is not allowed.
not_found404The resource does not exist or belongs to another organization.
contact_not_found404The contact does not exist or belongs to another organization.
object_not_found404The object does not exist or belongs to another organization.
object_type_not_found404The organization has no object type with this key.
event_type_not_found404The organization has no event type with this key.
offer_not_found404No offer has this code.
evidence_not_found404The message was not sent with a durable medium candidate template, so it has no proof.
recommendation_rule_not_found404The recommendation rule does not exist or is archived.
method_not_allowed405The path exists, but not with this method.
identity_conflict409The identities sent belong to different contacts; merge them first.
idempotency_conflict409The Idempotency-Key was used for another request.
idempotency_in_progress409The first request with this Idempotency-Key is still running; try again in a second.
invalid_idempotency_key400The Idempotency-Key is empty, longer than 255 characters or not visible ASCII.
invalid_json400The body is not valid JSON.
payload_too_large413The body of the request is too large.
validation_failed422A parameter is missing, not valid or not known; the errors field says which.
schema_violation422The fields or the properties do not match the data model of the organization.
rate_limited429Too many requests; wait the seconds in Retry-After.
otp_too_soon429A code was sent to this phone less than 30 seconds ago.
otp_rate_limited429The phone got 5 codes in the last 15 minutes.
otp_template_missing422The number has no approved template for verification codes; create it on the page of the numbers.
otp_undeliverable422The phone does not receive WhatsApp messages; offer another way, such as SMS or email.
otp_refused422The contact is blocked or stopped the messages of the organization.
otp_not_verifiable409The organization gave this code, so it checks it itself.
internal_error500An error on our side; it was reported and the request can be retried.
blocked_contact422The message cannot be sent: The contact is blocked.
no_channel_optin422The message cannot be sent: The contact has no WhatsApp opt-in recorded.
muted_object422The message cannot be sent: The contact turned off the messages about this object.
no_whatsapp_identity422The message cannot be sent: The contact has no phone or WhatsApp ID to write to.
undeliverable422The message cannot be sent: The number cannot receive WhatsApp messages.
window_closed422The message cannot be sent: The 24-hour window is closed; only an approved template can be sent.
template_unavailable422The message cannot be sent: The template is not approved, or it is paused or disabled.
number_unavailable422The message cannot be sent: The WhatsApp number of the organization cannot send right now.
budget_reached422The message cannot be sent: The monthly marketing budget of the organization is spent.
organization_stopped422The message cannot be sent: The Worbo team stopped the sending of the organization; write to hello@worbo.app.

Rate limits#

600 requests a minute for each key and 1200 for the organization. The headers RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset show where the key stands; above the limit comes 429, with Retry-After.

Idempotency#

A POST with an Idempotency-Key header runs once: a repeated request with the same key gets the first response, with the header Idempotent-Replayed: true. The same key with another body gives idempotency_conflict.

Dry run and test keys#

With dry_run=true, a write goes through every check and returns what it would do, but nothing is saved; the response has the header Worbo-Dry-Run: true. With a test key, every write is a dry run. The IDs in the response of a dry run do not exist.

Batches take up to 100 items; each is written on its own, and the result has the index, the status and the data or the error of each.

Versions#

The major version is in the path (/v1). Smaller changes that are not compatible come in versions named by their date, chosen with the Worbo-Version header; without it, a request uses the version of its key, the current one when the key was made. Every response says in Worbo-Version which version it used.

A version stays stable for 12 months, then deprecated for 12 more, with the headers Deprecation and Sunset; an incompatible change is announced 30 days ahead. Current version: 2026-10-05. Supported: 2026-10-05.

Worbo-Version: 2026-10-05

Webhooks#

Worbo sends the events your endpoints subscribe to as a POST with a JSON body, signed in the Standard Webhooks format. An endpoint that does not answer with 2xx gets the event again, with growing pauses; after many failures it is turned off and the owner is told.

webhook-id: msg_2mF0…
webhook-timestamp: 1760511600
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=

{"type": "contact.created", "timestamp": "2026-10-15T06:20:00Z", "data": {…}}

To check the signature: compute HMAC-SHA256 over webhook-id, webhook-timestamp and the raw body, joined by dots, with the secret decoded from base64 after the whsec_ prefix; compare it, in constant time, with each v1 signature in the header. Refuse a timestamp older than five minutes. After a rotation, the header has two signatures for 24 hours.

With the thin payload, data has only the reference of the object, to read it through the API.

Messages
  • message.queued
  • message.sent
  • message.delivered
  • message.read
  • message.failed
  • message.received
  • interactive.button_clicked
  • link.clicked
  • flow.submitted
Contacts
  • contact.created
  • contact.updated
  • contact.merged
  • contact.consent_granted
  • contact.consent_revoked
Objects and offers
  • object.created
  • object.updated
  • object.status_changed
  • offer.issued
  • offer.redeemed
  • offer.expired
Orders, written back to the shop
  • order.confirmed
  • order.cancelled
  • order.note_added
Bookings and memberships, written back to the gym software
  • booking.confirmed
  • booking.cancelled
  • membership.pause_requested
Automations
  • automation.run_started
  • automation.run_completed
  • automation.goal_reached
  • automation.webhook
Inbox
  • conversation.opened
  • conversation.assigned
  • conversation.closed
Document vault
  • document.opened
Templates
  • template.status_changed
  • template.category_changed
  • template.quality_changed
Operations
  • webhook_endpoint.disabled
  • webhook.test

MCP (AI assistants)#

The Worbo MCP server lets AI assistants, such as Claude or ChatGPT, work in an organization with the permissions of the person who connected them. The assistant connects with OAuth, and the person approves it in Worbo; the connections are under Integrations › AI assistants.

Nothing reaches many people from an assistant: it drafts and estimates a campaign, and a member approves the launch in Worbo. Errors carry the same codes as the API.

Server address
https://mcp.worbo.app/mcp
Tools
get_workspace_status search_contacts get_contact get_contact_timeline list_schema list_templates get_template list_automations get_automation estimate_audience get_report recommend_items list_conversations get_conversation draft_template draft_segment draft_campaign draft_automation request_approval get_approval send_template upsert_contact upsert_object record_opt_out add_internal_note track_event

Specification and tools#

The OpenAPI 3.1 specification describes every operation, in JSON or YAML. Called with your key, the OpenAPI specification also has the schema of your contacts, object types and event types, for code generators and Postman.

The Postman collection has every request, with its example body; put your key in the apiKey variable of the collection.

  • SDKs: @worbo/sdk for JavaScript and worbo/worbo-php for PHP, with a method for every operation, retries, idempotency and the check of the webhook signature.
  • Without code: Zapier and Make, and the WordPress plugin for WooCommerce shops.

Reference

Workspace#

The key in use, the WhatsApp numbers, the usage of the month and the audit log.

Read the key in use and its organization#

GET /me Any key

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /me
curl "https://api.worbo.app/v1/me" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "key": {
      "name": "CRM",
      "environment": "live",
      "scopes": [
        "string"
      ],
      "expires_at": "2026-10-15T09:00:00+03:00",
      "api_version": "2026-10-05"
    },
    "organization": {
      "name": "Sala Centru",
      "slug": "sala-centru"
    },
    "api_version": "2026-10-05"
  }
}

List the WhatsApp numbers, with quality, tier and warm-up#

GET /numbers Permission workspace:read Live key

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /numbers
curl "https://api.worbo.app/v1/numbers" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 3,
      "phone": "+40 722 000 000",
      "name": "Sala Centru",
      "sandbox": false,
      "quality_rating": "GREEN",
      "messaging_limit_tier": "TIER_1K",
      "warmup": false,
      "marketing_paused_until": "2026-10-15T09:00:00+03:00",
      "disabled": false,
      "disabled_reason": "string"
    }
  ]
}

Read the usage of a month and the limits of the plan#

GET /usage Permission workspace:read Live key

Query parameters

  • month string

    The month, as YYYY-MM; the current month by default.

    Example: 2026-10

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /usage
curl "https://api.worbo.app/v1/usage" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "month": "2026-10",
    "currency": "EUR",
    "categories": {
      "marketing": {
        "messages": 120,
        "billable": 118,
        "estimated_cost": 6.42
      }
    },
    "estimated_cost": 6.42,
    "plan": "growth",
    "billing_state": "active",
    "limits": {}
  }
}

List the audit log of the organization#

GET /audit-logs Permission workspace:read Live key

Query parameters

  • action string

    Only the entries of this action.

    Example: contact.created
  • since string

    Only what changed at or after this moment.

    Format: date-time Example: 2026-10-01T00:00:00+03:00
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /audit-logs
curl "https://api.worbo.app/v1/audit-logs" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 1201,
      "action": "contact.created",
      "label": "Contact created",
      "source": "api",
      "actor": {},
      "subject": {},
      "properties": {},
      "created_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Reference

Contacts#

People, found by any of their identities: phone, email, BSUID or the ID at a source.

List and search contacts#

GET /contacts Permission contacts:read Live key

Query parameters

  • search string

    Text in the name, the phone or the email.

    Example: Ana
  • phone string

    The contact with this phone.

    Example: +40722123456
  • email string

    The contact with this email.

    Format: email Example: ana@example.com
  • external_id string

    The contact with this ID at the source given in source.

    Example: crm-1001
  • source string

    The source of the external ID or of the contacts.

    Example: crm
  • tag string

    Only the contacts with this tag.

    Example: vip
  • updated_since string

    Only what changed at or after this moment.

    Format: date-time Example: 2026-10-01T00:00:00+03:00
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /contacts
curl "https://api.worbo.app/v1/contacts" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 123,
      "identities": [
        {
          "id": 501,
          "type": "phone",
          "value": "+40722123456",
          "source": "string",
          "primary": true
        }
      ],
      "fields": {
        "first_name": "Ana",
        "last_name": "Popescu",
        "language": "ro"
      },
      "tags": [
        "vip"
      ],
      "source": "api",
      "blocked": false,
      "created_at": "2026-10-15T09:00:00+03:00",
      "updated_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Create or update a contact by any of its identities#

POST /contacts Permission contacts:write

The contact is found by any of the identities sent; the others are attached to it. With update_existing_only, an unknown contact is not created.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • identities object Required

    At least one identity; the contact is found by any of them.

    Show the fieldsHide the fields
    • phone string

      E.164, such as +40722123456.

      Example: +40722123456
    • email string
      Format: email Example: ana@example.com
    • bsuid string
    • external_id string

      The ID of the contact at the source: text, or an object with source and value.

      Example: crm-1001
  • source string
    Example: crm
  • fields object
  • tags string[]
  • update_existing_only boolean
    Example: false

Responses

POST /contacts
curl -X POST "https://api.worbo.app/v1/contacts" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "identities": {
      "phone": "+40722123456",
      "email": "ana@example.com",
      "external_id": "crm-1001"
    },
    "source": "crm",
    "fields": {
      "first_name": "Ana"
    },
    "update_existing_only": false
  }'
{
  "data": {
    "id": 123,
    "identities": [
      {
        "id": 501,
        "type": "phone",
        "value": "+40722123456",
        "source": "string",
        "primary": true
      }
    ],
    "fields": {
      "first_name": "Ana",
      "last_name": "Popescu",
      "language": "ro"
    },
    "tags": [
      "vip"
    ],
    "source": "api",
    "blocked": false,
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Create or update up to 100 contacts#

POST /contacts/batch Permission contacts:write

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • items object[] Required
    Show the fieldsHide the fields
    • identities object Required

      At least one identity; the contact is found by any of them.

      Show the fieldsHide the fields
      • phone string

        E.164, such as +40722123456.

        Example: +40722123456
      • email string
        Format: email Example: ana@example.com
      • bsuid string
      • external_id string

        The ID of the contact at the source: text, or an object with source and value.

        Example: crm-1001
    • source string
      Example: crm
    • fields object
    • tags string[]
    • update_existing_only boolean
      Example: false

Responses

POST /contacts/batch
curl -X POST "https://api.worbo.app/v1/contacts/batch" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "identities": {
          "phone": "+40722123456",
          "email": "ana@example.com",
          "external_id": "crm-1001"
        },
        "source": "crm",
        "fields": {
          "first_name": "Ana"
        },
        "update_existing_only": false
      }
    ]
  }'
{
  "data": [
    {
      "index": 0,
      "status": "created",
      "data": {
        "id": 123,
        "identities": [
          {
            "id": 501,
            "type": "phone",
            "value": "+40722123456",
            "source": "string",
            "primary": true
          }
        ],
        "fields": {
          "first_name": "Ana",
          "last_name": "Popescu",
          "language": "ro"
        },
        "tags": [
          "vip"
        ],
        "source": "api",
        "blocked": false,
        "created_at": "2026-10-15T09:00:00+03:00",
        "updated_at": "2026-10-15T09:00:00+03:00"
      },
      "error": {
        "type": "https://worbo.app/docs/api/errors/validation_failed",
        "title": "The request is not valid",
        "status": 422,
        "detail": "The name field is required.",
        "code": "validation_failed",
        "errors": {
          "name": [
            "The name field is required."
          ]
        }
      }
    }
  ]
}

Read a contact#

GET /contacts/{contact} Permission contacts:read Live key

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /contacts/{contact}
curl "https://api.worbo.app/v1/contacts/123" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 123,
    "identities": [
      {
        "id": 501,
        "type": "phone",
        "value": "+40722123456",
        "source": "string",
        "primary": true
      }
    ],
    "fields": {
      "first_name": "Ana",
      "last_name": "Popescu",
      "language": "ro"
    },
    "tags": [
      "vip"
    ],
    "source": "api",
    "blocked": false,
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Change the fields and the tags of a contact#

PATCH /contacts/{contact} Permission contacts:write

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • fields object
  • tags string[]

Responses

PATCH /contacts/{contact}
curl -X PATCH "https://api.worbo.app/v1/contacts/123" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "last_name": "Ionescu"
    }
  }'
{
  "data": {
    "id": 123,
    "identities": [
      {
        "id": 501,
        "type": "phone",
        "value": "+40722123456",
        "source": "string",
        "primary": true
      }
    ],
    "fields": {
      "first_name": "Ana",
      "last_name": "Popescu",
      "language": "ro"
    },
    "tags": [
      "vip"
    ],
    "source": "api",
    "blocked": false,
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Erase a contact, at the request of the person (GDPR)#

DELETE /contacts/{contact} Permission contacts:delete

The data of the contact is erased for good; the audit log keeps only that the erasure happened.

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

DELETE /contacts/{contact}
curl -X DELETE "https://api.worbo.app/v1/contacts/123" \
  -H "Authorization: Bearer $WORBO_API_KEY"
No content

Turn the keyword bot off or on for a contact#

POST /contacts/{contact}/bot Permission contacts:write

For example when a CRM takes over the conversation.

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • enabled boolean Required
    Example: false

Responses

POST /contacts/{contact}/bot
curl -X POST "https://api.worbo.app/v1/contacts/123/bot" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": false
  }'
{
  "data": {
    "contact_id": 123,
    "bot_enabled": false
  }
}

List the identities of a contact#

GET /contacts/{contact}/identities Permission contacts:read Live key

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /contacts/{contact}/identities
curl "https://api.worbo.app/v1/contacts/123/identities" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 501,
      "type": "phone",
      "value": "+40722123456",
      "source": "string",
      "primary": true
    }
  ]
}

Attach an identity to a contact#

POST /contacts/{contact}/identities Permission contacts:write

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • type string Required
    Possible values: phone email bsuid username external_id
  • value string Required
    Example: ana@example.com
  • source string
  • primary boolean
    Example: false

Responses

POST /contacts/{contact}/identities
curl -X POST "https://api.worbo.app/v1/contacts/123/identities" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "email",
    "value": "ana@example.com",
    "primary": false
  }'
{
  "data": {
    "id": 501,
    "type": "phone",
    "value": "+40722123456",
    "source": "string",
    "primary": true
  }
}

Detach an identity from a contact#

DELETE /contacts/{contact}/identities/{identity} Permission contacts:write

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123
  • identity integer Required

    The ID of the identity.

    Example: 501

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

DELETE /contacts/{contact}/identities/{identity}
curl -X DELETE "https://api.worbo.app/v1/contacts/123/identities/501" \
  -H "Authorization: Bearer $WORBO_API_KEY"
No content

Merge another contact into this one#

POST /contacts/{contact}/merge Permission contacts:write

The identities, the history and the objects of the other contact move here; the event contact.merged follows.

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • contact_id integer Required

    The contact merged into this one; its identities and history move here.

    Example: 124

Responses

POST /contacts/{contact}/merge
curl -X POST "https://api.worbo.app/v1/contacts/123/merge" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 124
  }'
{
  "data": {
    "id": 123,
    "identities": [
      {
        "id": 501,
        "type": "phone",
        "value": "+40722123456",
        "source": "string",
        "primary": true
      }
    ],
    "fields": {
      "first_name": "Ana",
      "last_name": "Popescu",
      "language": "ro"
    },
    "tags": [
      "vip"
    ],
    "source": "api",
    "blocked": false,
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Reference

Consent#

The append-only consent history, by purpose and topic, with the proof of each consent.

Read the consent of a contact, with its history#

GET /contacts/{contact}/consents Permission contacts:read Live key

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /contacts/{contact}/consents
curl "https://api.worbo.app/v1/contacts/123/consents" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "status": {
      "purposes": {
        "channel": "granted",
        "transactional": null,
        "marketing": "granted",
        "recommendations": null
      },
      "topics": {},
      "meta_blocked": false,
      "blocked": false,
      "allowed": {
        "transactional": true,
        "marketing": true,
        "recommendations": false
      }
    },
    "history": [
      {
        "id": 900,
        "purpose": "marketing",
        "topic": "string",
        "state": "granted",
        "basis": "consent",
        "source": "form",
        "proof": {},
        "occurred_at": "2026-10-15T09:00:00+03:00"
      }
    ]
  }
}

Record a consent, with its proof, or a withdrawal#

POST /contacts/{contact}/consents Permission consents:write

A consent withdrawn by the person can be given back only by the person: through a form, at checkout or through a link.

Path parameters

  • contact integer Required

    The ID of the contact.

    Example: 123

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • purposes string[] Required
    Minimum: 1
  • state string Required
    Possible values: granted revoked
  • source string
    Possible values: form checkout click_to_chat api
  • topic string null
  • basis string
    Possible values: consent soft_opt_in
  • proof object

    What shows the consent: the text of the form, the page, the IP.

  • occurred_at string null
    Format: date-time

Responses

POST /contacts/{contact}/consents
curl -X POST "https://api.worbo.app/v1/contacts/123/consents" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "purposes": [
      "channel",
      "marketing"
    ],
    "state": "granted",
    "source": "form",
    "proof": {
      "form": "Newsletter, footer",
      "text": "I agree to receive offers on WhatsApp"
    }
  }'
{
  "data": {
    "recorded": [
      {
        "id": 900,
        "purpose": "marketing",
        "topic": "string",
        "state": "granted",
        "basis": "consent",
        "source": "form",
        "proof": {},
        "occurred_at": "2026-10-15T09:00:00+03:00"
      }
    ],
    "status": {
      "purposes": {
        "channel": "granted",
        "transactional": null,
        "marketing": "granted",
        "recommendations": null
      },
      "topics": {},
      "meta_blocked": false,
      "blocked": false,
      "allowed": {
        "transactional": true,
        "marketing": true,
        "recommendations": false
      }
    },
    "history": [
      {
        "id": 900,
        "purpose": "marketing",
        "topic": "string",
        "state": "granted",
        "basis": "consent",
        "source": "form",
        "proof": {},
        "occurred_at": "2026-10-15T09:00:00+03:00"
      }
    ]
  }
}

Reference

Data model#

The fields of the contacts, the object types and the event types of the organization, with their JSON Schema.

Read the JSON Schema of the body that writes a contact#

GET /contacts/schema Any key

With the custom fields of the organization; any key reads it.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /contacts/schema
curl "https://api.worbo.app/v1/contacts/schema" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {}
}

List the fields of the contacts#

GET /field-definitions Any key

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /field-definitions
curl "https://api.worbo.app/v1/field-definitions" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "key": "shoe_size",
      "label": "Shoe size",
      "labels": {},
      "type": "number",
      "required": false,
      "unique": false,
      "sensitivity": "normal",
      "key_date": false,
      "calculated": false,
      "multiple": false,
      "choices": [
        {
          "key": "string",
          "labels": {}
        }
      ],
      "default": {},
      "archived": false
    }
  ]
}

Create a field of the contacts or of an object type#

POST /field-definitions Permission schema:write

Through the same checks and limits as in the dashboard; the key does not change afterwards.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • object_type string

    The key of the object type; without it, the field belongs to the contacts.

    Example: vehicle
  • labels object Required
  • key string
    Example: plate
  • type string Required
    Possible values: text number money date datetime boolean single_select multi_select phone email url reference file location interval
  • sensitivity string
    Possible values: normal personal special
  • is_required boolean
  • is_unique boolean
  • segmentable boolean
  • templatable boolean
  • key_date boolean
  • audited boolean
  • settings object
  • default_value string

    The default value, of the type of the field.

Responses

POST /field-definitions
curl -X POST "https://api.worbo.app/v1/field-definitions" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "object_type": "vehicle",
    "labels": {
      "en": "Plate",
      "ro": "Număr de înmatriculare"
    },
    "key": "plate",
    "type": "text"
  }'
{
  "data": {
    "key": "shoe_size",
    "label": "Shoe size",
    "labels": {},
    "type": "number",
    "required": false,
    "unique": false,
    "sensitivity": "normal",
    "key_date": false,
    "calculated": false,
    "multiple": false,
    "choices": [
      {
        "key": "string",
        "labels": {}
      }
    ],
    "default": {},
    "archived": false
  }
}

List the object types#

GET /object-types Any key

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /object-types
curl "https://api.worbo.app/v1/object-types" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "key": "fit.membership",
      "label": "Membership",
      "labels": {},
      "plural_labels": {},
      "source": "fitness",
      "status_axes": [
        {
          "key": "lifecycle",
          "labels": {},
          "statuses": [
            {
              "key": "active",
              "labels": {},
              "category": "active"
            }
          ]
        }
      ],
      "roles": [
        {
          "key": "holder",
          "labels": {},
          "multiple": false,
          "primary": true
        }
      ],
      "fields": [
        {
          "key": "shoe_size",
          "label": "Shoe size",
          "labels": {},
          "type": "number",
          "required": false,
          "unique": false,
          "sensitivity": "normal",
          "key_date": false,
          "calculated": false,
          "multiple": false,
          "choices": [
            {
              "key": "string",
              "labels": {}
            }
          ],
          "default": {},
          "archived": false
        }
      ]
    }
  ]
}

Create an object type#

POST /object-types Permission schema:write

The type belongs to the organization and counts against its limit of types.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • labels object Required
  • plural_labels object
  • key string
    Example: vehicle
  • status_axes object[]
  • roles object[]
  • title_field string
  • retention_days integer

Responses

POST /object-types
curl -X POST "https://api.worbo.app/v1/object-types" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "labels": {
      "en": "Vehicle",
      "ro": "Vehicul"
    },
    "key": "vehicle"
  }'
{
  "data": {
    "key": "fit.membership",
    "label": "Membership",
    "labels": {},
    "plural_labels": {},
    "source": "fitness",
    "status_axes": [
      {
        "key": "lifecycle",
        "labels": {},
        "statuses": [
          {
            "key": "active",
            "labels": {},
            "category": "active"
          }
        ]
      }
    ],
    "roles": [
      {
        "key": "holder",
        "labels": {},
        "multiple": false,
        "primary": true
      }
    ],
    "fields": [
      {
        "key": "shoe_size",
        "label": "Shoe size",
        "labels": {},
        "type": "number",
        "required": false,
        "unique": false,
        "sensitivity": "normal",
        "key_date": false,
        "calculated": false,
        "multiple": false,
        "choices": [
          {
            "key": "string",
            "labels": {}
          }
        ],
        "default": {},
        "archived": false
      }
    ]
  }
}

Read an object type, with its statuses, roles and fields#

GET /object-types/{type} Any key

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /object-types/{type}
curl "https://api.worbo.app/v1/object-types/fit.membership" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "key": "fit.membership",
    "label": "Membership",
    "labels": {},
    "plural_labels": {},
    "source": "fitness",
    "status_axes": [
      {
        "key": "lifecycle",
        "labels": {},
        "statuses": [
          {
            "key": "active",
            "labels": {},
            "category": "active"
          }
        ]
      }
    ],
    "roles": [
      {
        "key": "holder",
        "labels": {},
        "multiple": false,
        "primary": true
      }
    ],
    "fields": [
      {
        "key": "shoe_size",
        "label": "Shoe size",
        "labels": {},
        "type": "number",
        "required": false,
        "unique": false,
        "sensitivity": "normal",
        "key_date": false,
        "calculated": false,
        "multiple": false,
        "choices": [
          {
            "key": "string",
            "labels": {}
          }
        ],
        "default": {},
        "archived": false
      }
    ]
  }
}

Read the JSON Schema of the body that writes an object of the type#

GET /object-types/{type}/schema Any key

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /object-types/{type}/schema
curl "https://api.worbo.app/v1/object-types/fit.membership/schema" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {}
}

List the event types#

GET /event-types Any key

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /event-types
curl "https://api.worbo.app/v1/event-types" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "key": "visit.recorded",
      "label": "Visit recorded",
      "labels": {},
      "source": "fitness",
      "violation_policy": "reject",
      "properties": [
        {
          "key": "shoe_size",
          "label": "Shoe size",
          "labels": {},
          "type": "number",
          "required": false,
          "unique": false,
          "sensitivity": "normal",
          "key_date": false,
          "calculated": false,
          "multiple": false,
          "choices": [
            {
              "key": "string",
              "labels": {}
            }
          ],
          "default": {},
          "archived": false
        }
      ]
    }
  ]
}

Read an event type, with its properties#

GET /event-types/{type} Any key

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /event-types/{type}
curl "https://api.worbo.app/v1/event-types/fit.membership" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "key": "visit.recorded",
    "label": "Visit recorded",
    "labels": {},
    "source": "fitness",
    "violation_policy": "reject",
    "properties": [
      {
        "key": "shoe_size",
        "label": "Shoe size",
        "labels": {},
        "type": "number",
        "required": false,
        "unique": false,
        "sensitivity": "normal",
        "key_date": false,
        "calculated": false,
        "multiple": false,
        "choices": [
          {
            "key": "string",
            "labels": {}
          }
        ],
        "default": {},
        "archived": false
      }
    ]
  }
}

Read the JSON Schema of the properties of an event type#

GET /event-types/{type}/schema Any key

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /event-types/{type}/schema
curl "https://api.worbo.app/v1/event-types/fit.membership/schema" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {}
}

Reference

Objects#

Memberships, bookings, orders: the records of each object type, linked to contacts in roles.

List the objects of a type#

GET /objects/{type} Permission objects:read Live key

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Query parameters

  • external_id string

    The object with this ID at the source.

    Example: abn-7781
  • source string

    Only the objects of this source.

    Example: upfit
  • contact_id integer

    Only the objects linked to this contact.

    Example: 123
  • status object

    The status on each axis, such as status[lifecycle]=active.

  • updated_since string

    Only what changed at or after this moment.

    Format: date-time Example: 2026-10-01T00:00:00+03:00
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /objects/{type}
curl "https://api.worbo.app/v1/objects/fit.membership" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 456,
      "type": "fit.membership",
      "source": "string",
      "external_id": "abn-7781",
      "title": "Full access 12 luni",
      "fields": {
        "plan": 12,
        "starts_on": "2026-09-01",
        "ends_on": "2027-08-31"
      },
      "statuses": {
        "lifecycle": "active",
        "payment": "ok"
      },
      "raw_status": "string",
      "relations": [
        {
          "id": 77,
          "contact_id": 123,
          "role": "holder",
          "primary": true,
          "muted": false,
          "valid_from": "2026-10-15",
          "valid_until": "2026-10-15"
        }
      ],
      "created_at": "2026-10-15T09:00:00+03:00",
      "updated_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Create or update an object by its ID at the source#

POST /objects/{type} Permission objects:write

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • external_id string Required
    Example: abn-7781
  • source string
    Example: upfit
  • fields object
  • statuses object
  • raw_status string
  • raw_status_label string
  • contact object

    The contact linked in role: {"id": 123} or {"identities": {...}, "fields": {...}}.

  • role string
    Example: holder
  • update_existing_only boolean
    Example: false

Responses

POST /objects/{type}
curl -X POST "https://api.worbo.app/v1/objects/fit.membership" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "abn-7781",
    "source": "upfit",
    "fields": {
      "starts_on": "2026-09-01",
      "ends_on": "2027-08-31"
    },
    "statuses": {
      "lifecycle": "active"
    },
    "contact": {
      "identities": {
        "phone": "+40722123456"
      }
    },
    "role": "holder",
    "update_existing_only": false
  }'
{
  "data": {
    "id": 456,
    "type": "fit.membership",
    "source": "string",
    "external_id": "abn-7781",
    "title": "Full access 12 luni",
    "fields": {
      "plan": 12,
      "starts_on": "2026-09-01",
      "ends_on": "2027-08-31"
    },
    "statuses": {
      "lifecycle": "active",
      "payment": "ok"
    },
    "raw_status": "string",
    "relations": [
      {
        "id": 77,
        "contact_id": 123,
        "role": "holder",
        "primary": true,
        "muted": false,
        "valid_from": "2026-10-15",
        "valid_until": "2026-10-15"
      }
    ],
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Create or update up to 100 objects#

POST /objects/{type}/batch Permission objects:write

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • items object[] Required
    Show the fieldsHide the fields
    • external_id string Required
      Example: abn-7781
    • source string
      Example: upfit
    • fields object
    • statuses object
    • raw_status string
    • raw_status_label string
    • contact object

      The contact linked in role: {"id": 123} or {"identities": {...}, "fields": {...}}.

    • role string
      Example: holder
    • update_existing_only boolean
      Example: false

Responses

POST /objects/{type}/batch
curl -X POST "https://api.worbo.app/v1/objects/fit.membership/batch" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "abn-7781",
        "source": "upfit",
        "fields": {
          "starts_on": "2026-09-01",
          "ends_on": "2027-08-31"
        },
        "statuses": {
          "lifecycle": "active"
        },
        "contact": {
          "identities": {
            "phone": "+40722123456"
          }
        },
        "role": "holder",
        "update_existing_only": false
      }
    ]
  }'
{
  "data": [
    {
      "index": 0,
      "status": "created",
      "data": {
        "id": 456,
        "type": "fit.membership",
        "source": "string",
        "external_id": "abn-7781",
        "title": "Full access 12 luni",
        "fields": {
          "plan": 12,
          "starts_on": "2026-09-01",
          "ends_on": "2027-08-31"
        },
        "statuses": {
          "lifecycle": "active",
          "payment": "ok"
        },
        "raw_status": "string",
        "relations": [
          {
            "id": 77,
            "contact_id": 123,
            "role": "holder",
            "primary": true,
            "muted": false,
            "valid_from": "2026-10-15",
            "valid_until": "2026-10-15"
          }
        ],
        "created_at": "2026-10-15T09:00:00+03:00",
        "updated_at": "2026-10-15T09:00:00+03:00"
      },
      "error": {
        "type": "https://worbo.app/docs/api/errors/validation_failed",
        "title": "The request is not valid",
        "status": 422,
        "detail": "The name field is required.",
        "code": "validation_failed",
        "errors": {
          "name": [
            "The name field is required."
          ]
        }
      }
    }
  ]
}

Read an object#

GET /objects/{type}/{object} Permission objects:read Live key

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership
  • object integer Required

    The ID of the object.

    Example: 456

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /objects/{type}/{object}
curl "https://api.worbo.app/v1/objects/fit.membership/456" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 456,
    "type": "fit.membership",
    "source": "string",
    "external_id": "abn-7781",
    "title": "Full access 12 luni",
    "fields": {
      "plan": 12,
      "starts_on": "2026-09-01",
      "ends_on": "2027-08-31"
    },
    "statuses": {
      "lifecycle": "active",
      "payment": "ok"
    },
    "raw_status": "string",
    "relations": [
      {
        "id": 77,
        "contact_id": 123,
        "role": "holder",
        "primary": true,
        "muted": false,
        "valid_from": "2026-10-15",
        "valid_until": "2026-10-15"
      }
    ],
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Change the fields or the statuses of an object#

PATCH /objects/{type}/{object} Permission objects:write

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership
  • object integer Required

    The ID of the object.

    Example: 456

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • source string
  • fields object
  • statuses object
  • raw_status string
  • raw_status_label string
  • contact object
  • role string

Responses

PATCH /objects/{type}/{object}
curl -X PATCH "https://api.worbo.app/v1/objects/fit.membership/456" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "statuses": {
      "lifecycle": "frozen"
    }
  }'
{
  "data": {
    "id": 456,
    "type": "fit.membership",
    "source": "string",
    "external_id": "abn-7781",
    "title": "Full access 12 luni",
    "fields": {
      "plan": 12,
      "starts_on": "2026-09-01",
      "ends_on": "2027-08-31"
    },
    "statuses": {
      "lifecycle": "active",
      "payment": "ok"
    },
    "raw_status": "string",
    "relations": [
      {
        "id": 77,
        "contact_id": 123,
        "role": "holder",
        "primary": true,
        "muted": false,
        "valid_from": "2026-10-15",
        "valid_until": "2026-10-15"
      }
    ],
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Link a contact to an object, in a role#

POST /objects/{type}/{object}/relations Permission objects:write

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership
  • object integer Required

    The ID of the object.

    Example: 456

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • contact_id integer
    Example: 123
  • contact object

    A contact found or created by its identities, instead of contact_id.

  • role string Required
    Example: beneficiary
  • primary boolean
    Example: false
  • muted boolean
    Example: false
  • valid_from string null
    Format: date
  • valid_until string null
    Format: date

Responses

POST /objects/{type}/{object}/relations
curl -X POST "https://api.worbo.app/v1/objects/fit.membership/456/relations" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 123,
    "role": "beneficiary",
    "primary": false,
    "muted": false
  }'
{
  "data": {
    "id": 77,
    "contact_id": 123,
    "role": "holder",
    "primary": true,
    "muted": false,
    "valid_from": "2026-10-15",
    "valid_until": "2026-10-15"
  }
}

Remove the link of a contact to an object#

DELETE /objects/{type}/{object}/relations/{relation} Permission objects:write

Path parameters

  • type string Required

    The key of the type, such as fit.membership.

    Example: fit.membership
  • object integer Required

    The ID of the object.

    Example: 456
  • relation integer Required

    The ID of the relation.

    Example: 77

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

DELETE /objects/{type}/{object}/relations/{relation}
curl -X DELETE "https://api.worbo.app/v1/objects/fit.membership/456/relations/77" \
  -H "Authorization: Bearer $WORBO_API_KEY"
No content

Reference

Files#

The files of the file fields: uploaded first, then given by ID as the value of the field.

Upload a file for a file field#

POST /files Permission files:write

PDF, images, Office, text or CSV documents, up to 16 MB. A file not used by any field within a day is deleted.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodymultipart/form-data

  • file string Required

    The file: PDF, image, Office, text or CSV, up to 16 MB.

Responses

POST /files
curl -X POST "https://api.worbo.app/v1/files" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "file=@document.pdf"
{
  "data": {
    "id": 77,
    "name": "contract.pdf",
    "mime": "application/pdf",
    "size": 48213,
    "sha256": "string",
    "contact_id": 123,
    "object_id": 456,
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Read a file, with the contact or the object that uses it#

GET /files/{file} Permission files:read Live key

Path parameters

  • file integer Required

    The ID of the file.

    Example: 77

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /files/{file}
curl "https://api.worbo.app/v1/files/77" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 77,
    "name": "contract.pdf",
    "mime": "application/pdf",
    "size": 48213,
    "sha256": "string",
    "contact_id": 123,
    "object_id": 456,
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Download the content of a file#

GET /files/{file}/content Permission files:read Live key

Path parameters

  • file integer Required

    The ID of the file.

    Example: 77

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /files/{file}/content
curl "https://api.worbo.app/v1/files/77/content" \
  -H "Authorization: Bearer $WORBO_API_KEY"
A file, as it was uploaded.

Reference

Events#

What happened at the source; events start automations and update objects.

Record an event#

POST /events Permission events:write

The contact and the object of the event are found or created; an event with the same ID from the same source is recorded only once.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • id string

    The ID of the event at the source; the same ID is recorded only once.

    Example: m-1
  • type string Required
    Example: membership.created
  • occurred_at string
    Format: date-time Example: 2026-10-15T09:00:00+03:00
  • source string
    Example: upfit
  • contact object
  • object object
    Show the fieldsHide the fields
    • type string
    • external_id string
    • role string
    • upsert object
  • properties object
  • historical boolean
    Example: false
  • update_existing_only boolean
    Example: false

Responses

POST /events
curl -X POST "https://api.worbo.app/v1/events" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "m-1",
    "type": "membership.created",
    "occurred_at": "2026-10-15T09:00:00+03:00",
    "source": "upfit",
    "contact": {
      "phone": "+40722123456"
    },
    "object": {
      "type": "fit.membership",
      "external_id": "abn-7781",
      "upsert": {
        "statuses": {
          "lifecycle": "active"
        }
      }
    },
    "properties": {
      "plan": "plan-12"
    },
    "historical": false,
    "update_existing_only": false
  }'
{
  "data": {
    "event_id": 8812,
    "type": "membership.created",
    "source": "upfit",
    "source_id": "m-1",
    "occurred_at": "2026-10-15T09:00:00+03:00",
    "duplicate": false,
    "historical": false,
    "contact_id": 123,
    "object_id": 456,
    "warnings": {},
    "identity_conflict": {}
  }
}

Record up to 100 events#

POST /events/batch Permission events:write

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • items object[] Required
    Show the fieldsHide the fields
    • id string

      The ID of the event at the source; the same ID is recorded only once.

      Example: m-1
    • type string Required
      Example: membership.created
    • occurred_at string
      Format: date-time Example: 2026-10-15T09:00:00+03:00
    • source string
      Example: upfit
    • contact object
    • object object
      Show the fieldsHide the fields
      • type string
      • external_id string
      • role string
      • upsert object
    • properties object
    • historical boolean
      Example: false
    • update_existing_only boolean
      Example: false

Responses

POST /events/batch
curl -X POST "https://api.worbo.app/v1/events/batch" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "id": "m-1",
        "type": "membership.created",
        "occurred_at": "2026-10-15T09:00:00+03:00",
        "source": "upfit",
        "contact": {
          "phone": "+40722123456"
        },
        "object": {
          "type": "fit.membership",
          "external_id": "abn-7781",
          "upsert": {
            "statuses": {
              "lifecycle": "active"
            }
          }
        },
        "properties": {
          "plan": "plan-12"
        },
        "historical": false,
        "update_existing_only": false
      }
    ]
  }'
{
  "data": [
    {
      "index": 0,
      "status": "created",
      "data": {
        "event_id": 8812,
        "type": "membership.created",
        "source": "upfit",
        "source_id": "m-1",
        "occurred_at": "2026-10-15T09:00:00+03:00",
        "duplicate": false,
        "historical": false,
        "contact_id": 123,
        "object_id": 456,
        "warnings": {},
        "identity_conflict": {}
      },
      "error": {
        "type": "https://worbo.app/docs/api/errors/validation_failed",
        "title": "The request is not valid",
        "status": 422,
        "detail": "The name field is required.",
        "code": "validation_failed",
        "errors": {
          "name": [
            "The name field is required."
          ]
        }
      }
    }
  ]
}

Reference

Messages#

WhatsApp messages sent and received, through the same rules as in the dashboard.

List the messages#

GET /messages Permission messages:read Live key

Query parameters

  • contact_id integer

    Only the messages of this contact.

    Example: 123
  • direction string

    Received or sent.

    Possible values: inbound outbound
  • status string

    Only the messages with this status.

    Example: delivered
  • since string

    Only what changed at or after this moment.

    Format: date-time Example: 2026-10-01T00:00:00+03:00
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /messages
curl "https://api.worbo.app/v1/messages" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 7001,
      "contact_id": 123,
      "number_id": 3,
      "direction": "outbound",
      "type": "template",
      "text": "string",
      "untrusted_text": "string",
      "template": {
        "name": "booking_confirmed",
        "language": "ro"
      },
      "category": "utility",
      "status": "pending",
      "reason": "string",
      "error_code": "string",
      "wamid": "string",
      "created_at": "2026-10-15T09:00:00+03:00",
      "sent_at": "2026-10-15T09:00:00+03:00",
      "delivered_at": "2026-10-15T09:00:00+03:00",
      "read_at": "2026-10-15T09:00:00+03:00",
      "failed_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Send a template, a free text or a form to a contact#

POST /messages Permission messages:send

The message goes through the same rules as in the dashboard: consent, quiet hours, frequency and limits. A free text or a form needs the 24-hour window open; a refusal comes with the code of the reason, such as window_closed. The answers to a form come with the webhook flow.submitted.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • contact_id integer Required
    Example: 123
  • number_id integer null
  • template object
    Show the fieldsHide the fields
    • name string Required
      Example: booking_confirmed
    • language string
      Example: ro
    • variables string[]

      The values of the variables; a missing value is filled from the field of the variable. In a library template left unchanged, a missing first name takes the fallback text of the library, for example “Hello from the gym team.”.

  • text string

    A free text, only while the 24-hour window is open; instead of template.

  • flow object
    Show the fieldsHide the fields
    • key string Required

      The key of a published WhatsApp form of the account of the number.

      Example: nps
    • body string Required

      The text of the message, above the button that opens the form.

      Example: Ne spui în 10 secunde cum a fost?

Responses

POST /messages
curl -X POST "https://api.worbo.app/v1/messages" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 123,
    "template": {
      "name": "booking_confirmed",
      "language": "ro",
      "variables": [
        "Ana",
        "3 octombrie, 18:00"
      ]
    },
    "flow": {
      "key": "nps",
      "body": "Ne spui în 10 secunde cum a fost?"
    }
  }'
{
  "data": {
    "id": 7001,
    "contact_id": 123,
    "number_id": 3,
    "direction": "outbound",
    "type": "template",
    "text": "string",
    "untrusted_text": "string",
    "template": {
      "name": "booking_confirmed",
      "language": "ro"
    },
    "category": "utility",
    "status": "pending",
    "reason": "string",
    "error_code": "string",
    "wamid": "string",
    "created_at": "2026-10-15T09:00:00+03:00",
    "sent_at": "2026-10-15T09:00:00+03:00",
    "delivered_at": "2026-10-15T09:00:00+03:00",
    "read_at": "2026-10-15T09:00:00+03:00",
    "failed_at": "2026-10-15T09:00:00+03:00"
  }
}

Read a message and its status#

GET /messages/{message} Permission messages:read Live key

Path parameters

  • message integer Required

    The ID of the message.

    Example: 7001

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /messages/{message}
curl "https://api.worbo.app/v1/messages/7001" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 7001,
    "contact_id": 123,
    "number_id": 3,
    "direction": "outbound",
    "type": "template",
    "text": "string",
    "untrusted_text": "string",
    "template": {
      "name": "booking_confirmed",
      "language": "ro"
    },
    "category": "utility",
    "status": "pending",
    "reason": "string",
    "error_code": "string",
    "wamid": "string",
    "created_at": "2026-10-15T09:00:00+03:00",
    "sent_at": "2026-10-15T09:00:00+03:00",
    "delivered_at": "2026-10-15T09:00:00+03:00",
    "read_at": "2026-10-15T09:00:00+03:00",
    "failed_at": "2026-10-15T09:00:00+03:00"
  }
}

Read the proof of a message sent with a durable medium candidate template#

GET /messages/{message}/evidence Permission messages:read Live key

The exact text the contact got and the document of the header kept by Worbo, with their SHA-256 fingerprints, and the moments Meta reported. It does not replace the email required by law.

Path parameters

  • message integer Required

    The ID of the message.

    Example: 7001

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /messages/{message}/evidence
curl "https://api.worbo.app/v1/messages/7001/evidence" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 52,
    "message_id": 7001,
    "contact_id": 123,
    "number_id": 3,
    "template": {
      "name": "withdrawal_received",
      "language": "ro"
    },
    "recipient": "+40722123456",
    "wamid": "string",
    "text": "string",
    "text_sha256": "string",
    "document": {
      "name": "confirmare.pdf",
      "mime": "application/pdf",
      "size": 48213,
      "sha256": "string",
      "stored": true,
      "error": "string",
      "url": "string"
    },
    "sent_at": "2026-10-15T09:00:00+03:00",
    "delivered_at": "2026-10-15T09:00:00+03:00",
    "read_at": "2026-10-15T09:00:00+03:00",
    "failed_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Download the document kept as the proof of a message#

GET /messages/{message}/evidence/document Permission messages:read Live key

Path parameters

  • message integer Required

    The ID of the message.

    Example: 7001

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /messages/{message}/evidence/document
curl "https://api.worbo.app/v1/messages/7001/evidence/document" \
  -H "Authorization: Bearer $WORBO_API_KEY"
A file, as it was uploaded.

Reference

Document vault#

Files given to a contact through a link that expires, announced on WhatsApp and opened only with a code sent to the phone of the contact.

Give a file to a contact through the vault#

POST /vault Permission vault:write

Upload the file first with uploadFile. The contact gets the template worbo_document on WhatsApp, with the title, the term and the button that opens the link; the link opens only with a code sent to their phone. The answer has the link, the only time it is shown: send it by email too, if needed. The number needs the templates of the vault approved, made on the page of the vault.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • contact_id integer Required
    Example: 123
  • file_id integer Required

    The ID of a file uploaded with uploadFile.

    Example: 77
  • title string Required

    The title the contact sees, in the message and on the page of the link.

    Max length: 120 Example: Rezultatul analizelor
  • expires_in_days integer

    How many days the link is valid, until the end of the last day.

    Default: 7 Minimum: 1 Maximum: 30
  • number_id integer null

Responses

POST /vault
curl -X POST "https://api.worbo.app/v1/vault" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 123,
    "file_id": 77,
    "title": "Rezultatul analizelor"
  }'
{
  "data": {
    "id": 15,
    "contact_id": 123,
    "file_id": 77,
    "number_id": 3,
    "title": "Rezultatul analizelor",
    "state": "active",
    "expires_at": "2026-10-15T09:00:00+03:00",
    "opened_at": "2026-10-15T09:00:00+03:00",
    "opens": 1,
    "message_id": 7001,
    "created_at": "2026-10-15T09:00:00+03:00",
    "url": "https://example.com"
  }
}

Read a document of the vault, with the state of its link and the openings#

GET /vault/{vault} Permission vault:read Live key

Path parameters

  • vault integer Required

    The ID of the document in the vault.

    Example: 15

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /vault/{vault}
curl "https://api.worbo.app/v1/vault/15" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 15,
    "contact_id": 123,
    "file_id": 77,
    "number_id": 3,
    "title": "Rezultatul analizelor",
    "state": "active",
    "expires_at": "2026-10-15T09:00:00+03:00",
    "opened_at": "2026-10-15T09:00:00+03:00",
    "opens": 1,
    "message_id": 7001,
    "created_at": "2026-10-15T09:00:00+03:00",
    "url": "https://example.com"
  }
}

Revoke the link of a document of the vault#

DELETE /vault/{vault} Permission vault:write

Path parameters

  • vault integer Required

    The ID of the document in the vault.

    Example: 15

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

DELETE /vault/{vault}
curl -X DELETE "https://api.worbo.app/v1/vault/15" \
  -H "Authorization: Bearer $WORBO_API_KEY"
No content

Reference

Verification codes#

One-time codes sent on WhatsApp with the authentication template of the number, checked by Worbo or by the organization.

Send a verification code on WhatsApp#

POST /otp Permission otp:send

Without code, Worbo makes a 6-digit code, valid for 10 minutes, and checks it with verifyOtp; with code, the organization checks it itself. The message leaves at once, with the authentication template of the number, approved on its page. A phone known to have no WhatsApp gets otp_undeliverable at once, so the site can offer SMS or email; otherwise a failure comes as the status of the message and the webhook message.failed. A phone gets at most 5 codes in 15 minutes and one every 30 seconds (otp_rate_limited, otp_too_soon). The code never appears in answers, webhooks or the inbox.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • phone string Required

    The phone that gets the code, in international format.

    Example: +40722123456
  • code string

    The code made by the organization, which checks it itself; without it, Worbo makes the code and checks it.

    Example: 482913
  • number_id integer null
  • language string

    The language of the message; by default, the language of the contact.

    Example: ro
  • purpose string

    What the code is for, kept with it, such as login or document.

    Max length: 64 Example: login

Responses

POST /otp
curl -X POST "https://api.worbo.app/v1/otp" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+40722123456",
    "code": "482913",
    "language": "ro",
    "purpose": "login"
  }'
{
  "data": {
    "id": 880,
    "phone": "+40722123456",
    "purpose": "login",
    "verifiable": true,
    "expires_at": "2026-10-15T09:00:00+03:00",
    "message_id": 7001,
    "status": "pending"
  }
}

Check a verification code made by Worbo#

POST /otp/{otp}/verify Permission otp:verify

A code is used once, within its term, with at most 5 attempts; the answer says why a check failed. A code given by the organization gets 409 otp_not_verifiable.

Path parameters

  • otp integer Required

    The ID of the verification code, from the answer that sent it.

    Example: 880

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • code string Required
    Example: 482913

Responses

POST /otp/{otp}/verify
curl -X POST "https://api.worbo.app/v1/otp/880/verify" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "482913"
  }'
{
  "data": {
    "id": 880,
    "verified": true,
    "reason": "wrong_code",
    "attempts_left": 4
  }
}

Reference

Recommendations#

The rules of the recommendation engine and what one of them would recommend now to a contact, with the reason of each item.

List the recommendation rules#

GET /recommendation-rules Permission recommendations:read

The active rules, made in the dashboard at Recommendations: the catalog, the types in their order, the number of items and the cooldowns. The automations use them by key.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /recommendation-rules
curl "https://api.worbo.app/v1/recommendation-rules" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "key": "ecom.cross_sell",
      "name": "Bought together",
      "catalog": "ecom.products",
      "types": [
        {
          "type": "co_purchase",
          "params": {}
        }
      ],
      "max_items": 3,
      "contact_cooldown_days": 14,
      "item_cooldown_days": 30,
      "fill_bestsellers": true
    }
  ]
}

Read the results of a recommendation rule#

GET /recommendation-rules/{rule}/results Permission recommendations:read Live key

On a period, by default the last 30 days: the recommendations sent and their recipients, the steps skipped by reason, the clicks on the items, the conversions within 7 days of the message (an order for the products, a booking for the classes, a membership for the plans), the revenue per recipient, the control group of the automations, the opt-outs after the message and the cost at Meta per conversion.

Path parameters

  • rule string Required

    The key of the recommendation rule.

    Example: ecom.cross_sell

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /recommendation-rules/{rule}/results
curl "https://api.worbo.app/v1/recommendation-rules/ecom.cross_sell/results" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "rule": "ecom.cross_sell",
    "from": "2026-10-15T09:00:00+03:00",
    "to": "2026-10-15T09:00:00+03:00",
    "sent": 120,
    "recipients": 118,
    "skipped": {},
    "clicks": 34,
    "clickers": 29,
    "items": [
      {
        "id": 310,
        "name": "Filtre de cafea",
        "clicks": 12
      }
    ],
    "goals": [
      "order.created"
    ],
    "conversions": 9,
    "conversion_rate": 0.075,
    "revenue": 1840.5,
    "revenue_per_recipient": 15.6,
    "currency": "RON",
    "control": {
      "contacts": 13,
      "conversions": 0,
      "rate": 0
    },
    "lift": 0.075,
    "opt_outs": 1,
    "cost": 18.4,
    "cost_per_conversion": 2.04
  }
}

Preview a recommendation rule on a contact#

POST /recommendations/preview Permission recommendations:read Live key

What the rule would recommend now to the contact, with the reason of each item, the items left out and why, the cooldown of the rule and the consent needed. Nothing is sent and the cooldowns stay as they are. The recommendations from the history of the contact need the purpose recommendations besides marketing.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • rule string Required
    Example: ecom.cross_sell
  • contact_id integer Required
    Example: 123

Responses

POST /recommendations/preview
curl -X POST "https://api.worbo.app/v1/recommendations/preview" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "rule": "ecom.cross_sell",
    "contact_id": 123
  }'
{
  "data": {
    "rule": "ecom.cross_sell",
    "contact_id": 123,
    "items": [
      {
        "id": 310,
        "name": "Filtre de cafea",
        "price": 19.9,
        "currency": "RON",
        "url": "string",
        "image_url": "string",
        "type": "co_purchase",
        "score": 5,
        "reason": "Often bought together with Coffee beans 1kg (5 orders).",
        "details": {}
      }
    ],
    "excluded": {},
    "empty": "cooldown",
    "cooldown_until": "2026-10-15T09:00:00+03:00",
    "purpose": "marketing",
    "sendable": true,
    "consent_reason": "string"
  }
}

Reference

Templates#

WhatsApp templates: drafts checked by the linter, submission to Meta and status.

List the templates#

GET /templates Permission templates:read

Query parameters

  • number_id integer

    Only the templates of this number.

    Example: 3
  • status string

    Only the templates with this status.

    Example: approved
  • name string

    Only the templates with this name.

    Example: booking_confirmed
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /templates
curl "https://api.worbo.app/v1/templates" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 31,
      "number_id": 3,
      "name": "booking_confirmed",
      "language": "ro",
      "category": "utility",
      "status": "approved",
      "rejected_reason": "string",
      "quality": "string",
      "components": [
        {}
      ],
      "variables": [
        {
          "example": "Ana",
          "field": "contact.first_name"
        }
      ],
      "source": "string",
      "submitted_at": "2026-10-15T09:00:00+03:00",
      "created_at": "2026-10-15T09:00:00+03:00",
      "updated_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Draft a template, checked by the linter#

POST /templates Permission templates:write

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • number_id integer null
  • name string Required
    Example: booking_confirmed
  • language string Required
    Example: ro
  • category string Required
    Possible values: utility marketing
  • body string Required
    Example: Bună, {{1}}. Rezervarea ta pentru {{2}} este confirmată.
  • examples string[]
  • fields string[]

    For each variable, the field that fills it, such as contact.first_name, or null.

  • header_format string
  • header_text string
  • header_example string
  • footer string
  • buttons object[]

Responses

POST /templates
curl -X POST "https://api.worbo.app/v1/templates" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "booking_confirmed",
    "language": "ro",
    "category": "utility",
    "body": "Bună, {{1}}. Rezervarea ta pentru {{2}} este confirmată.",
    "examples": [
      "Ana",
      "3 octombrie, 18:00"
    ],
    "fields": [
      "contact.first_name",
      null
    ]
  }'
{
  "data": {
    "id": 31,
    "number_id": 3,
    "name": "booking_confirmed",
    "language": "ro",
    "category": "utility",
    "status": "approved",
    "rejected_reason": "string",
    "quality": "string",
    "components": [
      {}
    ],
    "variables": [
      {
        "example": "Ana",
        "field": "contact.first_name"
      }
    ],
    "source": "string",
    "submitted_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00",
    "lint": {}
  }
}

Read a template#

GET /templates/{template} Permission templates:read

Path parameters

  • template integer Required

    The ID of the template.

    Example: 31

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /templates/{template}
curl "https://api.worbo.app/v1/templates/31" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 31,
    "number_id": 3,
    "name": "booking_confirmed",
    "language": "ro",
    "category": "utility",
    "status": "approved",
    "rejected_reason": "string",
    "quality": "string",
    "components": [
      {}
    ],
    "variables": [
      {
        "example": "Ana",
        "field": "contact.first_name"
      }
    ],
    "source": "string",
    "submitted_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Submit a template to Meta#

POST /templates/{template}/submit Permission templates:write

Stopped by the linter, with the reason, or accepted, with the status in review.

Path parameters

  • template integer Required

    The ID of the template.

    Example: 31

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

POST /templates/{template}/submit
curl -X POST "https://api.worbo.app/v1/templates/31/submit" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "id": 31,
    "number_id": 3,
    "name": "booking_confirmed",
    "language": "ro",
    "category": "utility",
    "status": "approved",
    "rejected_reason": "string",
    "quality": "string",
    "components": [
      {}
    ],
    "variables": [
      {
        "example": "Ana",
        "field": "contact.first_name"
      }
    ],
    "source": "string",
    "submitted_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Reference

Offers#

Offers found by their code and redeemed, at the front desk or in the software of the source.

Find an offer by its code#

GET /offers/{code} Permission objects:read Live key

Path parameters

  • code string Required

    The code of the offer.

    Example: AUTUMN-7KQ2

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /offers/{code}
curl "https://api.worbo.app/v1/offers/AUTUMN-7KQ2" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 456,
    "type": "fit.membership",
    "source": "string",
    "external_id": "abn-7781",
    "title": "Full access 12 luni",
    "fields": {
      "plan": 12,
      "starts_on": "2026-09-01",
      "ends_on": "2027-08-31"
    },
    "statuses": {
      "lifecycle": "active",
      "payment": "ok"
    },
    "raw_status": "string",
    "relations": [
      {
        "id": 77,
        "contact_id": 123,
        "role": "holder",
        "primary": true,
        "muted": false,
        "valid_from": "2026-10-15",
        "valid_until": "2026-10-15"
      }
    ],
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Mark an offer as used#

POST /offers/{code}/redeem Permission objects:write

Path parameters

  • code string Required

    The code of the offer.

    Example: AUTUMN-7KQ2

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • location_id integer null
  • beneficiary_contact_id integer null
  • occurred_at string null
    Format: date-time

Responses

POST /offers/{code}/redeem
curl -X POST "https://api.worbo.app/v1/offers/AUTUMN-7KQ2/redeem" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "data": {
    "id": 456,
    "type": "fit.membership",
    "source": "string",
    "external_id": "abn-7781",
    "title": "Full access 12 luni",
    "fields": {
      "plan": 12,
      "starts_on": "2026-09-01",
      "ends_on": "2027-08-31"
    },
    "statuses": {
      "lifecycle": "active",
      "payment": "ok"
    },
    "raw_status": "string",
    "relations": [
      {
        "id": 77,
        "contact_id": 123,
        "role": "holder",
        "primary": true,
        "muted": false,
        "valid_from": "2026-10-15",
        "valid_until": "2026-10-15"
      }
    ],
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Reference

Segments#

Dynamic segments of contacts, counted live.

List the segments#

GET /segments Permission segments:read Live key

Query parameters

  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /segments
curl "https://api.worbo.app/v1/segments" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 12,
      "name": "Toți membrii",
      "description": "string",
      "definition": {
        "match": "all",
        "conditions": [
          {
            "type": "field",
            "field": "first_name",
            "operator": "not_empty"
          }
        ]
      },
      "last_count": 240,
      "counted_at": "2026-10-15T09:00:00+03:00",
      "created_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Create a segment#

POST /segments Permission segments:write

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • name string Required
    Example: Toți membrii
  • description string
  • definition object Required
    Show the fieldsHide the fields
    • match string Required
      Possible values: all any
    • conditions object[] Required

Responses

POST /segments
curl -X POST "https://api.worbo.app/v1/segments" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Toți membrii",
    "definition": {
      "match": "all",
      "conditions": [
        {
          "type": "field",
          "field": "first_name",
          "operator": "not_empty"
        }
      ]
    }
  }'
{
  "data": {
    "id": 12,
    "name": "Toți membrii",
    "description": "string",
    "definition": {
      "match": "all",
      "conditions": [
        {
          "type": "field",
          "field": "first_name",
          "operator": "not_empty"
        }
      ]
    },
    "last_count": 240,
    "counted_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Count the contacts of a definition, without saving it#

POST /segments/count Permission segments:write

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • definition object Required
    Show the fieldsHide the fields
    • match string Required
      Possible values: all any
    • conditions object[] Required

Responses

POST /segments/count
curl -X POST "https://api.worbo.app/v1/segments/count" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "definition": {
      "match": "all",
      "conditions": [
        {
          "type": "field",
          "field": "first_name",
          "operator": "not_empty"
        }
      ]
    }
  }'
{
  "data": {
    "count": 240
  }
}

Read a segment, with its live count#

GET /segments/{segment} Permission segments:read Live key

Path parameters

  • segment integer Required

    The ID of the segment.

    Example: 12

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /segments/{segment}
curl "https://api.worbo.app/v1/segments/12" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 12,
    "name": "Toți membrii",
    "description": "string",
    "definition": {
      "match": "all",
      "conditions": [
        {
          "type": "field",
          "field": "first_name",
          "operator": "not_empty"
        }
      ]
    },
    "last_count": 240,
    "counted_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00",
    "count": 240
  }
}

Reference

Automations#

Reading automations, starting one for a contact and taking a contact out of a run.

List the automations#

GET /automations Permission automations:read

Query parameters

  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /automations
curl "https://api.worbo.app/v1/automations" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 8,
      "name": "Recâștigare",
      "status": "active",
      "trigger": "manual",
      "number_id": 3,
      "recipe": "string",
      "version_id": 14,
      "holdout_percent": 0,
      "created_at": "2026-10-15T09:00:00+03:00",
      "updated_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Read an automation, with its definition and its figures#

GET /automations/{automation} Permission automations:read

Path parameters

  • automation integer Required

    The ID of the automation.

    Example: 8

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /automations/{automation}
curl "https://api.worbo.app/v1/automations/8" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 8,
    "name": "Recâștigare",
    "status": "active",
    "trigger": "manual",
    "number_id": 3,
    "recipe": "string",
    "version_id": 14,
    "holdout_percent": 0,
    "created_at": "2026-10-15T09:00:00+03:00",
    "updated_at": "2026-10-15T09:00:00+03:00",
    "definition": {},
    "report": {}
  }
}

Start an automation for a contact#

POST /automations/{automation}/runs Permission automations:run

Only an active automation started by hand. The run takes the newest object of the contact of the type chosen in the trigger; the same Idempotency-Key starts it only once.

Path parameters

  • automation integer Required

    The ID of the automation.

    Example: 8

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • contact_id integer Required
    Example: 123

Responses

POST /automations/{automation}/runs
curl -X POST "https://api.worbo.app/v1/automations/8/runs" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 123
  }'
{
  "data": {
    "id": 3301,
    "automation_id": 8,
    "contact_id": 123,
    "object_id": 1,
    "status": "active",
    "exit_reason": "string",
    "held_out": false,
    "started_at": "2026-10-15T09:00:00+03:00",
    "finished_at": "2026-10-15T09:00:00+03:00",
    "converted_at": "2026-10-15T09:00:00+03:00"
  }
}

Take a contact out of a run#

DELETE /automations/{automation}/runs/{run} Permission automations:run

Path parameters

  • automation integer Required

    The ID of the automation.

    Example: 8
  • run integer Required

    The ID of the run.

    Example: 3301

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

DELETE /automations/{automation}/runs/{run}
curl -X DELETE "https://api.worbo.app/v1/automations/8/runs/3301" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 3301,
    "automation_id": 8,
    "contact_id": 123,
    "object_id": 1,
    "status": "active",
    "exit_reason": "string",
    "held_out": false,
    "started_at": "2026-10-15T09:00:00+03:00",
    "finished_at": "2026-10-15T09:00:00+03:00",
    "converted_at": "2026-10-15T09:00:00+03:00"
  }
}

Reference

Campaigns#

Campaign drafts and their estimate; the launch is approved in the dashboard.

List the campaigns#

GET /campaigns Permission campaigns:read

Query parameters

  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /campaigns
curl "https://api.worbo.app/v1/campaigns" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 21,
      "name": "Oferta de toamnă",
      "status": "draft",
      "kind": "template",
      "text": "string",
      "object_id": 1,
      "object_roles": [
        "string"
      ],
      "purpose": "marketing",
      "number_id": 3,
      "template": "autumn_offer",
      "variables": [
        "string"
      ],
      "header_text": "string",
      "topic": "string",
      "segment_id": 12,
      "location_id": 1,
      "scheduled_at": "2026-10-15T09:00:00+03:00",
      "expires_at": "2026-10-15T09:00:00+03:00",
      "wave_by": "size",
      "wave_size": 1,
      "wave_hours": 24,
      "wave_segments": [
        1
      ],
      "budget": "250.00",
      "total": 1,
      "processed": 1,
      "created_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Create a campaign draft#

POST /campaigns Permission campaigns:write

The moments come in ISO 8601, with their time zone. The launch is approved in the dashboard.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • name string Required
    Example: Oferta de toamnă
  • kind string

    free: a free message without a template, only to the contacts with the 24-hour window open on the number. object: a utility template to the people of one object, instead of a segment.

    Default: template Possible values: template free object
  • object_id integer null

    With kind object: the object whose people get the notice.

    Example: 456
  • object_roles string[] null

    With kind object: the roles of the people who get it; none means all.

  • text string null

    The free message, the same for everyone; only with kind free.

    Max length: 4096
  • purpose string null

    What the free message is: marketing, with its consent and limit, or information.

    Possible values: marketing transactional
  • number_id integer null
    Example: 3
  • template string null
    Example: autumn_offer
  • variables string[]
  • header_text string null
  • topic string null
  • segment_id integer null
    Example: 12
  • location_id integer null
  • scheduled_at string null
    Format: date-time Example: 2026-10-20T10:00:00+03:00
  • expires_at string null
    Format: date-time
  • wave_by string
    Possible values: size location segment
  • wave_size integer null
  • wave_hours integer
    Example: 24
  • wave_segments integer[] null
  • budget number null

Responses

POST /campaigns
curl -X POST "https://api.worbo.app/v1/campaigns" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Oferta de toamnă",
    "object_id": 456,
    "object_roles": [
      "holder"
    ],
    "number_id": 3,
    "template": "autumn_offer",
    "segment_id": 12,
    "scheduled_at": "2026-10-20T10:00:00+03:00",
    "wave_by": "size",
    "wave_hours": 24
  }'
{
  "data": {
    "id": 21,
    "name": "Oferta de toamnă",
    "status": "draft",
    "kind": "template",
    "text": "string",
    "object_id": 1,
    "object_roles": [
      "string"
    ],
    "purpose": "marketing",
    "number_id": 3,
    "template": "autumn_offer",
    "variables": [
      "string"
    ],
    "header_text": "string",
    "topic": "string",
    "segment_id": 12,
    "location_id": 1,
    "scheduled_at": "2026-10-15T09:00:00+03:00",
    "expires_at": "2026-10-15T09:00:00+03:00",
    "wave_by": "size",
    "wave_size": 1,
    "wave_hours": 24,
    "wave_segments": [
      1
    ],
    "budget": "250.00",
    "total": 1,
    "processed": 1,
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Read a campaign, with the report of its messages and the cost#

GET /campaigns/{campaign} Permission campaigns:read

Path parameters

  • campaign integer Required

    The ID of the campaign.

    Example: 21

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /campaigns/{campaign}
curl "https://api.worbo.app/v1/campaigns/21" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 21,
    "name": "Oferta de toamnă",
    "status": "draft",
    "kind": "template",
    "text": "string",
    "object_id": 1,
    "object_roles": [
      "string"
    ],
    "purpose": "marketing",
    "number_id": 3,
    "template": "autumn_offer",
    "variables": [
      "string"
    ],
    "header_text": "string",
    "topic": "string",
    "segment_id": 12,
    "location_id": 1,
    "scheduled_at": "2026-10-15T09:00:00+03:00",
    "expires_at": "2026-10-15T09:00:00+03:00",
    "wave_by": "size",
    "wave_size": 1,
    "wave_hours": 24,
    "wave_segments": [
      1
    ],
    "budget": "250.00",
    "total": 1,
    "processed": 1,
    "created_at": "2026-10-15T09:00:00+03:00",
    "report": {}
  }
}

Estimate the audience and the cost of a campaign#

POST /campaigns/{campaign}/estimate Permission campaigns:write

With the same exclusions as at launch: no WhatsApp, no consent, undeliverable, the frequency cap.

Path parameters

  • campaign integer Required

    The ID of the campaign.

    Example: 21

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

POST /campaigns/{campaign}/estimate
curl -X POST "https://api.worbo.app/v1/campaigns/21/estimate" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "audience": 240,
    "contactable": 198,
    "excluded": {
      "whatsapp": 12,
      "consent": 28,
      "optin": 10,
      "marketing": 18,
      "window": 0,
      "undeliverable": 2
    },
    "capped": 0,
    "other_countries": 0,
    "number": {
      "quality": "GREEN",
      "marketing_paused_until": "2026-10-15T09:00:00+03:00"
    },
    "united_states": 0,
    "template": {},
    "cost": {
      "amount": 10.79,
      "free": 0,
      "rate": 0.0545,
      "currency": "EUR",
      "country": "RO",
      "budget_messages": 1
    },
    "waves": {
      "count": 1,
      "per_day": 198,
      "last_at": "2026-10-15T09:00:00+03:00",
      "sizes": [
        {}
      ]
    },
    "limit": {
      "daily": 1000,
      "days": 1,
      "over": false
    },
    "start": "2026-10-15T09:00:00+03:00",
    "quiet_until": "2026-10-15T09:00:00+03:00",
    "ends_before_last_wave": false
  }
}

Reference

Conversations#

The inbox: conversations, their messages, replies, assignment and closing.

List the conversations#

GET /conversations Permission conversations:read Live key

Query parameters

  • status string

    Only the conversations with this status.

    Possible values: open pending resolved
  • contact_id integer

    Only the conversations of this contact.

    Example: 123
  • assigned_user_id integer

    Only the conversations assigned to this member.

    Example: 5
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /conversations
curl "https://api.worbo.app/v1/conversations" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 640,
      "contact_id": 123,
      "number_id": 3,
      "status": "open",
      "assigned_user_id": 1,
      "assigned_team_id": 1,
      "unread": 1,
      "last_message_at": "2026-10-15T09:00:00+03:00",
      "last_message_direction": "inbound",
      "last_message_preview": "string",
      "untrusted_last_message_preview": "string",
      "window_closes_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

List the messages of a conversation#

GET /conversations/{conversation}/messages Permission conversations:read Live key

Path parameters

  • conversation integer Required

    The ID of the conversation.

    Example: 640

Query parameters

  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /conversations/{conversation}/messages
curl "https://api.worbo.app/v1/conversations/640/messages" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 7001,
      "contact_id": 123,
      "number_id": 3,
      "direction": "outbound",
      "type": "template",
      "text": "string",
      "untrusted_text": "string",
      "template": {
        "name": "booking_confirmed",
        "language": "ro"
      },
      "category": "utility",
      "status": "pending",
      "reason": "string",
      "error_code": "string",
      "wamid": "string",
      "created_at": "2026-10-15T09:00:00+03:00",
      "sent_at": "2026-10-15T09:00:00+03:00",
      "delivered_at": "2026-10-15T09:00:00+03:00",
      "read_at": "2026-10-15T09:00:00+03:00",
      "failed_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Reply with a free text, in the 24-hour window#

POST /conversations/{conversation}/messages Permission conversations:reply

Path parameters

  • conversation integer Required

    The ID of the conversation.

    Example: 640

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • text string Required
    Example: Bună! Cu ce vă ajutăm?

Responses

POST /conversations/{conversation}/messages
curl -X POST "https://api.worbo.app/v1/conversations/640/messages" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Bună! Cu ce vă ajutăm?"
  }'
{
  "data": {
    "id": 7001,
    "contact_id": 123,
    "number_id": 3,
    "direction": "outbound",
    "type": "template",
    "text": "string",
    "untrusted_text": "string",
    "template": {
      "name": "booking_confirmed",
      "language": "ro"
    },
    "category": "utility",
    "status": "pending",
    "reason": "string",
    "error_code": "string",
    "wamid": "string",
    "created_at": "2026-10-15T09:00:00+03:00",
    "sent_at": "2026-10-15T09:00:00+03:00",
    "delivered_at": "2026-10-15T09:00:00+03:00",
    "read_at": "2026-10-15T09:00:00+03:00",
    "failed_at": "2026-10-15T09:00:00+03:00"
  }
}

Assign a conversation to a member#

POST /conversations/{conversation}/assign Permission conversations:reply

Path parameters

  • conversation integer Required

    The ID of the conversation.

    Example: 640

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • user_id integer Required null

    The member who takes the conversation; null leaves it unassigned.

    Example: 5

Responses

POST /conversations/{conversation}/assign
curl -X POST "https://api.worbo.app/v1/conversations/640/assign" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": 5
  }'
{
  "data": {
    "id": 640,
    "contact_id": 123,
    "number_id": 3,
    "status": "open",
    "assigned_user_id": 1,
    "assigned_team_id": 1,
    "unread": 1,
    "last_message_at": "2026-10-15T09:00:00+03:00",
    "last_message_direction": "inbound",
    "last_message_preview": "string",
    "untrusted_last_message_preview": "string",
    "window_closes_at": "2026-10-15T09:00:00+03:00"
  }
}

Close a conversation#

POST /conversations/{conversation}/close Permission conversations:reply

Path parameters

  • conversation integer Required

    The ID of the conversation.

    Example: 640

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

POST /conversations/{conversation}/close
curl -X POST "https://api.worbo.app/v1/conversations/640/close" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "id": 640,
    "contact_id": 123,
    "number_id": 3,
    "status": "open",
    "assigned_user_id": 1,
    "assigned_team_id": 1,
    "unread": 1,
    "last_message_at": "2026-10-15T09:00:00+03:00",
    "last_message_direction": "inbound",
    "last_message_preview": "string",
    "untrusted_last_message_preview": "string",
    "window_closes_at": "2026-10-15T09:00:00+03:00"
  }
}

Reference

Catalogs#

Products, services, classes, plans and locations, written one by one or in batches.

List the catalogs#

GET /catalogs Permission catalogs:read

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /catalogs
curl "https://api.worbo.app/v1/catalogs" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "key": "fit.classes",
      "name": "Classes",
      "kind": "class",
      "currency": "RON",
      "source": "fitness"
    }
  ]
}

List the items of a catalog#

GET /catalogs/{catalog}/items Permission catalogs:read

Path parameters

  • catalog string Required

    The key of the catalog, such as fit.classes.

    Example: fit.classes

Query parameters

  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /catalogs/{catalog}/items
curl "https://api.worbo.app/v1/catalogs/fit.classes/items" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 310,
      "external_id": "yoga",
      "sku": "string",
      "name": "Yoga",
      "price": "50.00",
      "currency": "RON",
      "stock": 1,
      "available": true,
      "recommendable": true,
      "url": "string",
      "image_url": "string",
      "fields": {},
      "updated_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Create or update an item by its ID at the source#

POST /catalogs/{catalog}/items Permission catalogs:write

Path parameters

  • catalog string Required

    The key of the catalog, such as fit.classes.

    Example: fit.classes

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • id integer
  • external_id string
    Example: yoga
  • name string
    Example: Yoga
  • sku string
  • price number
    Example: 50
  • currency string
    Example: RON
  • stock integer
  • available boolean
    Example: true
  • recommendable boolean
    Example: true
  • url string
  • image_url string
  • custom object

Responses

POST /catalogs/{catalog}/items
curl -X POST "https://api.worbo.app/v1/catalogs/fit.classes/items" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "yoga",
    "name": "Yoga",
    "price": 50,
    "currency": "RON",
    "available": true,
    "recommendable": true
  }'
{
  "data": {
    "id": 310,
    "external_id": "yoga",
    "sku": "string",
    "name": "Yoga",
    "price": "50.00",
    "currency": "RON",
    "stock": 1,
    "available": true,
    "recommendable": true,
    "url": "string",
    "image_url": "string",
    "fields": {},
    "updated_at": "2026-10-15T09:00:00+03:00"
  }
}

Create or update up to 100 items#

POST /catalogs/{catalog}/items/batch Permission catalogs:write

Path parameters

  • catalog string Required

    The key of the catalog, such as fit.classes.

    Example: fit.classes

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • items object[] Required
    Show the fieldsHide the fields
    • id integer
    • external_id string
      Example: yoga
    • name string
      Example: Yoga
    • sku string
    • price number
      Example: 50
    • currency string
      Example: RON
    • stock integer
    • available boolean
      Example: true
    • recommendable boolean
      Example: true
    • url string
    • image_url string
    • custom object

Responses

POST /catalogs/{catalog}/items/batch
curl -X POST "https://api.worbo.app/v1/catalogs/fit.classes/items/batch" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "yoga",
        "name": "Yoga",
        "price": 50,
        "currency": "RON",
        "available": true,
        "recommendable": true
      }
    ]
  }'
{
  "data": [
    {
      "index": 0,
      "status": "created",
      "data": {
        "id": 310,
        "external_id": "yoga",
        "sku": "string",
        "name": "Yoga",
        "price": "50.00",
        "currency": "RON",
        "stock": 1,
        "available": true,
        "recommendable": true,
        "url": "string",
        "image_url": "string",
        "fields": {},
        "updated_at": "2026-10-15T09:00:00+03:00"
      },
      "error": {
        "type": "https://worbo.app/docs/api/errors/validation_failed",
        "title": "The request is not valid",
        "status": 422,
        "detail": "The name field is required.",
        "code": "validation_failed",
        "errors": {
          "name": [
            "The name field is required."
          ]
        }
      }
    }
  ]
}

Reference

Webhooks#

The endpoints that receive the events of Worbo, their deliveries and replays.

List the webhook endpoints#

GET /webhook-endpoints Permission webhooks:manage

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /webhook-endpoints
curl "https://api.worbo.app/v1/webhook-endpoints" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 4,
      "url": "https://crm.example.com/worbo",
      "description": "string",
      "events": [
        "contact.created",
        "message.received"
      ],
      "payload": "snapshot",
      "enabled": true,
      "disabled_reason": "string",
      "failing_since": "2026-10-15T09:00:00+03:00",
      "last_success_at": "2026-10-15T09:00:00+03:00",
      "created_at": "2026-10-15T09:00:00+03:00"
    }
  ]
}

Add a webhook endpoint#

POST /webhook-endpoints Permission webhooks:manage

The signing secret is in the response, only now.

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • url string Required
    Format: uri Example: https://crm.example.com/worbo
  • description string
  • events string[] Required
  • payload string
    Possible values: snapshot thin

Responses

POST /webhook-endpoints
curl -X POST "https://api.worbo.app/v1/webhook-endpoints" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://crm.example.com/worbo",
    "events": [
      "contact.created",
      "message.received"
    ],
    "payload": "snapshot"
  }'
{
  "data": {
    "id": 4,
    "url": "https://crm.example.com/worbo",
    "description": "string",
    "events": [
      "contact.created",
      "message.received"
    ],
    "payload": "snapshot",
    "enabled": true,
    "disabled_reason": "string",
    "failing_since": "2026-10-15T09:00:00+03:00",
    "last_success_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00",
    "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
  }
}

Change the address or the events of an endpoint#

PATCH /webhook-endpoints/{endpoint} Permission webhooks:manage

Path parameters

  • endpoint integer Required

    The ID of the webhook endpoint.

    Example: 4

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Request bodyapplication/json

  • url string Required
    Format: uri Example: https://crm.example.com/worbo
  • description string
  • events string[] Required
  • payload string
    Possible values: snapshot thin

Responses

PATCH /webhook-endpoints/{endpoint}
curl -X PATCH "https://api.worbo.app/v1/webhook-endpoints/4" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://crm.example.com/worbo",
    "events": [
      "contact.created",
      "message.received"
    ],
    "payload": "snapshot"
  }'
{
  "data": {
    "id": 4,
    "url": "https://crm.example.com/worbo",
    "description": "string",
    "events": [
      "contact.created",
      "message.received"
    ],
    "payload": "snapshot",
    "enabled": true,
    "disabled_reason": "string",
    "failing_since": "2026-10-15T09:00:00+03:00",
    "last_success_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Delete a webhook endpoint#

DELETE /webhook-endpoints/{endpoint} Permission webhooks:manage

Path parameters

  • endpoint integer Required

    The ID of the webhook endpoint.

    Example: 4

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

DELETE /webhook-endpoints/{endpoint}
curl -X DELETE "https://api.worbo.app/v1/webhook-endpoints/4" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "id": 4,
    "deleted": true
  }
}

Rotate the signing secret of an endpoint#

POST /webhook-endpoints/{endpoint}/rotate Permission webhooks:manage

The previous secret stays valid for 24 hours; meanwhile, both signatures are sent.

Path parameters

  • endpoint integer Required

    The ID of the webhook endpoint.

    Example: 4

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

POST /webhook-endpoints/{endpoint}/rotate
curl -X POST "https://api.worbo.app/v1/webhook-endpoints/4/rotate" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "id": 4,
    "url": "https://crm.example.com/worbo",
    "description": "string",
    "events": [
      "contact.created",
      "message.received"
    ],
    "payload": "snapshot",
    "enabled": true,
    "disabled_reason": "string",
    "failing_since": "2026-10-15T09:00:00+03:00",
    "last_success_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00",
    "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
  }
}

List the deliveries of the events#

GET /webhook-deliveries Permission webhooks:manage

Query parameters

  • endpoint_id integer

    Only the deliveries to this endpoint.

    Example: 4
  • status string

    Only the deliveries with this status.

    Possible values: pending delivered failed
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /webhook-deliveries
curl "https://api.worbo.app/v1/webhook-deliveries" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "id": 9001,
      "endpoint_id": 4,
      "event": {
        "id": "msg_2mF0",
        "type": "contact.created"
      },
      "status": "delivered",
      "attempts": 1,
      "last_status": 200,
      "last_error": "string",
      "next_attempt_at": "2026-10-15T09:00:00+03:00",
      "delivered_at": "2026-10-15T09:00:00+03:00",
      "created_at": "2026-10-15T09:00:00+03:00"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

Send a delivery again#

POST /webhook-deliveries/{delivery}/replay Permission webhooks:manage

Path parameters

  • delivery integer Required

    The ID of the delivery.

    Example: 9001

Query parameters

  • dry_run boolean

    Runs every check and returns what would happen, without saving anything.

Headers

  • Idempotency-Key string

    A unique key of the request, such as a UUID: a repeated request with the same key gets the first response, without doing the work again.

    Max length: 255
  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

POST /webhook-deliveries/{delivery}/replay
curl -X POST "https://api.worbo.app/v1/webhook-deliveries/9001/replay" \
  -H "Authorization: Bearer $WORBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "id": 9001,
    "endpoint_id": 4,
    "event": {
      "id": "msg_2mF0",
      "type": "contact.created"
    },
    "status": "delivered",
    "attempts": 1,
    "last_status": 200,
    "last_error": "string",
    "next_attempt_at": "2026-10-15T09:00:00+03:00",
    "delivered_at": "2026-10-15T09:00:00+03:00",
    "created_at": "2026-10-15T09:00:00+03:00"
  }
}

Reference

Reports#

The results of a period and the conversions of the automations.

Read the results of a period#

GET /reports/results Permission analytics:read

The automations with the control group, the baseline, the value and the cost, in the days of the organization.

Query parameters

  • from string Required

    The first day of the period.

    Format: date Example: 2026-10-01
  • to string Required

    The last day of the period.

    Format: date Example: 2026-10-15
  • location_id integer

    Only the contacts of this home location.

    Example: 7

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /reports/results
curl "https://api.worbo.app/v1/reports/results" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": {
    "from": "2026-09-30T21:00:00+00:00",
    "to": "2026-10-15T20:59:59+00:00",
    "journeys": [
      {
        "id": 8,
        "name": "Recâștigare",
        "conversion": "string",
        "entered": 40,
        "converted": 6,
        "control": {},
        "value": 1194,
        "sent": 40,
        "clicked": 11,
        "cost": 2.18
      }
    ],
    "conversions": [
      {}
    ],
    "baseline": {},
    "cost": {
      "amount": 2.18,
      "currency": "EUR"
    },
    "value": 1194
  }
}

List the conversions of the automations#

GET /conversions Permission analytics:read

Query parameters

  • automation_id integer

    Only the conversions of this automation.

    Example: 8
  • since string

    Only what changed at or after this moment.

    Format: date-time Example: 2026-10-01T00:00:00+03:00
  • limit integer

    How many items a page has, between 1 and 100.

    Default: 25 Minimum: 1 Maximum: 100
  • cursor string

    The next_cursor of the previous page.

Headers

  • Worbo-Version string

    The API version, as a date; without it, the version of the key.

    Possible values: 2026-10-05

Responses

GET /conversions
curl "https://api.worbo.app/v1/conversions" \
  -H "Authorization: Bearer $WORBO_API_KEY"
{
  "data": [
    {
      "run_id": 3301,
      "automation_id": 8,
      "contact_id": 123,
      "object_id": 1,
      "held_out": false,
      "converted_at": "2026-10-15T09:00:00+03:00",
      "event_id": 1,
      "value": 199,
      "currency": "RON"
    }
  ],
  "next_cursor": "string",
  "has_more": true
}

The key stays only in this browser tab and is sent only to the Worbo API. With a wk_test_ key, every write is a dry run.

Send the request to see the response.