public-api
Integrator access: API keys with scopes and integrator webhooks (HMAC-signed callbacks). All other resources are shared with the web/mobile API and documented per scope.
Integration home: connections, webhooks, API keys, usage and portal links
GET /v1/integration
- getIntegrationHome
- API key scope integration:read
- Tenant operator
Operator console "Integration" page (P9-T11, FR-PLAT-06): every non-retired banking connection with lifecycle, health, breaker, webhook registration and last event, event backlog, last reconciliation run and open exceptions, activation checklist progress; API key counts; 7-day usage; integrator webhook health; developer-portal links.
API key scope: integration:read (operator-level keys only, X-Tenant-Id = the operator id).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Responses
200 OK
application/jsonIntegration home of an operator (FR-PLAT-06): connections, webhook registration, API keys, usage, integrator webhooks and portal links.
operatorIdUuidrequiredgeneratedAtTimestamprequiredactiveConnectionIdstring | null (uuid)requiredActive primary connection (production first).
connectionsarray of IntegrationConnectionrequiredConnections not retired, active first.
apiKeysobjectrequiredUnrevoked, unexpired keys of the operator (all customers and operator-level).
Fields of apiKeys
activeintegerrequiredliveintegerrequiredtestintegerrequiredoperatorLevelintegerrequiredusedLast24hintegerrequired
usageLast7DaysApiUsageTotalsrequiredintegratorWebhooksobjectrequiredFields of integratorWebhooks
endpointsintegerrequiredactiveintegerrequiredpausedintegerrequiredfailedintegerrequireddeliveriesPendingintegerrequireddeliveriesFailed24hintegerrequiredlastDeliveryAtTimestamp | nullrequired
linksobjectrequiredDeveloper portal (
DEVELOPER_PORTAL_URL, D-35, D-42).Fields of links
portalstring (uri)requiredreferencestring (uri)requiredgettingStartedstring (uri)requiredsandboxstring (uri)requiredchangelogstring (uri)requiredopenapistring (uri)required
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X GET "https://bank.wirebloom.com/v1/integration" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integration", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"GET",
"https://bank.wirebloom.com/v1/integration",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Recent requests of an API key (7 days, no bodies)
GET /v1/integration/api-keys/{apiKeyId}/requests
- listOperatorApiKeyRequests
- API key scope integration:read
- Tenant operator
The last requests of any key of the operator (newest first) and the status breakdown over 7 days. Method, route template, status, duration and request id only.
API key scope: integration:read (operator-level keys only, X-Tenant-Id = the operator id).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
apiKeyIdrequired | path | Uuid | Identifier (apiKeyId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
limit | query | integer | Entries (default and max 100). |
outcome | query | string |
|
Responses
200 OK
application/jsonapiKeyIdUuidrequiredretentionDaysintegerrequiredDays the request log keeps (7).
statusCountsobjectrequiredResponses per HTTP status over the retention window (error breakdown).
dataarray of ApiRequestLogEntryrequiredNewest first.
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X GET "https://bank.wirebloom.com/v1/integration/api-keys/{apiKeyId}/requests" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integration/api-keys/{apiKeyId}/requests", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"GET",
"https://bank.wirebloom.com/v1/integration/api-keys/{apiKeyId}/requests",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()API usage per key across the operator (daily)
GET /v1/integration/api-usage
- getOperatorApiUsage
- API key scope integration:read
- Tenant operator
Per-key totals and daily series (P9-T11). Days before yesterday come from the daily rollup; yesterday and today are live from the request log (a call appears within API_REQUEST_LOG_FLUSH_MS, 5 s by default). Covers every key of the operator: customer keys and operator-level keys.
API key scope: integration:read (operator-level keys only, X-Tenant-Id = the operator id).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
from | query | Date | First UTC day (default: |
to | query | Date | Last UTC day, inclusive (default: today). At most 90 days after |
apiKeyId | query | Uuid | One key only. |
environment | query | string |
|
customerId | query | Uuid | One customer's keys only. |
Responses
200 OK
application/jsonfromDaterequiredtoDaterequiredgeneratedAtTimestamprequiredtotalsApiUsageTotalsrequiredkeysarray of ApiKeyUsagerequiredKeys in scope (at most 200, newest first): active keys and keys revoked during the window, with or without requests.
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X GET "https://bank.wirebloom.com/v1/integration/api-usage" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integration/api-usage", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"GET",
"https://bank.wirebloom.com/v1/integration/api-usage",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()List integrator webhook endpoints
GET /v1/integrator-webhooks
- listIntegratorWebhooks
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
cursor | query | string | Opaque cursor from |
limit | query | integer | Page size (max 100). |
sort | query | string | Sort order; prefix |
Responses
200 OK
application/jsonCursor-paginated list of IntegratorWebhook.
dataarray of IntegratorWebhookrequiredpagePageInforequired
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X GET "https://bank.wirebloom.com/v1/integrator-webhooks" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"GET",
"https://bank.wirebloom.com/v1/integrator-webhooks",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Register webhook endpoint
POST /v1/integrator-webhooks
- createIntegratorWebhook
- API key scope webhooks:manage
- Tenant any
Not idempotent: the response carries the signing secret shown once. SSRF guard on the URL (422); at most 10 endpoints per customer (409).
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Step-up: requires a verified step-up challenge for action integrator_webhook.change within the last 5 minutes (session/bearer only). Otherwise 403 with problem type step-up-required; the step-up check runs before body validation. API keys holding webhooks:manage may call it without a step-up; every create, update, secret rotation and deletion notifies the endpoint owners (webhook_endpoint_changed, staff or customer members with webhooks.manage), whoever made it (review W3-03, P4 S-14).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Request body
urlstring (uri)requiredeventsarray of IntegratorEventTyperequireddescriptionstring | nullenabledboolean
Responses
201 Created
application/jsonidUuidrequiredread-onlyFields of id
urlstring (uri)requiredeventsarray of IntegratorEventTyperequireddescriptionstring | nullenabledbooleanrequiredsecretPrefixstringrequiredread-onlycreatedAtTimestamprequiredread-onlyFields of createdAt
updatedAtTimestamprequiredread-onlyRow version: the ETag is
W/"<updatedAt epoch ms>"(If-MatchonPATCH).Fields of updatedAt
lastDeliveryAtTimestamp | nullfailureCountintegerrequiredread-onlystatusstringread-onlypausedafter 20 consecutive failed attempts orenabled: false;failedwhen a delivery exhausts 72 h without success. Re-enable withPATCH enabled: true.pauseReasonstring | nullread-onlysecretstringrequiredSigning secret
whsec_..., shown once.
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json422 Semantically invalid request; `errors[]` lists field-level problems. Also `idempotency-key-reused` when the key was used with a different payload, `limit-exceeded`, `recipient-not-approved`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/integrator-webhooks" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID" \
-H "Content-Type: application/json" \
--data '{
"url": "https://example.com",
"events": [
"webhook.test"
]
}'const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://example.com",
"events": [
"webhook.test"
]
}),
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/integrator-webhooks",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
"Content-Type": "application/json",
},
json={
"url": "https://example.com",
"events": [
"webhook.test"
]
},
timeout=30,
)
response.raise_for_status()Get webhook endpoint
GET /v1/integrator-webhooks/{webhookId}
- getIntegratorWebhook
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
If-None-Match | header | string | Conditional GET; |
Responses
200 OK
application/jsonIntegrator webhook endpoint (
tenant.integrator_webhooks). Customer-level endpoints receive the customer's events; operator-level endpoints (created withX-Tenant-Id= the operator, P9-T08b) receive the events of every customer of the operator, including the operator-only types.idUuidrequiredread-onlyFields of id
urlstring (uri)requiredeventsarray of IntegratorEventTyperequireddescriptionstring | nullenabledbooleanrequiredsecretPrefixstringrequiredread-onlycreatedAtTimestamprequiredread-onlyFields of createdAt
updatedAtTimestamprequiredread-onlyRow version: the ETag is
W/"<updatedAt epoch ms>"(If-MatchonPATCH).Fields of updatedAt
lastDeliveryAtTimestamp | nullfailureCountintegerrequiredread-onlystatusstringread-onlypausedafter 20 consecutive failed attempts orenabled: false;failedwhen a delivery exhausts 72 h without success. Re-enable withPATCH enabled: true.pauseReasonstring | nullread-only
304 Not modified (`If-None-Match` matched).
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X GET "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"GET",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Update webhook endpoint
PATCH /v1/integrator-webhooks/{webhookId}
- updateIntegratorWebhook
- API key scope webhooks:manage
- Tenant any
Concurrency: If-Match with the current ETag is required (428 if absent, 412 if stale).
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Step-up: requires a verified step-up challenge for action integrator_webhook.change within the last 5 minutes (session/bearer only). Otherwise 403 with problem type step-up-required; the step-up check runs before body validation. API keys holding webhooks:manage may call it without a step-up; every create, update, secret rotation and deletion notifies the endpoint owners (webhook_endpoint_changed, staff or customer members with webhooks.manage), whoever made it (review W3-03, P4 S-14).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
If-Matchrequired | header | string | ETag of the representation being modified (from a prior GET/PATCH). |
Request body
urlstring (uri)requiredeventsarray of IntegratorEventTyperequireddescriptionstring | nullenabledboolean
Responses
200 OK
application/jsonIntegrator webhook endpoint (
tenant.integrator_webhooks). Customer-level endpoints receive the customer's events; operator-level endpoints (created withX-Tenant-Id= the operator, P9-T08b) receive the events of every customer of the operator, including the operator-only types.idUuidrequiredread-onlyFields of id
urlstring (uri)requiredeventsarray of IntegratorEventTyperequireddescriptionstring | nullenabledbooleanrequiredsecretPrefixstringrequiredread-onlycreatedAtTimestamprequiredread-onlyFields of createdAt
updatedAtTimestamprequiredread-onlyRow version: the ETag is
W/"<updatedAt epoch ms>"(If-MatchonPATCH).Fields of updatedAt
lastDeliveryAtTimestamp | nullfailureCountintegerrequiredread-onlystatusstringread-onlypausedafter 20 consecutive failed attempts orenabled: false;failedwhen a delivery exhausts 72 h without success. Re-enable withPATCH enabled: true.pauseReasonstring | nullread-only
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json412 `If-Match` does not match the current ETag (resource changed).
application/problem+json422 Semantically invalid request; `errors[]` lists field-level problems. Also `idempotency-key-reused` when the key was used with a different payload, `limit-exceeded`, `recipient-not-approved`.
application/problem+json428 `If-Match` header is required for this operation.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X PATCH "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID" \
-H "If-Match: \"<etag>\"" \
-H "Content-Type: application/json" \
--data '{
"url": "https://example.com",
"events": [
"webhook.test"
]
}'const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}", {
method: "PATCH",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
"If-Match": "\"<etag>\"",
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://example.com",
"events": [
"webhook.test"
]
}),
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"PATCH",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
"If-Match": "\"<etag>\"",
"Content-Type": "application/json",
},
json={
"url": "https://example.com",
"events": [
"webhook.test"
]
},
timeout=30,
)
response.raise_for_status()Delete webhook endpoint
DELETE /v1/integrator-webhooks/{webhookId}
- deleteIntegratorWebhook
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Step-up: requires a verified step-up challenge for action integrator_webhook.change within the last 5 minutes (session/bearer only). Otherwise 403 with problem type step-up-required; the step-up check runs before body validation. API keys holding webhooks:manage may call it without a step-up; every create, update, secret rotation and deletion notifies the endpoint owners (webhook_endpoint_changed, staff or customer members with webhooks.manage), whoever made it (review W3-03, P4 S-14).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Responses
204 No Content
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X DELETE "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}", {
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);import os
import requests
response = requests.request(
"DELETE",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Delivery attempts
GET /v1/integrator-webhooks/{webhookId}/deliveries
- listWebhookDeliveries
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
cursor | query | string | Opaque cursor from |
limit | query | integer | Page size (max 100). |
sort | query | string | Sort order; prefix |
filter | query | object | Filters as |
Responses
200 OK
application/jsonCursor-paginated list of WebhookDelivery.
dataarray of WebhookDeliveryrequiredpagePageInforequired
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X GET "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/deliveries" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/deliveries", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"GET",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/deliveries",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Redeliver an event
POST /v1/integrator-webhooks/{webhookId}/deliveries/{deliveryId}/redeliver
- redeliverWebhook
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
deliveryIdrequired | path | Uuid | Identifier (deliveryId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Responses
202 Accepted
application/jsonidUuidrequiredread-onlyFields of id
eventIdUuidrequiredeventTypeIntegratorEventTyperequiredattemptintegerrequiredstatusCodeinteger | nulldurationMsinteger | nullsucceededbooleanrequirednextRetryAtTimestamp | nullcreatedAtTimestamprequiredread-onlyFields of createdAt
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/deliveries/{deliveryId}/redeliver" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/deliveries/{deliveryId}/redeliver", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/deliveries/{deliveryId}/redeliver",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Rotate signing secret (old valid 24 h)
POST /v1/integrator-webhooks/{webhookId}/rotate-secret
- rotateIntegratorWebhookSecret
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Step-up: requires a verified step-up challenge for action integrator_webhook.change within the last 5 minutes (session/bearer only). Otherwise 403 with problem type step-up-required; the step-up check runs before body validation. API keys holding webhooks:manage may call it without a step-up; every create, update, secret rotation and deletion notifies the endpoint owners (webhook_endpoint_changed, staff or customer members with webhooks.manage), whoever made it (review W3-03, P4 S-14).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Responses
200 OK
application/jsonidUuidrequiredread-onlyFields of id
urlstring (uri)requiredeventsarray of IntegratorEventTyperequireddescriptionstring | nullenabledbooleanrequiredsecretPrefixstringrequiredread-onlycreatedAtTimestamprequiredread-onlyFields of createdAt
updatedAtTimestamprequiredread-onlyRow version: the ETag is
W/"<updatedAt epoch ms>"(If-MatchonPATCH).Fields of updatedAt
lastDeliveryAtTimestamp | nullfailureCountintegerrequiredread-onlystatusstringread-onlypausedafter 20 consecutive failed attempts orenabled: false;failedwhen a delivery exhausts 72 h without success. Re-enable withPATCH enabled: true.pauseReasonstring | nullread-onlysecretstringrequiredSigning secret
whsec_..., shown once.
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/rotate-secret" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/rotate-secret", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/rotate-secret",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Send a test event
POST /v1/integrator-webhooks/{webhookId}/test
- testIntegratorWebhook
- API key scope webhooks:manage
- Tenant any
API key scope: webhooks:manage.
Level (P9-T08b): X-Tenant-Id = a customer → that customer's endpoints; X-Tenant-Id = the operator → the operator-level endpoints (sessions of operator owners with webhooks.manage, operator-level keys with webhooks:manage).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
webhookIdrequired | path | Uuid | Identifier (webhookId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Responses
200 OK
application/jsonidUuidrequiredread-onlyFields of id
eventIdUuidrequiredeventTypeIntegratorEventTyperequiredattemptintegerrequiredstatusCodeinteger | nulldurationMsinteger | nullsucceededbooleanrequirednextRetryAtTimestamp | nullcreatedAtTimestamprequiredread-onlyFields of createdAt
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/test" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/test", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/integrator-webhooks/{webhookId}/test",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Simulate an incoming payment
POST /v1/sandbox/incoming-payments
- simulateSandboxIncomingPayment
- API key scope payments:write
- Tenant customer
Sandbox only (wb_test_ keys and sandbox environments); 404 feature-disabled elsewhere.
API key scope: payments:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Idempotency-Key | header | string | Optional idempotency key; same semantics as on money operations. |
Request body
Responses
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json422 Semantically invalid request; `errors[]` lists field-level problems. Also `idempotency-key-reused` when the key was used with a different payload, `limit-exceeded`, `recipient-not-approved`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/sandbox/incoming-payments" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID" \
-H "Content-Type: application/json" \
--data '{
"balanceId": "0192a6f0-7c1e-7b3a-9d2e-5f4c3b2a1908",
"amount": {
"amountMinor": "125050",
"currency": "GBP"
}
}'const response = await fetch("https://bank.wirebloom.com/v1/sandbox/incoming-payments", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"balanceId": "0192a6f0-7c1e-7b3a-9d2e-5f4c3b2a1908",
"amount": {
"amountMinor": "125050",
"currency": "GBP"
}
}),
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/sandbox/incoming-payments",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
"Content-Type": "application/json",
},
json={
"balanceId": "0192a6f0-7c1e-7b3a-9d2e-5f4c3b2a1908",
"amount": {
"amountMinor": "125050",
"currency": "GBP"
}
},
timeout=30,
)
response.raise_for_status()Simulate a provider status for a payment
POST /v1/sandbox/payments/{paymentId}/status
- simulateSandboxPaymentStatus
- API key scope payments:write
- Tenant customer
Sandbox only (wb_test_ keys and sandbox environments); 404 feature-disabled elsewhere.
API key scope: payments:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
paymentIdrequired | path | Uuid | Identifier (paymentId). |
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Idempotency-Key | header | string | Optional idempotency key; same semantics as on money operations. |
Request body
statusstringrequired
Responses
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json404 Resource does not exist in this tenant (cross-tenant ids also return 404), or feature disabled (`feature-disabled`).
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json422 Semantically invalid request; `errors[]` lists field-level problems. Also `idempotency-key-reused` when the key was used with a different payload, `limit-exceeded`, `recipient-not-approved`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/sandbox/payments/{paymentId}/status" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID" \
-H "Content-Type: application/json" \
--data '{
"status": "processing"
}'const response = await fetch("https://bank.wirebloom.com/v1/sandbox/payments/{paymentId}/status", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"status": "processing"
}),
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/sandbox/payments/{paymentId}/status",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
"Content-Type": "application/json",
},
json={
"status": "processing"
},
timeout=30,
)
response.raise_for_status()Reset sandbox deliveries and paused endpoints
POST /v1/sandbox/reset
- resetSandbox
- API key scope webhooks:manage
- Tenant customer
Sandbox only (wb_test_ keys and sandbox environments); 404 feature-disabled elsewhere.
API key scope: webhooks:manage.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Responses
200 OK
application/jsondeliveriesDeletedintegerrequiredendpointsReactivatedintegerrequired
401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/sandbox/reset" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID"const response = await fetch("https://bank.wirebloom.com/v1/sandbox/reset", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/sandbox/reset",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
},
timeout=30,
)
response.raise_for_status()Emit an integrator event
POST /v1/sandbox/webhook-events
- simulateSandboxWebhookEvent
- API key scope webhooks:manage
- Tenant customer
Sandbox only (wb_test_ keys and sandbox environments); 404 feature-disabled elsewhere. Events carry data.sandbox: true.
API key scope: webhooks:manage.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-Tenant-Idrequired | header | Uuid | Tenant context: the operator tenant id (staff operations) or customer tenant id (customer operations). Validated against the caller's memberships; mismatch → |
X-Request-Id | header | string | Client-supplied correlation id. Generated by the server when absent; always echoed in the response and in problem details. |
Idempotency-Key | header | string | Optional idempotency key; same semantics as on money operations. |
Request body
typeIntegratorEventTyperequiredobjectIdUuidstatusstringamountMoney
Responses
400 Malformed request: unparseable JSON, or an invalid header, path or query parameter (`errors[].field` is `header.X`, `path.x` or `query.x`). Body validation failures are 422 `validation-error`.
application/problem+json401 Missing, expired or invalid credentials (`unauthenticated`, `session-expired` with `reason` `idle` / `revoked` / `expired`, `invalid-api-key`, `mfa-required`).
application/problem+json403 Authenticated but not allowed: missing capability or scope, tenant not in memberships, `step-up-required`, IP not allow-listed, impersonation restriction.
application/problem+json409 State conflict: `invalid-transition`, `duplicate-recipient`, `quote-expired`, `insufficient-funds`, `idempotency-key-in-use` (with Retry-After), `not-cancellable`.
application/problem+json422 Semantically invalid request; `errors[]` lists field-level problems. Also `idempotency-key-reused` when the key was used with a different payload, `limit-exceeded`, `recipient-not-approved`.
application/problem+json429 Rate limit exceeded.
application/problem+jsondefault Unexpected error (`500 internal-error`, `501 not-implemented`, `502 provider-error`, `503 service-unavailable`, `504 provider-timeout`). Money operations that time out at the provider are never retried blindly; their state becomes `exception`/unknown and is reconciled.
application/problem+json
Code samples
curl -X POST "https://bank.wirebloom.com/v1/sandbox/webhook-events" \
-H "Authorization: Bearer $WIREBLOOM_API_KEY" \
-H "X-Tenant-Id: $WIREBLOOM_CUSTOMER_ID" \
-H "Content-Type: application/json" \
--data '{
"type": "webhook.test"
}'const response = await fetch("https://bank.wirebloom.com/v1/sandbox/webhook-events", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WIREBLOOM_API_KEY}`,
"X-Tenant-Id": process.env.WIREBLOOM_CUSTOMER_ID!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"type": "webhook.test"
}),
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const result = await response.json();import os
import requests
response = requests.request(
"POST",
"https://bank.wirebloom.com/v1/sandbox/webhook-events",
headers={
"Authorization": f"Bearer {os.environ['WIREBLOOM_API_KEY']}",
"X-Tenant-Id": os.environ["WIREBLOOM_CUSTOMER_ID"],
"Content-Type": "application/json",
},
json={
"type": "webhook.test"
},
timeout=30,
)
response.raise_for_status()