Organization Webhooks

Register a webhook endpoint

POST
/api/v1/webhook-endpoints

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.

Authorization

ApiKeyAuth webhooks:manage
headerAuthorizationBearer <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

Header Parameters

Idempotency-Key*string

Caller-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.

Lengthlength <= 64

Request Body

application/json
  1. body
url*string

https URL; private and internal addresses are refused.

Lengthlength <= 2048
eventTypes*array<string>

Names from the webhook catalog (order.created, ...).

Items1 <= items
description?string
Lengthlength <= 200

Response Body

The new endpoint with its signing secret.

application/json
  1. response

The endpoint as POST /webhook-endpoints answers it, with the signing secret (shown only here).

id*string
url*string
description*string|null
eventTypes*array<string>

Names from the webhook catalog.

mode*string

The mode of the key that created the endpoint; it only receives events of businesses of the same mode.

Value in"live""test"
enabled*boolean
disabledReason*|

FAILURES = switched off after repeated failed deliveries, OWNER = switched off through the API.

Value in"FAILURES""OWNER"null
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
secret*string

whsec_... - verify Shyni-Signature with it, exactly as shown. Not retrievable later.

Example Request
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."}