Skip to main content

Webhook Configuration

Learn how to configure webhooks for your OrcaRail API keys to receive real-time payment notifications.

Overview​

Webhooks in OrcaRail are configured at the API key level. Each API key can have its own webhook URL, allowing you to:

  • Send different events to different endpoints
  • Use separate webhooks for different environments (development, staging, production)
  • Test webhooks independently for each API key

Setting Up Webhooks​

Step 1: Create or Update an API Key​

Webhooks are configured when creating or updating an API key. You can set a webhookUrl parameter:

Creating an API Key with Webhook URL​

POST /api/v1/organizations/:organizationId/api-keys
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

Replace :organizationId with the organization you want to manage. You can find it in Dashboard → Organization Settings, or by calling your organizations list endpoint and copying the id of the organization you want to use. The bearer token must belong to a user/session that can manage that same organization.

Request Body:

{
"name": "Production API Key",
"webhookUrl": "https://api.example.com/webhooks/orcarail"
}

Response:

{
"apiKey": {
"id": 1,
"name": "Production API Key",
"keyPrefix": "ak_live_",
"status": "active",
"webhookUrl": "https://api.example.com/webhooks/orcarail",
"createdAt": "2024-01-01T00:00:00.000Z"
},
"key": "ak_live_abc123def456",
"secret": "sk_live_xyz789uvw012"
}

Updating an API Key's Webhook URL​

You can update the webhook URL for an existing API key:

PATCH /api/v1/api-keys/:id
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

Request Body:

{
"webhookUrl": "https://api.example.com/webhooks/orcarail"
}

Response:

{
"id": 1,
"name": "Production API Key",
"keyPrefix": "ak_live_",
"status": "active",
"webhookUrl": "https://api.example.com/webhooks/orcarail",
"updatedAt": "2024-01-01T12:00:00.000Z"
}

Step 2: Webhook URL Requirements​

Your webhook URL must meet these requirements:

  • HTTPS - Required in production (HTTP allowed for local development)
  • Publicly accessible - OrcaRail must be able to reach it from the internet
  • Valid HTTP endpoint - Must accept POST requests
  • Fast response - Should return 200 OK within 10 seconds (timeout is 10 seconds)

Step 3: Remove Webhook URL​

To stop receiving webhooks for an API key, set webhookUrl to null:

PATCH /api/v1/api-keys/:id
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

Request Body:

{
"webhookUrl": null
}

Code Examples​

JavaScript/TypeScript​

// Create API key with webhook URL
const response = await fetch(
'https://api.orcarail.com/api/v1/organizations/org_123/api-keys',
{
method: 'POST',
headers: {
Authorization: `Bearer ${jwtToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Production API Key',
webhookUrl: 'https://api.example.com/webhooks/orcarail',
}),
}
)

const { apiKey, key, secret } = await response.json()
console.log('API Key created:', key)
console.log('Webhook URL:', apiKey.webhookUrl)

// Update webhook URL
const updateResponse = await fetch(
`https://api.orcarail.com/api/v1/api-keys/${apiKey.id}`,
{
method: 'PATCH',
headers: {
Authorization: `Bearer ${jwtToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
webhookUrl: 'https://api.example.com/webhooks/orcarail-v2',
}),
}
)

Python​

import requests

# Create API key with webhook URL
response = requests.post(
'https://api.orcarail.com/api/v1/organizations/org_123/api-keys',
headers={
'Authorization': f'Bearer {jwt_token}',
'Content-Type': 'application/json',
},
json={
'name': 'Production API Key',
'webhookUrl': 'https://api.example.com/webhooks/orcarail',
},
)

data = response.json()
api_key = data['apiKey']
print(f"API Key created: {data['key']}")
print(f"Webhook URL: {api_key['webhookUrl']}")

# Update webhook URL
update_response = requests.patch(
f"https://api.orcarail.com/api/v1/api-keys/{api_key['id']}",
headers={
'Authorization': f'Bearer {jwt_token}',
'Content-Type': 'application/json',
},
json={
'webhookUrl': 'https://api.example.com/webhooks/orcarail-v2',
},
)

cURL​

# Create API key with webhook URL
curl -X POST https://api.orcarail.com/api/v1/organizations/org_123/api-keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production API Key",
"webhookUrl": "https://api.example.com/webhooks/orcarail"
}'

# Update webhook URL
curl -X PATCH https://api.orcarail.com/api/v1/api-keys/1 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": "https://api.example.com/webhooks/orcarail-v2"
}'

Testing Your Webhook Configuration​

Using the Test Webhook Endpoint​

OrcaRail provides endpoints to test your webhook configuration:

Send Test Webhook​

Sends a test payment_intent.completed event to your configured webhook URL:

POST /api/v1/webhooks/test/:apiKeyId
Authorization: Bearer YOUR_JWT_TOKEN

Response:

{
"success": true
}

Example:

const response = await fetch(
'https://api.orcarail.com/api/v1/webhooks/test/1',
{
method: 'POST',
headers: {
Authorization: `Bearer ${jwtToken}`,
},
}
)

const result = await response.json()
console.log('Test webhook sent:', result.success)

Send Custom Webhook​

Send a custom payload to test your webhook handler:

POST /api/v1/webhooks/test/:apiKeyId/custom
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

Request Body:

{
"payload": {
"type": "payment_intent.completed",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"amount": "100.00",
"currency": "usd",
"status": "succeeded"
}
}
}
}

Response:

{
"success": true
}

Viewing Webhook Logs​

Check the delivery status of your webhooks:

GET /api/v1/webhooks/logs?limit=50&offset=0
Authorization: Bearer YOUR_JWT_TOKEN

Query Parameters:

ParameterTypeDefaultDescription
limitnumber50Number of logs to return
offsetnumber0Number of logs to skip

Response:

{
"logs": [
{
"id": 1,
"apiKeyId": 1,
"event": "payment_intent.completed",
"url": "https://api.example.com/webhooks/orcarail",
"statusCode": 200,
"success": true,
"attemptNumber": 1,
"createdAt": "2024-01-01T00:00:00.000Z"
}
],
"total": 1
}

Example:

const response = await fetch(
'https://api.orcarail.com/api/v1/webhooks/logs?limit=10&offset=0',
{
headers: {
Authorization: `Bearer ${jwtToken}`,
},
}
)

const { logs, total } = await response.json()
console.log(`Found ${total} webhook logs`)
logs.forEach((log) => {
console.log(`${log.event}: ${log.success ? 'Success' : 'Failed'}`)
})

Best Practices​

1. Use Different Webhooks for Different Environments​

Create separate API keys with different webhook URLs for each environment:

// Development
{
name: "Development API Key",
webhookUrl: "https://dev.example.com/webhooks/orcarail"
}

// Staging
{
name: "Staging API Key",
webhookUrl: "https://staging.example.com/webhooks/orcarail"
}

// Production
{
name: "Production API Key",
webhookUrl: "https://api.example.com/webhooks/orcarail"
}

2. Test Before Production​

Always test your webhook endpoint before using it in production:

  1. Use the test webhook endpoint to verify your handler works
  2. Check webhook logs to ensure successful delivery
  3. Verify signature validation is working correctly

3. Monitor Webhook Delivery​

Regularly check webhook logs to ensure:

  • Webhooks are being delivered successfully
  • Response times are acceptable
  • No errors are occurring

4. Handle Webhook Failures​

OrcaRail will retry failed webhooks automatically:

  • Maximum attempts: 3 attempts (1 initial + 2 retries)
  • Backoff strategy: Exponential backoff starting at 2 seconds
  • Timeout: 10 seconds per request

Ensure your webhook endpoint can handle retries gracefully (make handlers idempotent).

5. Use ngrok for Local Development​

For local development, use ngrok to expose your local server:

# Install ngrok
npm install -g ngrok

# Expose local server
ngrok http 3000

Then configure your webhook URL to the ngrok URL:

https://abc123.ngrok.io/webhooks/orcarail

Troubleshooting​

Webhook Not Receiving Events​

  1. Check API Key Status - Ensure your API key is active
  2. Verify Webhook URL - Confirm the URL is correctly configured
  3. Check Webhook Logs - Review logs for delivery errors
  4. Test Webhook - Use the test endpoint to verify connectivity

Webhook Returns 404​

  • Verify your webhook endpoint exists and accepts POST requests
  • Check that the URL path is correct
  • Ensure your server is running and accessible

Webhook Returns 500​

  • Check your server logs for errors
  • Verify your webhook handler doesn't throw exceptions
  • Ensure you're returning 200 OK even if processing fails

Signature Verification Fails​

  • Verify you're using the correct secret (from the API key)
  • Ensure you're computing the signature correctly
  • Check that you're using the raw request body (not parsed JSON)

Next Steps​