Docs · Account

Clients and portals (Agency).

The Agency tier turns Ciela into the operating layer for your client roster. Add each client you've sold a Library agent to, drop the per-client webhook URL into their n8n flow or Vapi assistant, and watch performance roll up automatically. Each client also gets a public branded portal at /portal/{slug} so they can see the ROI you're delivering without you having to assemble a deck every month.

Quick facts

Plan
Agency tier only
Per-client URL
/api/agent-callback/{slug}, 16 hex chars
Per-client secret
48 hex chars, sent as X-Webhook-Secret
Public portal
/portal/{slug}, read-only, no login
Idempotency
Send external_id and retries collapse to one row

Model

Three concepts to keep straight:

  • ClientAn end client of your agency, not a Ciela user. They never log in. You add them at /dashboard/clients with their name, primary contact, and monthly retainer. The server mints a unique slug + webhook secret for them on creation.
  • DeploymentOne Library agent you've installed for this client. Receptionist, lead reactivation, quote generator, missed-call text-back, or custom. The deployment is your bookkeeping record, the agent itself runs in the client's n8n + Vapi (not in Ciela). Status flips between live, paused, retired.
  • EventA performance datapoint POSTed by a deployed agent. Call answered, lead captured, appointment booked, message sent, message received, quote sent, or custom. Optional value_cents for revenue events drives the ROI rollup.

Walkthrough

01

Add the client

Click Add client at /dashboard/clients. Name is required. Primary contact, contact email, and monthly retainer are optional, all editable later.

On save you land on the detail page where the unique POST URL and webhook secret are already provisioned and visible. Copy both. Treat the secret like any production credential, if it leaks, delete the client and re-add to rotate.

02

Record the deployments

For every Library agent you install in this client's infrastructure, hit Record deployment. Pick the agent type, give it a name your client will recognize (eg "Acme Front Desk"), and add any setup notes (Vapi assistant id, n8n flow URL, GHL pipeline id) you want to find again later.

Deployments are pure bookkeeping, you can ship the agent to the client either way, but logging it here lets events attribute to a specific install on the rollup and the portal. If you retire an agent, set its status to retired rather than deleting, so historical metrics keep their attribution.

03

Wire the webhook into n8n + Vapi

In the deployed flow (n8n HTTP Request node, Vapi tool, or any other runtime), add a step that POSTs to the client-specific URL with the secret in the X-Webhook-Secret header. Wire it to fire on whatever moments matter for the agent: every call completed, every booking confirmed, every lead written to the CRM.

Minimum body:

POST /api/agent-callback/<slug>
X-Webhook-Secret: <secret>
Content-Type: application/json

{
  "event_type": "appointment_booked",
  "deployment_id": "<optional, from /dashboard/clients/[id]>",
  "external_id": "<optional, your idempotency key>",
  "value_cents": 20000,
  "metadata": { "customer": "Jane", "service": "Cleaning" }
}

Send external_id if the runtime might retry (n8n's retry-on-fail, Vapi tool retries). Duplicate POSTs with the same external_id return { ok: true, duplicate: true } and collapse to one row, so you never double-count.

Send deployment_id to attribute the event to a specific agent install. Useful when one client has two receptionists running side by side, otherwise leave it null and the event still rolls up at the client level.

04

Watch metrics roll up

Back at /dashboard/clients the topline shows active clients, MRR across active retainers, and total events in the last 30 days. Each client row shows their own 30-day event count and live deployments.

Open a client to see the per-type breakdown, the latest events with metadata, attributed value (sum of value_cents), and the deployment list with per-agent statuses you can flip in place.

05

Share the branded portal

Hit Open client portal on the detail page, or send your client the URL at /portal/{slug}. It's public, read-only, no login. They see the last 30 days of events, the agents running for them, recent activity, and any attributed revenue.

Ciela's brand is nowhere on the portal. It renders under your agency's brand fields (name, logo, color) from your profile, with per-client logo and color overrides if you set them. Set yours under your account settings before sending the first portal link.

Event types

  • call_answeredAgent picked up an inbound call (Vapi assistant or n8n handoff).
  • call_completedCall wrapped up. Use this for end-of-call metrics if your runtime distinguishes pick-up from completion.
  • lead_capturedA new lead got written to the CRM. Add metadata to identify source (form, missed-call recovery, etc.).
  • appointment_bookedCalendar event created. Add value_cents if you want it to show in the ROI rollup.
  • message_sentOutbound text or chat message dispatched by the deployed agent.
  • message_receivedInbound message handled by the deployed agent.
  • quote_sentQuote / estimate delivered to a prospect. value_cents = the quoted amount if you want to track pipeline.
  • customAnything else. Put a descriptive label in metadata so the activity feed reads sensibly.

Per-client URL + secret model

Every client gets a separate slug + secret. Compromising one client's secret does not affect any other client. Posting to client A's URL with client B's secret returns 404, indistinguishable from a typo on the slug, so blind guessing yields no signal.

Slugs are 16 hex chars, secrets are 48 hex chars, both generated server-side at creation time and stored on the client row. They don't expire. If a secret leaks today the fastest recovery is to delete the client (which cascades deployments + events) and re-add, both URL and secret regenerate. A dedicated "Rotate secret" button is on the roadmap once enough usage justifies it.

Privacy notes for the portal

  • What the client seesTheir name, your agency brand, aggregate counts by event type, attributed value, the deployments running for them, and per-event metadata you chose to send. Nothing about your other clients, nothing about your retainer.
  • Metadata is visibleAnything you put in the metadata object on the webhook event shows up on the portal feed. Don't post PII you don't want the client to see. The portal is effectively a public URL guarded only by the slug's non-enumerability.
  • AuthenticationNone. The slug is the secret. Treat the portal URL like a shared Google Doc link, share it deliberately. If you need to revoke a portal you delete the client (or wait for the planned slug-rotation feature).

Common failure modes

401 Missing X-Webhook-Secret: the runtime sent the POST without the header. Some no-code tools strip custom headers, in that case put the secret in the JSON body as "secret" instead.

404 Not found: slug or secret is wrong. We collapse "wrong slug" and "wrong secret" into the same response so attackers can't tell which factor failed. Copy both fresh from the client detail page.

400 Invalid event_type: the body did not include one of the eight allowed values. Use custom for anything that doesn't fit.

No events showing up: confirm the POST returned { ok: true } in the runtime's logs. Successful posts always include an event_id in the response. If you see duplicate: true, that event already landed under the same external_id.

Need help?

Stuck wiring the webhook from n8n or Vapi? Ask Ciela for a copy-paste config for your specific stack, or write to support@ciela.ai and we'll jump on the connection with you.

Ask Ciela

Keep reading