Docs

Start here

Register an endpoint

POST/v1/webhookson https://api.auray.ai/v1

Sends one signed challenge to the URL.

Sends one signed challenge to the URL. The endpoint switches on only if it answers 200 with the nonce we sent — which is why registering somebody else's URL cannot make us send them anything. The challenge names the registering account in account, inside what the signature covers, so a receiver echoes the nonce only for its own account. 201 even when the challenge fails: the endpoint exists, it is simply not switched on.

#Authentication

Authorization: Bearer auray_sk_… — webhooks:write.

#Request

#Body

application/json, required.

FieldTypeRequiredDefaultDescription
urlstringyes—https only, public host, no credentials. A URL.
productsstring[]no—Empty or omitted means every product.

#Example request

curl -X POST https://api.auray.ai/v1/webhooks \
  -H "Authorization: Bearer $AURAY_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "url": "https://example.com/hooks/auray"
}'

#Responses

#201 Created

Registered.

FieldTypeRequiredDefaultDescription
idstringno—
objectstringno—One of "webhook".
urlstringno—A URL.
productsstring[]no—
statusstringno—active if the challenge succeeded just now, pending if it did not. One of "pending", "active".
verifiedbooleanno—
verify_keysstringno—Where the public keys that sign your deliveries are published. Fetch it, cache it, and look up the kid each Auray-Signature names. A URL rather than a key, because a copy handed back here would go stale the moment one is rotated — and free rotation is the point of the scheme. A URL.
signature_algorithmstringno—How Auray-Signature is signed: Ed25519 over <t>.<raw body>, the header reading t=…,v2=…,kid=…. THERE IS NO SHARED SECRET — this response used to return secret (whsec_…) for an HMAC scheme, and the same bytes that verified a delivery could forge one. The private half of this key never leaves the deployment. One key signs for every account, so the body names who it is for, inside what the signature covers: account (your account id, the id GET /v1/me returns) and webhook_id (the endpoint, or null for a per-request ?webhook). Compare account with yours and refuse anything else. One of "EdDSA".
created_atstringno—
verificationobjectno—Present ONLY when the challenge failed — and the response is still a success, because the endpoint was registered; it is your server that did not answer.
verification.failedstringno—Which check failed.
verification.statusintegerno—The HTTP status your endpoint answered with, if it answered. May be null.
verification.responsestringno—The first bytes of what it said. May be null.
verification.howstringno—What to do about it, including the id to retry against.
request_idstringno—Mirrored in the X-Request-Id header.

Headers:

HeaderDescription
RateLimit-LimitBurst capacity.
RateLimit-Remaining
RateLimit-ResetSeconds until refill.
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-ResetUnix seconds. The X- spelling is what client libraries read.
X-Request-Id

#400 Bad Request

#401 Unauthorized

#403 Forbidden

#409 Conflict

#413 Payload Too Large

#429 Too Many Requests

#500 Internal Server Error

#503 Service Unavailable

#Status codes

StatusMeaning
201Registered.
400Bad Request
401Unauthorized
403Forbidden
409Conflict
413Payload Too Large
429Too Many Requests
500Internal Server Error
503Service Unavailable

Every refusal names its code, and every code is explained at Errors.

Start typing to search every page of the documentation.

Up arrow Down arrow to moveEnter to openEscape to close