Endpoint Authentication
Every outbound webhook is signed, so your customer can prove it came from you. Some receivers also need the request to carry credentials before it reaches their code. An API gateway or load balancer may require HTTP Basic auth, or the receiving API may be protected by OAuth2 and only accept a bearer token.
Endpoint authentication covers these cases. Give an HTTP endpoint a username and password, or an OAuth2 client, and Hookbase sends an Authorization header with every delivery. Endpoint authentication requires the Starter plan or above.
When to use it
- The endpoint sits behind a gateway, WAF or reverse proxy that rejects requests without Basic auth.
- The receiving API is protected by an OAuth2 authorization server and only accepts access tokens issued to a client (the client credentials grant, RFC 6749 §4.4).
- The receiver prefers its existing auth stack over checking a webhook signature at the edge.
Endpoint authentication applies to HTTP endpoints only. Queue, bus and bucket endpoints authenticate with their own destination credentials, and nothing is pushed to a polling endpoint. The API rejects authentication on those kinds with 400.
Set it up in the dashboard
Open Outbound → Endpoints, then Create Endpoint or Edit on an HTTP endpoint. In the Authentication section, choose HTTP Basic or OAuth2 client credentials and fill in the fields below.
The password and client secret are write-only. Once saved, the form shows them as Set and never displays them again. Leave the field blank to keep the saved value, or type a new one to replace it. To remove authentication, choose None and save.
The endpoint page lists the type and the non-secret settings, for example HTTP Basic (hookbase).
HTTP Basic
| Field | Required | Rules |
|---|---|---|
type | Yes | "basic" |
username | Yes | 1 to 256 characters, must not contain : |
password | On create, and when switching from OAuth2 | 1 to 1024 characters. Write-only |
Each delivery carries Authorization: Basic <base64(username:password)>.
OAuth2 client credentials
| Field | Required | Rules |
|---|---|---|
type | Yes | "oauth2_client_credentials" |
tokenUrl | Yes | An https:// URL, at most 2048 characters. URLs that point to private or internal networks, embed credentials or use a non-standard port are rejected (allowed ports: 443, 80, 8080, 8443, 3000, 4000, 5000, 8000, 9000) |
clientId | Yes | 1 to 512 characters |
clientSecret | On create, and when switching from Basic | 1 to 2048 characters. Write-only |
scope | No | At most 1024 characters. Sent as the scope parameter when set |
audience | No | At most 1024 characters. Sent as the audience parameter when set (Auth0 and some other servers require it) |
clientAuthMethod | No | client_secret_basic (default) or client_secret_post |
Hookbase gets a token by sending a POST to tokenUrl with Content-Type: application/x-www-form-urlencoded and the body grant_type=client_credentials, plus scope and audience when you set them. The client authenticates as follows:
client_secret_basic: anAuthorization: Basicheader built from the client ID and secret. Both are form-urlencoded first, as RFC 6749 §2.3.1 requires.client_secret_post:client_idandclient_secretare added to the form body.
The token response must be JSON with an access_token. token_type must be Bearer if it is present. Each delivery then carries Authorization: Bearer <access_token>.
Token caching and refresh
- A token is reused until 60 seconds before it expires, based on the response's
expires_in. If the response has noexpires_in, Hookbase treats the token as valid for 5 minutes. - Tokens are cached per endpoint, keyed by a hash of the stored settings. Any change to the endpoint's authentication, including a new secret, means the next delivery fetches a new token.
- If the endpoint answers
401, the cached token is discarded, so the retry fetches a new one. This covers tokens revoked before they expire. - The token request times out after 10 seconds. Redirects from the token URL are not followed.
When a token can't be obtained
If the token request fails, times out, returns a non-2xx status, has no access_token or uses another token type, the delivery attempt fails with error type auth and is retried on the endpoint's normal schedule, like any other failed attempt. The attempt's error message includes the HTTP status and the OAuth error / error_description fields from the response, but never the raw response body.
Plan availability
| Plan | Endpoint authentication |
|---|---|
| Free | No |
| Pay As You Go | No |
| Starter | Yes |
| Pro | Yes |
| Business | Yes |
Setting or changing credentials on a plan without the feature returns 403. Removing credentials is always allowed. If you downgrade, credentials you already saved keep being sent, so the receiver doesn't start rejecting deliveries. You can remove them, but you can't change them until you upgrade again.
API
authentication is a field on Create Endpoint and Update Endpoint.
Create with HTTP Basic
curl -X POST https://api.hookbase.app/api/organizations/$ORG_ID/webhook-endpoints \
-H "Authorization: Bearer $HOOKBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"applicationId": "'$APP_ID'",
"url": "https://api.customer.com/webhooks",
"authentication": {
"type": "basic",
"username": "hookbase",
"password": "'$RECEIVER_PASSWORD'"
}
}'Create with OAuth2 client credentials
curl -X POST https://api.hookbase.app/api/organizations/$ORG_ID/webhook-endpoints \
-H "Authorization: Bearer $HOOKBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"applicationId": "'$APP_ID'",
"url": "https://api.customer.com/webhooks",
"authentication": {
"type": "oauth2_client_credentials",
"tokenUrl": "https://auth.customer.com/oauth/token",
"clientId": "hookbase-webhooks",
"clientSecret": "'$CLIENT_SECRET'",
"scope": "webhooks:write",
"clientAuthMethod": "client_secret_basic"
}
}'What responses show
Every endpoint response includes authentication with the type and the non-secret settings, or null when the endpoint has none. The password and client secret are never returned:
{
"data": {
"id": "wh_ep_xxx",
"url": "https://api.customer.com/webhooks",
"authentication": {
"type": "oauth2_client_credentials",
"tokenUrl": "https://auth.customer.com/oauth/token",
"clientId": "hookbase-webhooks",
"scope": "webhooks:write",
"audience": null,
"clientAuthMethod": "client_secret_basic"
}
}
}Update
PATCH replaces the whole authentication setting, so send every non-secret field you want to keep. With the same type as before, leave out password / clientSecret to keep the stored one:
curl -X PATCH https://api.hookbase.app/api/organizations/$ORG_ID/webhook-endpoints/$ENDPOINT_ID \
-H "Authorization: Bearer $HOOKBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"authentication": {
"type": "oauth2_client_credentials",
"tokenUrl": "https://auth.customer.com/oauth/token",
"clientId": "hookbase-webhooks",
"scope": "webhooks:write webhooks:read"
}
}'When you switch type (Basic to OAuth2 or back), the new secret is required. Without it the API returns 400 with "message": "authentication: clientSecret is required" (or password is required). Leaving authentication out of the PATCH entirely leaves it unchanged.
Remove
curl -X PATCH https://api.hookbase.app/api/organizations/$ORG_ID/webhook-endpoints/$ENDPOINT_ID \
-H "Authorization: Bearer $HOOKBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "authentication": null }'How it works with signatures
Authentication is in addition to the webhook signature, not a replacement for it.
- Every delivery is still signed exactly as described in Signature Verification. The signature covers the message ID, timestamp and body, not the
Authorizationheader, so adding, changing or removing credentials doesn't affect verification. - Credentials prove the request is allowed through. The signature proves the body came from you and wasn't changed. Receivers should keep verifying the signature.
- When authentication is set, its
Authorizationheader replaces any customAuthorizationheader you configured in the endpoint'sheaders. - Test endpoint sends the same credentials as a real delivery, so a successful test also proves the credentials work.
- Delivery attempts store the request headers for the dashboard and the portal, but credential headers keep only their scheme (
Basic [redacted],Bearer [redacted]). - With static IP delivery turned on, the webhook itself goes through the static IP relay, but the OAuth token request is made directly. Don't restrict the token URL to the static IPs.
Storage
The username and OAuth settings are stored as plain settings. The password and client secret are encrypted at rest and decrypted only when a delivery needs them. Listing or reading endpoints never decrypts them.