Webhooks
Afia's HTTP API tracks various events, such as customer.created, domain.updated and file.deleted.
You can register a webhook endpoint that will get notified whenever certain events occur.
When your endpoint responds with an HTTP status code between 200-299, Afia considers the webhook as delivered. Otherwise, Afia will retry the webhook later.
Afia guarantees at-least-once delivery. Ensure that your webhook endpoints support receiving the same payload multiple times.
Trying Out Webhooks
First, start a local API server:
afia serve --create-key sk_local_123 --api-port 9200
Send a request to the API server to create a new WebhookEndpoint:
curl -H 'Authorization: Bearer sk_local_123' \
http://localhost:9200/unstable/webhook_endpoints \
--json '{"url": "http://localhost:5500/my-webhook-handler", "events": ["customer.created"]}'
Whenever you create a Customer, Afia will send an event to localhost:5500/my-webhook-handler.
We will now create an server to handle the webhook events.
Create a my-webhook-handler.rs file with the following contents:
#!/usr/bin/env cargo +nightly -Zscript
---
[dependencies]
axum = "0.8"
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread"] }
---
use axum::{extract, http::StatusCode, routing::post, Router};
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
let app = Router::new().route("/my-webhook-handler", post(handle_webhook));
let listener = TcpListener::bind("0.0.0.0:5500").await.unwrap();
println!("Listening on port 5500");
axum::serve(listener, app).await.unwrap();
}
async fn handle_webhook(extract::Json(payload): extract::Json<serde_json::Value>) -> StatusCode {
let payload_pretty = serde_json::to_string_pretty(&payload).unwrap();
println!(
r#"Received webhook payload:
{payload_pretty}"#
);
StatusCode::OK
}
Start the webhook handler server:
cargo +nightly -Zscript run --manifest-path=./my-webhook-handler.rs
Use the local API server to create a customer:
curl -H 'Authorization: Bearer sk_local_123' http://localhost:9200/unstable/customers --json '{}'
The webhook handler server should print something like:
{
"created_at": "2030-03-08:01:23.456789Z",
"data": {
"object": {
"customer_id": "cus_E737igTiZP7zP2s2T4aeFhZPZs",
"email": null,
"name": null,
"org_id": "org_yiykiAb2gt7rb3nHcEc2z6ehf6",
"phone": null
},
"type": "customer.created"
},
"event_id": "ev_aP3aZGeEktAzEPGEEfgKGaLKTa"
}
Retries
If webhook delivery fails, Afia will periodically retry using exponential backoff.
If the webhook fails to deliver after several days, Afia will stop retrying.
The commands below will trigger a webhook before starting the webhook handler server from above.
The first send will fail since the server is not running. After a few seconds, Afia will retry. The handler will then receive and print the webhook payload.
afia serve --create-key sk_local_123 --api-port 9200
curl -H 'Authorization: Bearer sk_local_123' \
http://localhost:9200/unstable/webhook_endpoints \
--json '{"url": "http://localhost:5500/my-webhook-handler", "events": ["customer.created"]}'
curl -H 'Authorization: Bearer sk_local_123' http://localhost:9200/unstable/customers --json '{}'
cargo +nightly -Zscript run --manifest-path=./my-webhook-handler.rs
Delivery Order
Webhooks can be delivered out of order. Your handler should not assume that it will receive payloads in any particular order.