Register the URLs that receive events, rotate their signing secrets, send test events and work with the delivery log. Organization admins can do the same in the Flux app under Settings → Developers.
One event sent to one endpoint, with its attempt history.
Delivery status: pending (waiting to be sent or retried), delivered (your endpoint returned 2xx), dead (all 10 attempts failed) or cancelled (the endpoint was deleted).
Field
Description
idinteger (64-bit)
Delivery id. Use it to redeliver.
eventIdstring
The event, evt_…. Same as the Flux-Event-Id header.
eventTypestring
The event type.
statusstring
Delivery state. One of pending, delivered, dead, cancelled.
attemptsinteger
Attempts so far. At most 10 before dead, plus any redeliveries.
lastStatusCodeinteger · nullable
HTTP status of the last attempt.
lastErrorstring · nullable
What went wrong on the last attempt, up to 500 characters.
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}/api/v1/webhook-endpoints");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Registers a URL to receive events. The response includes the signing secret. It's shown once: store it in your secret manager straight away.
Request body
Field
Description
urlstring
required An absolute https URL of at most 500 characters, publicly reachable. Required on create.
descriptionstring
optional At most 200 characters.
eventsarray of strings
required At least one known event type, or ["*"] for all. Required on create.
activeboolean
optional Default true. Setting true re-enables a disabled endpoint and resets its failure count.
The URL must be an absolute https URL of at most 500 characters, with no credentials in it. It can't be or resolve to a loopback, private, link-local or carrier-grade NAT address; Flux checks this again on every delivery. Flux doesn't follow redirects. events must contain at least one known event type, or "*" for all.
using System.Net.Http.Headers;
using System.Text;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/api/v1/webhook-endpoints");
request.Headers.Add("Idempotency-Key", "endpoint-billing-sync");
request.Content = new StringContent("""
{
"url": "https://hooks.example.com/flux",
"description": "Billing sync",
"events": ["invoice.paid", "receipt.issued"]
}
""", Encoding.UTF8, "application/json");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}/api/v1/webhook-endpoints/3");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
using System.Net.Http.Headers;
using System.Text;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Patch, $"{baseUrl}/api/v1/webhook-endpoints/3");
request.Content = new StringContent("""
{
"active": true
}
""", Encoding.UTF8, "application/json");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Delete, $"{baseUrl}/api/v1/webhook-endpoints/3");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Creates a new signing secret and returns it once. The old secret stops working immediately, so deploy the new one promptly. See Rotate keys and secrets.
Path parameters
Field
Description
idinteger
required The webhook endpoint's id.
Request
curl -X POST "$FLUX_BASE_URL/api/v1/webhook-endpoints/3/rotate-secret" \
-H "Authorization: ApiKey $FLUX_API_KEY"
// Node.js 18+ (built-in fetch). Save as an .mjs file.
const response = await fetch(`${process.env.FLUX_BASE_URL}/api/v1/webhook-endpoints/3/rotate-secret`, {
method: "POST",
headers: {
Authorization: `ApiKey ${process.env.FLUX_API_KEY}`,
},
});
console.log(response.status, await response.json());
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/api/v1/webhook-endpoints/3/rotate-secret");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/api/v1/webhook-endpoints/3/test");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}/api/v1/webhook-endpoints/3/deliveries");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
using System.Net.Http.Headers;
var baseUrl = Environment.GetEnvironmentVariable("FLUX_BASE_URL");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("ApiKey", Environment.GetEnvironmentVariable("FLUX_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/api/v1/webhook-deliveries/99001/redeliver");
using var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");