Webhooks
Webhooks provide real-time notifications when events occur in your Proxy account. Configure endpoints to receive HTTP POST requests for events you care about.
Setting Up Webhooks
Create a Webhook Endpoint
curl -X POST https://api.useproxy.ai/v1/webhooks \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/proxy",
"events": ["transaction.created", "intent.matched"],
"description": "Production webhook"
}'
Webhook Fields
Field Type Description urlstring HTTPS endpoint to receive events eventsarray List of event types to subscribe to descriptionstring Human-readable description statusstring active or disabled
Event Types
Transaction Events
Event Description transaction.createdNew transaction recorded transaction.settledTransaction settled transaction.declinedTransaction was declined
Intent Events
Event Description intent.createdNew intent declared intent.matchedIntent matched to transaction intent.mismatchedTransaction didn’t match intent intent.expiredIntent expired intent.pending_approvalIntent awaiting approval
Card Events
Event Description card.createdNew card issued card.frozenCard was frozen card.closedCard was closed
Webhook Payload
{
"id" : "evt_xxx" ,
"type" : "transaction.created" ,
"createdAt" : "2024-01-15T10:30:00Z" ,
"data" : {
"transactionId" : "txn_xxx" ,
"cardId" : "card_xxx" ,
"amount" : 5000 ,
"merchant" : "Amazon"
}
}
Signature Verification
All webhooks include a Proxy-Signature header for verification. The header format is:
Proxy-Signature: t=1706745600,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Where:
t is the Unix timestamp (seconds) when the webhook was sent
v1 is the HMAC-SHA256 signature
The signature is computed over {timestamp}.{json_payload} using your webhook secret.
Node.js Example
const crypto = require ( 'crypto' );
function verifyWebhook ( req , secret ) {
const signature = req . headers [ 'proxy-signature' ];
const payload = JSON . stringify ( req . body );
// Parse the signature header
const parts = signature . split ( ',' );
const timestamp = parts [ 0 ]. split ( '=' )[ 1 ];
const receivedSig = parts [ 1 ]. split ( '=' )[ 1 ];
// Compute expected signature
const signedPayload = ` ${ timestamp } . ${ payload } ` ;
const expectedSig = crypto
. createHmac ( 'sha256' , secret )
. update ( signedPayload )
. digest ( 'hex' );
// Compare signatures (use timing-safe comparison)
return crypto . timingSafeEqual (
Buffer . from ( receivedSig ),
Buffer . from ( expectedSig )
);
}
// Express.js handler example
app . post ( '/webhooks/proxy' , express . json (), ( req , res ) => {
const secret = 'whsec_your_webhook_secret' ;
if ( ! verifyWebhook ( req , secret )) {
return res . status ( 401 ). send ( 'Invalid signature' );
}
// Process the webhook
const event = req . body ;
console . log ( 'Received event:' , event . type );
res . status ( 200 ). send ( 'OK' );
});
Convex Example
import { httpAction } from "./_generated/server" ;
export const webhookHandler = httpAction ( async ( ctx , request ) => {
const signature = request . headers . get ( "proxy-signature" );
const body = await request . text ();
const secret = process . env . PROXY_WEBHOOK_SECRET ! ;
// Parse signature
const parts = signature ?. split ( ',' ) || [];
const timestamp = parts [ 0 ]?. split ( '=' )[ 1 ];
const receivedSig = parts [ 1 ]?. split ( '=' )[ 1 ];
// Verify signature
const signedPayload = ` ${ timestamp } . ${ body } ` ;
const encoder = new TextEncoder ();
const key = await crypto . subtle . importKey (
"raw" ,
encoder . encode ( secret ),
{ name: "HMAC" , hash: "SHA-256" },
false ,
[ "sign" ]
);
const sig = await crypto . subtle . sign ( "HMAC" , key , encoder . encode ( signedPayload ));
const expectedSig = Array . from ( new Uint8Array ( sig ))
. map ( b => b . toString ( 16 ). padStart ( 2 , '0' ))
. join ( '' );
if ( receivedSig !== expectedSig ) {
return new Response ( "Invalid signature" , { status: 401 });
}
// Process webhook
const event = JSON . parse ( body );
console . log ( "Received:" , event . type );
return new Response ( "OK" , { status: 200 });
});
Always verify webhook signatures before processing events. This ensures the request came from Proxy and hasn’t been tampered with.
Retry Policy
Failed webhook deliveries are retried with exponential backoff:
Attempt Delay 1 Immediate 2 5 minutes 3 30 minutes 4 2 hours 5 24 hours
After 5 failed attempts, the webhook is marked as failed and requires manual retry.
Managing Webhooks
List Webhooks
curl https://api.useproxy.ai/v1/webhooks \
-H "Authorization: Bearer your_api_key"
Update a Webhook
curl -X PATCH https://api.useproxy.ai/v1/webhooks/wh_xxx \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"events": ["transaction.created", "transaction.declined"]
}'
Delete a Webhook
curl -X DELETE https://api.useproxy.ai/v1/webhooks/wh_xxx \
-H "Authorization: Bearer your_api_key"
Next Steps
API Reference Full API documentation
Quickstart Get started quickly