The Requests API lets you list captured webhooks and retrieve their full contents — including decrypted headers, query parameters, body, and per-destination forwarding results — programmatically.
Payload data is encrypted at rest with AES-256-GCM using organization-scoped data-encryption keys. Authorized API reads return decrypted captured content.
List requests
GET /v1/endpoints/:id/requests
Returns captured requests for an endpoint, newest first. Returns metadata only — no body, headers, or query params. Use the Get request endpoint for full payload access.
curl -s "https://api.hookdeploy.dev/v1/endpoints/ENDPOINT_ID/requests?limit=25" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
Query parameters:
| Param | Default | Max | Description |
|---|---|---|---|
limit | 25 | 100 | Number of requests to return |
before | — | — | Request UUID cursor — returns requests older than this ID |
after | — | — | Request UUID cursor — returns requests newer than this ID |
from | — | — | ISO 8601 datetime — filter requests captured after this time |
to | — | — | ISO 8601 datetime — filter requests captured before this time |
method | — | — | Filter by HTTP method (GET, POST, PUT, etc.) |
source_ip | — | — | Filter by source IP address |
Response:
{
"data": {
"data": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"endpoint_id": "550e8400-e29b-41d4-a716-446655440000",
"method": "POST",
"content_type": "application/json",
"body_size_bytes": 563,
"source_ip": "1.2.3.4",
"captured_at": "2026-05-24T12:00:00Z",
"has_body": true
}
],
"meta": {
"count": 1,
"has_more": false,
"next_cursor": null
}
}
}
When data.meta.has_more is true, pass data.meta.next_cursor as before to fetch the next page.
Cursor pagination
HookDeploy uses cursor-based pagination. This keeps performance consistent as your request history grows.
First page:
curl -s "https://api.hookdeploy.dev/v1/endpoints/ENDPOINT_ID/requests?limit=25" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
Next page — pass data.meta.next_cursor as before:
curl -s "https://api.hookdeploy.dev/v1/endpoints/ENDPOINT_ID/requests?limit=25&before=770e8400-e29b-41d4-a716-446655440002" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
Repeat until data.meta.next_cursor is null.
Filtering by date range:
curl -s "https://api.hookdeploy.dev/v1/endpoints/ENDPOINT_ID/requests?from=2026-05-01T00:00:00Z&to=2026-05-31T23:59:59Z" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
Get request
GET /v1/endpoints/:id/requests/:requestId
Returns a single request with full decrypted contents — headers, query parameters, body, and an array of forwarding results (one per destination).
curl -s "https://api.hookdeploy.dev/v1/endpoints/ENDPOINT_ID/requests/REQUEST_ID" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
Response:
{
"data": {
"id": "770e8400-e29b-41d4-a716-446655440002",
"endpoint_id": "550e8400-e29b-41d4-a716-446655440000",
"method": "POST",
"content_type": "application/json",
"body_size_bytes": 563,
"source_ip": "1.2.3.4",
"captured_at": "2026-05-24T12:00:00Z",
"headers": {
"content-type": "application/json",
"x-stripe-signature": "t=1234567890,v1=abc..."
},
"query": {},
"body": {
"id": "evt_abc123",
"type": "payment_intent.succeeded",
"data": {
"object": {
"amount": 4200,
"currency": "usd"
}
}
},
"forward_results": [
{
"id": "880e8400-e29b-41d4-a716-446655440003",
"destination_id": "990e8400-e29b-41d4-a716-446655440004",
"destination_name": "Production Server",
"destination_url": "https://myserver.com/webhooks",
"status_code": 200,
"response_time_ms": 312,
"success": true,
"error": null,
"forwarded_at": "2026-05-24T12:00:01Z",
"transformation_applied": false,
"transformation_errors": null,
"response_body_available": true,
"response_body_size_bytes": 412,
"response_body_truncated": false,
"response_body_content_type": "application/json"
}
]
}
}
Forward result fields:
| Field | Description |
|---|---|
destination_id | UUID of the forward destination, or null for legacy single-destination forwarding |
destination_name | Display name of the destination |
destination_url | Target URL, or private IP:port for WireGuard/Tailscale tunnel destinations |
status_code | HTTP status code returned by the destination, or null on connection failure |
response_time_ms | Round-trip time in milliseconds |
success | true if status code is 2xx |
error | Error message for failed deliveries (timeout, connection refused, non-2xx) |
forwarded_at | ISO 8601 timestamp of the forwarding attempt |
transformation_applied | Whether a transformation rule was applied before forwarding |
transformation_errors | Array of transformation errors, or null |
response_body_available | true if a destination response body was captured for this forward result |
response_body_size_bytes | Captured response body size in bytes, or null if none was captured |
response_body_truncated | true if the destination response exceeded the capture size limit |
response_body_content_type | Content-Type of the captured response body, or null |
When response_body_available is true, use Get forward response body to retrieve the decrypted body.
Get forward response body
GET /v1/endpoints/:id/requests/:requestId/forward-results/:forwardResultId/response
Returns the decrypted response body from a destination for a single forward result. Capture requires a Starter plan or above (opt-in per destination); reading historical captures has no plan gate.
curl -s "https://api.hookdeploy.dev/v1/endpoints/ENDPOINT_ID/requests/REQUEST_ID/forward-results/FORWARD_RESULT_ID/response" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
Response:
{
"data": {
"body": "{\"status\":\"ok\"}",
"content_type": "application/json",
"size_bytes": 412,
"truncated": false
}
}
Errors:
| Status | Code | When |
|---|---|---|
| 403 | forbidden | Forward result does not belong to this request or organization |
| 404 | not_found | No response body was captured for this forward result |
Captured response bodies are encrypted at rest with the same per-organization keys as request payloads. The API decrypts on read using the historical key recorded at capture time. There is no plan check on read — historical captures remain accessible after a plan downgrade; only new capture is gated at the destination level (Starter+).
bodyis the decrypted destination response body as a string (JSON responses are returned as text, not parsed objects).content_typereflects the destination’sContent-Typeheader at capture time.truncatedistrueif the response exceeded the capture size limit.
Security
Request data is encrypted at rest with AES-256-GCM using organization-scoped data-encryption keys that rotate weekly. API authorization keeps request access isolated to the owning organization.
Next steps
- Destinations API — List forward destinations for an endpoint
- Replay API — Re-send a captured request to a target URL
- Endpoints API — Manage endpoint URLs