Custom Domains API
Manage custom domains for webhook ingestion and tunnel endpoints.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/custom-domains | List custom domains |
| POST | /api/custom-domains | Create custom domain |
| GET | /api/custom-domains/{id} | Get custom domain |
| DELETE | /api/custom-domains/{id} | Delete custom domain |
| POST | /api/custom-domains/{id}/verify | Verify domain DNS |
Custom Domain Object
{
"id": "ffffffff-ffff-4fff-8fff-ffffffffffff",
"organizationId": "eeeeeeee-eeee-4eee-8eee-eeeeeeee0001",
"domain": "webhooks.yourapp.com",
"domainType": "source",
"targetId": "11111111-1111-4111-8111-111111111111",
"verificationStatus": "verified",
"cfCustomHostnameId": "0d89c70e-7b8a-4b1f-9f4c-0a1b2c3d4e5f",
"cfHostnameStatus": "active",
"cfSslStatus": "active",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"verifiedAt": "2024-01-15T10:30:00Z"
}Domain Types
| Type | Description |
|---|---|
source | Custom domain for webhook ingestion URLs |
tunnel | Custom domain for tunnel endpoints |
Verification Statuses
verificationStatus is derived from the Cloudflare hostname and SSL states, and takes one of three
values:
| Status | Description |
|---|---|
pending | Not yet serving — the CNAME has not resolved, or the certificate is still being issued |
verified | Hostname and SSL are both active |
failed | The hostname was deleted or moved, or the certificate expired or was deleted |
cfHostnameStatus and cfSslStatus carry Cloudflare's own states underneath, which is where to
look when verificationStatus is pending and you want to know which half is waiting.
List Custom Domains
GET /api/custom-domainsExample
curl https://api.hookbase.app/api/custom-domains \
-H "Authorization: Bearer whr_your_api_key"Response
{
"domains": [
{
"id": "ffffffff-ffff-4fff-8fff-ffffffffffff",
"organizationId": "eeeeeeee-eeee-4eee-8eee-eeeeeeee0001",
"domain": "webhooks.yourapp.com",
"domainType": "source",
"targetId": "11111111-1111-4111-8111-111111111111",
"verificationStatus": "verified",
"cfCustomHostnameId": "0d89c70e-7b8a-4b1f-9f4c-0a1b2c3d4e5f",
"cfHostnameStatus": "active",
"cfSslStatus": "active",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"verifiedAt": "2024-01-15T10:30:00Z"
}
]
}Create Custom Domain
POST /api/custom-domainsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Fully qualified domain name |
| type | string | Yes | Domain type: source or tunnel |
Example
curl -X POST https://api.hookbase.app/api/custom-domains \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"domain": "webhooks.yourapp.com",
"domainType": "source",
"targetId": "11111111-1111-4111-8111-111111111111"
}'Response
{
"id": "ffffffff-ffff-4fff-8fff-ffffffff0001",
"domain": "webhooks.yourapp.com",
"domainType": "source",
"targetId": "11111111-1111-4111-8111-111111111111",
"verificationStatus": "pending",
"cnameTarget": "api.hookbase.app",
"cfHostname": {
"id": "0d89c70e-7b8a-4b1f-9f4c-0a1b2c3d4e5f",
"status": "pending"
}
}This response is not wrapped in an envelope, and it returns 201.
Point a single CNAME record at the value in cnameTarget — webhooks.yourapp.com →
api.hookbase.app — then call the verify endpoint. There is no separate _hookbase-verify record.
Get Custom Domain
GET /api/custom-domains/{id}{
"domain": {
"id": "ffffffff-ffff-4fff-8fff-ffffffffffff",
"organizationId": "eeeeeeee-eeee-4eee-8eee-eeeeeeee0001",
"domain": "webhooks.yourapp.com",
"domainType": "source",
"targetId": "11111111-1111-4111-8111-111111111111",
"verificationStatus": "verified",
"cfCustomHostnameId": "0d89c70e-7b8a-4b1f-9f4c-0a1b2c3d4e5f",
"cfHostnameStatus": "active",
"cfSslStatus": "active",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"verifiedAt": "2024-01-15T10:30:00Z"
},
"cfDetails": null,
"cnameTarget": "api.hookbase.app"
}cfDetails carries the live Cloudflare custom-hostname record when one exists, and is null
otherwise.
Verify Domain
POST /api/custom-domains/{id}/verifyChecks DNS records and activates the domain if verification passes.
Example
curl -X POST https://api.hookbase.app/api/custom-domains/ffffffff-ffff-4fff-8fff-ffffffffffff/verify \
-H "Authorization: Bearer whr_your_api_key"Response
{
"id": "ffffffff-ffff-4fff-8fff-ffffffffffff",
"domain": "webhooks.yourapp.com",
"verificationStatus": "verified",
"cfHostnameStatus": "active",
"cfSslStatus": "active",
"justVerified": true,
"validationErrors": [],
"sslValidationErrors": []
}Verification that has not passed is not an error response — the same 200 body comes back with
verificationStatus still pending and the reasons in validationErrors or sslValidationErrors.
Poll the endpoint until verificationStatus is verified; justVerified is true only on the
call that flips it, which is the one that sends the notification email.
Delete Custom Domain
DELETE /api/custom-domains/{id}Warning
Deleting a custom domain reverts all URLs to the default api.hookbase.app domain.
Example
curl -X DELETE https://api.hookbase.app/api/custom-domains/ffffffff-ffff-4fff-8fff-ffffffffffff \
-H "Authorization: Bearer whr_your_api_key"Response
204 No ContentError Responses
400 Bad Request
Invalid domain:
{
"error": "Bad Request",
"message": "Domain must be a valid fully qualified domain name",
"code": "INVALID_DOMAIN"
}409 Conflict
Domain already in use:
{
"error": "Conflict",
"message": "Domain 'webhooks.yourapp.com' is already registered",
"code": "DOMAIN_IN_USE"
}Related
- Custom Domains Guide — Setup walkthrough and troubleshooting