Skip to main content

Webhook Events

Event envelope

All webhook events use a JSON envelope:
{
  "id": "event-id",
  "type": "transfer.completed",
  "created": "2026-04-29T23:30:00.000000Z",
  "data": {
    "id": "resource-id",
    "status": "complete"
  }
}
FieldTypeDescription
idstringStable event identifier (the event ID). Use this for deduplication. This is not the same as data.id.
typestringEvent type, such as transfer.completed.
createdstringUTC timestamp when the event was created.
dataobjectEvent-specific payload. data.id is the resource ID (e.g., transfer ID or payment ID), which may differ from the event id.
Your handler should branch on type.
switch (event.type) {
  case "transfer.completed":
    await handleTransferCompleted(event.data);
    break;
  case "payment.completed":
    await handlePaymentCompleted(event.data);
    break;
  default:
    // Unknown future event type.
    // Store and acknowledge safely.
    break;
}

transfer.created

Emitted when a Brale transfer is created. Example:
{
  "id": "3D4ExampleEventId",
  "type": "transfer.created",
  "created": "2026-04-29T23:30:00.000000Z",
  "data": {
    "id": "3D4ExampleTransferId",
    "status": "pending",
    "amount": {
      "value": "100.00",
      "currency": "USD"
    }
  }
}
Notes:
  • Treat data.id as the transfer ID.
  • Additional fields may be present as the transfer schema evolves.
  • Your integration should ignore unknown fields.

transfer.completed

Emitted when a Brale transfer reaches complete status. Use this event to replace polling transfer status. Example:
{
  "id": "3D4ExampleEventId",
  "type": "transfer.completed",
  "created": "2026-04-29T23:30:00.000000Z",
  "data": {
    "id": "3D4ExampleTransferId",
    "status": "complete",
    "amount": {
      "value": "100.00",
      "currency": "USD"
    }
  }
}
Notes:
  • Treat data.id as the transfer ID.
  • Treat data.status as the completed transfer state.
  • Additional fields may be present as the transfer schema evolves.
  • Your integration should ignore unknown fields.

payment.completed

Emitted when a payment reaches complete status. Example:
{
  "id": "3D4ExamplePaymentId",
  "type": "payment.completed",
  "created": "2026-04-28T21:30:00.000000Z",
  "data": {
    "id": "3D4ExamplePaymentId",
    "status": "complete",
    "amount": {
      "value": "1000.00",
      "currency": "USD"
    },
    "direction": "inbound",
    "type": "wire",
    "inserted_at": "2026-04-28T20:00:00.000000Z",
    "updated_at": "2026-04-28T21:30:00.000000Z"
  }
}

transfer.canceled

Emitted when a Brale transfer is canceled. Example:
{
  "id": "3D4ExampleEventId",
  "type": "transfer.canceled",
  "created": "2026-04-29T23:30:00.000000Z",
  "data": {
    "id": "3D4ExampleTransferId",
    "status": "canceled",
    "amount": {
      "value": "100.00",
      "currency": "USD"
    }
  }
}
Notes:
  • Treat data.id as the transfer ID.
  • Treat data.status as the canceled transfer state.
  • Additional fields may be present as the transfer schema evolves.
  • Your integration should ignore unknown fields.

account.verification.documents_required

Emitted when Brale’s KYB review determines one or more documents must be uploaded. Use this event to prompt the account holder to submit the requested documents. For each document with status: "pending_upload", stage the file (use document_kind and person_label from the payload), then link staged submissions. You can also poll required documents instead of using this webhook. Example:
{
  "id": "3Ar9BnQCKIrB3SYjKGBzCtFs6XL",
  "type": "account.verification.documents_required",
  "created": "2026-06-09T14:32:00Z",
  "data": {
    "account_id": "3Ar9BnQCKIrB3SYjKGBzCtFs6XL",
    "updated_at": "2026-06-09T14:32:00Z",
    "documents": [
      {
        "document_kind": "certificate_of_good_standing",
        "document_type": "business_document",
        "display_name": "Certificate of Good Standing",
        "status": "pending_upload",
        "person_label": null
      },
      {
        "document_kind": "government_photo_id",
        "document_type": "individual_document",
        "display_name": "Government-issued photo ID",
        "status": "pending_upload",
        "person_label": "Jane Doe"
      }
    ]
  }
}
Notes:
  • Treat data.account_id as the account ID.
  • Each entry in data.documents describes a required document. status is pending_upload until the document is submitted.
  • Include person_label when staging individual (KYC) documents.
  • Your integration should ignore unknown fields.

account.verification.completed

Emitted when account verification completes and the account is enabled. Example:
{
  "id": "3Ar9BnQCKIrB3SYjKGBzCtFs6XL",
  "type": "account.verification.completed",
  "created": "2026-06-09T16:00:00Z",
  "data": {
    "account_id": "3Ar9BnQCKIrB3SYjKGBzCtFs6XL",
    "status": "complete",
    "updated_at": "2026-06-09T16:00:00Z"
  }
}
Notes:
  • Treat data.account_id as the account ID.
  • Treat data.status as the completed verification state (complete).
  • This event fires only when the account reaches complete status.
  • Your integration should ignore unknown fields.

Handling future event types

Brale may add new event types over time. Best practices:
  • Use GET /webhooks/event_types to discover supported events.
  • Branch on event.type.
  • Acknowledge unknown event types safely.
  • Ignore unknown fields in data.
  • Do not assume event ordering.