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