Register a webhook endpoint
Registers a webhook endpoint of the organization. It receives the events of every business the organization owns
or has access to whose mode equals the mode of the calling key (see Webhooks), each with its businessId. url
must be https and must not point to a private or internal address; eventTypes are names from the webhook
catalog. The signing secret (secret) is in this response and nowhere else: a replay of the same request
(same Idempotency-Key) repeats it, no read does. Up to 5 endpoints per organization (409 CONFLICT). Audited
with the API key as the actor. Org-level: send no Shyni-Business header. Requires the webhooks:manage
scope and an Idempotency-Key header.
ApiKeyAuth webhooks:manageAuthorizationBearer <shyni_sk_live_*>An API key, issued once and never retrievable again: an organization key in the developer
portal, or a studio key in the studio's admin (Moje studio → API). Send as Authorization: Bearer shyni_sk_live_....
Scope: webhooks:manage
Idempotency-Key*stringCaller-chosen idempotency token for this write. A retry under the SAME key with
the SAME body replays the first response; the SAME key with a DIFFERENT body is
422 IDEMPOTENCY_KEY_MISMATCH. See Idempotency above.
length <= 64application/json- body
url*stringhttps URL; private and internal addresses are refused.
length <= 2048eventTypes*array<string>Names from the webhook catalog (order.created, ...).
1 <= itemsdescription?stringlength <= 200The new endpoint with its signing secret.
application/json- response
The endpoint as POST /webhook-endpoints answers it, with the signing secret (shown only here).
id*stringurl*stringdescription*string|nulleventTypes*array<string>Names from the webhook catalog.
mode*stringThe mode of the key that created the endpoint; it only receives events of businesses of the same mode.
"live""test"enabled*booleandisabledReason*|FAILURES = switched off after repeated failed deliveries, OWNER = switched off through the API.
"FAILURES""OWNER"nullcreatedAt*stringdate-timeupdatedAt*stringdate-timesecret*stringwhsec_... - verify Shyni-Signature with it, exactly as shown. Not retrievable later.
curl -X POST 'https://api.shyni.io/api/v1/webhook-endpoints' \ -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY' \ -H 'Idempotency-Key: 7f3c9a52-1d4e-4b86-a0c7-5e2b9d8f6a13' \ -H 'Content-Type: application/json' \ -d '{ "url": "string", "eventTypes": [ "string" ]}'Response 201
The new endpoint with its signing secret.
{ "id": "string", "url": "string", "description": "string", "eventTypes": [ "string" ], "mode": "live", "enabled": true, "disabledReason": "FAILURES", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "secret": "string"}Response 400
A parameter, header or request body is missing, malformed, or out of range. A request body property the endpoint does not define answers UNKNOWN_FIELD instead, with field naming it.
{ "code": "INVALID_INPUT", "message": "Parameter perPage must be between 1 and 100."}Response 401
Missing, malformed, unknown, or revoked API key (INVALID_API_KEY).
{ "code": "INVALID_API_KEY", "message": "Missing or invalid API key."}Response 403
The key is valid but the request is refused. Branch on code: INSUFFICIENT_SCOPE (the key lacks the
permission this endpoint requires), PLAN_REQUIRED (the studio is not on a plan that includes API keys,
Pro and above), ORIGIN_NOT_ALLOWED, SECRET_KEY_IN_BROWSER, or DEMO_STUDIO on a write to the demo studio.
See Authentication and Scopes above.
{ "code": "INSUFFICIENT_SCOPE", "message": "This API key does not have the permission this endpoint requires."}Response 409
The request is well-formed but the studio's current state forbids it.
{ "code": "CONFLICT", "message": "The voucher cannot be deactivated because it is not active."}Response 422
The same Idempotency-Key was already used for a request with a different body, use a new key (see Idempotency above).
{ "code": "IDEMPOTENCY_KEY_MISMATCH", "message": "This Idempotency-Key was already used for a different request. Use a new key."}Response 429
Burst rate limit exceeded.
{ "code": "RATE_LIMITED", "message": "Too many requests. Retry after the time given in the Retry-After header."}