Skip to main content
Webhooks tell your server when something happens instead of making you poll. Each team sets up its own endpoints, and each endpoint belongs to one environment: production or sandbox.

Setting up an endpoint

Switch to the team, then open Settings → Webhooks. Owners, admins and developers see it when the team has API access. Endpoints from both environments are listed together, each labelled Production or Sandbox. A team can have up to 10 endpoints in each environment. Two endpoints in Settings, one labelled Production and one Sandbox, each with its URL, the events it receives, and its auth shown by the last four characters Add endpoint asks for:
  • the environment, Production or Sandbox (it can’t be changed later),
  • an HTTPS URL that resolves to a public address,
  • the events to receive,
  • optional auth, sent on every delivery alongside the signature (see below).
A URL whose host does not resolve, or resolves to an address that is not public, is refused with “Could not reach this URL from OmniChar”. The same answer covers both cases, so the check can’t be used to probe a private network. After you add it, its signing secret is shown once. Copy it into your server’s configuration; you won’t see it again. Test before saving sends a sample event to the URL first, so you can check it and its auth before the endpoint exists. The New endpoint dialog with Production picked as the environment, an HTTPS URL, all seven events checked, a bearer token, and a test sent before saving that was delivered with HTTP 200 Each endpoint can be edited, disabled, enabled or deleted. Delivery log lists its last 50 attempts with the event, the response code, the number of attempts and the time, and a failed delivery that is not a test can be sent again with Retry. The delivery log of an endpoint: a test char.ready delivered, a char.ready that failed with HTTP 503 after 12 attempts with a Retry button, and a delivered license.issued The same operations are available to a team key with the webhooks:read and webhooks:write scopes, under /v1/teams/{team_id}/webhooks. A key manages endpoints in its own environment only. Each call is listed in the API reference.

Endpoint auth

The signature is always sent. If your endpoint also expects its own credentials, choose one: Credentials are stored encrypted and never shown again. For a credential of 12 characters or more the page shows its last four; editing the endpoint offers Replace. If you change the URL, the page asks for the auth again or None, so a credential is never sent to a host it wasn’t set for. Through the API, a change of host without new auth is refused. A custom header cannot be one OmniChar sets itself (OmniChar-Signature, OmniChar-Event-Id, Content-Type, Content-Length, Host, User-Agent) or a transport header (Transfer-Encoding, Connection, Keep-Alive, TE, Trailer, Upgrade, Expect, Proxy-Authorization, Proxy-Connection).

Testing an endpoint

Send test on an endpoint sends a sample of the event you pick, signed and with the endpoint’s auth, through the same path as a real delivery. The result shows the HTTP status, the response time, the first 1 KB of the answer, and the reason when it failed: a timeout, a TLS error, or “Could not reach this URL from OmniChar”, which covers both a host that does not resolve and an address that is not public. Test deliveries are labelled test in the log and are never retried. You can send 10 tests a minute per team.

Rotating a signing secret

Rotate secret gives the endpoint a new secret, shown once. For the next 24 hours every delivery is signed with both the new and the old secret, so you can switch your server over without missing an event. The documented signature check accepts either.

Events

license.issued, license.revoked and license.expired go to both teams: the provider that issued the license and the licensee that holds it. A license waiting on an email with no account has no licensee yet, so only the provider hears about it until that person signs up. Then the licensee gets license.issued and the provider gets license.updated. If you created a character with a callback_url, its char.* events are also sent there, signed with your team’s default secret for that environment. Ask us for that secret; we can rotate it for you the same way, with a 24-hour overlap.

Payload

data is the same object GET /v1/chars/{id} returns, or for license events, the license as GET /v1/licenses returns it. Each request carries two headers: Verify the signature before acting on an event.

Delivery and retries

  • We POST JSON and wait up to 10 seconds. Any 2xx answer is a success.
  • Anything else, including a timeout, is retried after 30 seconds, then 1, 2, 4 minutes and so on, never more than an hour apart, for 24 hours. After that the delivery is marked as given up.
  • Redirects are not followed. The URL must be HTTPS and must resolve to a public address.
Delivery is at least once: the same event can arrive twice, for example after a timeout. Deduplicate on OmniChar-Event-Id.

Sending a test event

POST /v1/webhooks/test sends a sample event to all your sandbox endpoints at once. It works with sandbox keys that have the webhooks:write scope.
A test event’s data carries "test": true.