Skip to content

Build a plugin

A plugin is an HTTPS endpoint that receives signed events from RolChat, plus optional calls it makes back into RolChat. There is no code to upload and no runtime to host inside RolChat.

In Settings → Plugins → Catalogue → Custom, or with the API:

POST /api/v1/plugins
Authorization: Bearer rcp_…
X-Account-Id: <account uuid>
{
"plugin_type": "custom",
"name": "Acme back office",
"api_key_external": "<key RolChat should use to call you, optional>",
"webhook_url_outbound": "https://backoffice.acme.com/rolchat",
"sync_config": {
"enrich_contacts": true,
"enrich_companies": true,
"sync_agent_schedule": false,
"create_contacts": false
}
}

The response contains the plugin ID and the webhook secret, shown once. Store it; every event RolChat sends is signed with it, and every event you send to RolChat must be too.

RolChat posts to webhook_url_outbound when things change:

Event When
chats.conversation.created A conversation starts
crm.contact.created A contact is created
crm.contact.updated A contact changes
tickets.ticket.created A ticket is created
tickets.ticket.status_changed A ticket moves
marketing.meeting.booked A meeting is booked
marketing.meeting.cancelled A meeting is cancelled
{
"event": "crm.contact.created",
"account_id": "…",
"plugin_id": "…",
"timestamp": "2026-04-13T14:32:00Z",
"data": { … }
}

Verify the signature, freshness and nonce exactly as described in Webhooks, answer 200 quickly, and deduplicate by event ID. The broader event families available to subscriptions are in the event catalogue.

Post to your plugin’s inbound endpoint, signed with the same secret:

POST /api/v1/webhooks/plugin/{plugin_id}
Content-Type: application/json
X-RolChat-Timestamp: 1713615825
X-RolChat-Signature: sha256=…
X-RolChat-Nonce: nonce_01HK…
{
"event": "contact.data_updated",
"timestamp": "2026-04-13T14:32:00Z",
"data": {
"external_id": "acme_user_123",
"email": "user@company.com",
"plugin_data": { "role": "Admin", "registered_at": "2024-03-15", "last_login": "2026-04-11" }
}
}

Response: { "received": true, "matched_contact_id": "…" }.

Inbound event What RolChat does
contact.data_updated Stores plugin_data on the matching contact
company.data_updated Stores plugin_data on the matching company
contact.created_external Creates or updates a contact
agent.unavailable Runs the booking form’s unavailability strategy (cancel, reassign, offer a new slot)
agent.available Notifies the agent about pending meetings

Matching. RolChat looks the contact up by e-mail first, then by the external_id your plugin stored earlier. Not found: a lead is created if sync_config.create_contacts is on, otherwise the event is logged as unmatched.

Contact and company cards show a section named after your plugin with the fields you sent, read-only, with the time of the last update. The same data is returned by the API:

GET /api/v1/contacts/{id}
{
"data": {
"id": "…",
"plugin_data": {
"{plugin_id}": { "plugin_name": "Acme back office", "updated_at": "…", "data": { … } }
}
}
}

Automation conditions can test plugin data, so a rule can route a conversation by the customer’s plan in your system.

GET /api/v1/plugins connected plugins
GET /api/v1/plugins/catalog catalogue
POST /api/v1/plugins connect
GET /api/v1/plugins/{id} details
PATCH /api/v1/plugins/{id} settings
DELETE /api/v1/plugins/{id} remove
POST /api/v1/plugins/{id}/activate activate
POST /api/v1/plugins/{id}/deactivate pause
POST /api/v1/plugins/{id}/test test the external key
POST /api/v1/plugins/{id}/webhook-secret/rotate rotate with a 7-day overlap
POST /api/v1/plugins/{id}/webhook-secret/revoke revoke immediately
GET /api/v1/plugins/{id}/events event log (direction, status, type, dates, cursor)
GET /api/v1/plugins/{id}/sync-schedule schedule and last run
PATCH /api/v1/plugins/{id}/sync-schedule { enabled, cron, timezone }
POST /api/v1/plugins/{id}/sync-schedule/trigger run now (one per 5 minutes)

A published plugin declares itself in a manifest: name, category, the scopes it requests, the events it subscribes to, its settings form, optional allowed_source_ips, recommended_rotation_days, and its pricing if paid. The manifest drives the connect screen and the review before a community plugin is listed.

  • Inbound body up to 5 MB; outbound 1 MB by default.
  • Plugin API keys are limited to 300 requests per minute; inbound webhooks to 120 per minute per plugin.
  • Sustained delivery failures mark a plugin degraded; more than half failing for an hour pauses it and notifies the account admins.
  • Never log or echo the webhook secret. Rotate it if you suspect exposure; the overlap window means nothing breaks.