Five-minute webhook quickstart
Receive a signed webhook in five minutes
You need an Oway bearer token, a company API key (oway_sk_... or oway_ck_...), curl, jq,
and a public HTTPS receiver. Signed-in portal users are scoped through their membership, but
external API clients send both credentials. Keep the raw request body; serializing parsed JSON
again will change the signature input.
1. Start a receiver
Create a route that accepts POST, reads the body as bytes, and captures these headers:
webhook-id
webhook-timestamp
webhook-signatureUse one of the executable verification examples in
Verify webhook signatures. Verify first, deduplicate the parsed event_id
second, enqueue your work third, and return 204 immediately.
2. Inspect your available events
export OWAY_API_TOKEN='replace-with-your-token'
export OWAY_COMPANY_API_KEY='replace-with-your-company-key'
curl --fail-with-body \
--header "Authorization: Bearer $OWAY_API_TOKEN" \
--header "x-oway-api-key: $OWAY_COMPANY_API_KEY" \
https://api.oway.io/v1/webhooks/catalog | jqThe catalog is audience-aware. Do not hardcode event names that are absent from this response.
3. Create an endpoint
export RECEIVER_URL='https://webhooks.example.com/oway'
ENDPOINT_RESPONSE="$(curl --fail-with-body \
--request POST \
--header "Authorization: Bearer $OWAY_API_TOKEN" \
--header "x-oway-api-key: $OWAY_COMPANY_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: endpoint-$(date +%s)" \
--data "$(jq -n \
--arg url "$RECEIVER_URL" \
'{url:$url,description:"Oway production",event_types:["shipment.delivered"]}')" \
https://api.oway.io/v1/webhooks/endpoints)"
printf '%s\n' "$ENDPOINT_RESPONSE" | jq '.endpoint | {id}'
export OWAY_WEBHOOK_SECRET="$(jq -r .secret <<<"$ENDPOINT_RESPONSE")"
export OWAY_ENDPOINT_ID="$(jq -r .endpoint.id <<<"$ENDPOINT_RESPONSE")"
unset ENDPOINT_RESPONSEMove OWAY_WEBHOOK_SECRET to your secret manager now. It appears only in this response. Do not
write the response or your shell environment to a shared file.
4. Send a real signed test
curl --fail-with-body \
--request POST \
--header "Authorization: Bearer $OWAY_API_TOKEN" \
--header "x-oway-api-key: $OWAY_COMPANY_API_KEY" \
--header "Idempotency-Key: test-$(date +%s)" \
"https://api.oway.io/v1/webhooks/endpoints/$OWAY_ENDPOINT_ID/test" | jqThe response is 202 Accepted because the test goes through the normal asynchronous delivery
path. Your receiver should verify it and return 2xx.
5. Confirm the attempt
curl --fail-with-body \
--header "Authorization: Bearer $OWAY_API_TOKEN" \
--header "x-oway-api-key: $OWAY_COMPANY_API_KEY" \
--get \
--data-urlencode "endpoint_id=$OWAY_ENDPOINT_ID" \
--data-urlencode "limit=10" \
https://api.oway.io/v1/webhooks/deliveries | jqA successful test reaches succeeded with a succeeded attempt. If it does not, use the delivery
ID with GET /v1/webhooks/deliveries/{delivery_id} and follow
Troubleshooting.
Updated about 3 hours ago