Skip to content

Callbacks Overview ​

Callbacks are how Flywire notifies your systems about events as they happen. Where the rest of this documentation describes inbound requests (your server calling the Agents API), a callback is the opposite direction: Flywire sends an asynchronous HTTP POST to a URL you configure whenever something noteworthy occurs — for example, when a payment's status changes.

You don't poll for these events. Once callbacks are enabled for your agency, Flywire pushes them to your endpoint as they occur.

Envelope ​

Every callback shares the same top-level envelope. The event-specific data lives under data; the surrounding fields identify and timestamp the delivery.

FieldTypeDescription
idstring (UUID)Unique identifier for this callback delivery. Use it to de-duplicate — Flywire may deliver the same event more than once.
occurredOnstring (ISO-8601)When the event occurred.
dataobjectEvent-specific payload. Its shape depends on the callback type — see the per-callback pages below.
json
{
  "id": "9f1c8d7e-2a3b-4c5d-8e6f-0a1b2c3d4e5f",
  "occurredOn": "2026-03-15T08:55:00Z",
  "data": {
    "...": "event-specific fields"
  }
}

Headers ​

Each callback request carries the following headers:

HeaderDescription
Content-Typeapplication/vnd.flywire.<type>+json;version=<version> — a vendor media type identifying the event and its version. For example, application/vnd.flywire.payment.status.updated+json;version=1.0.
Message-SignatureA Base64-encoded HMAC-SHA256 signature of the raw request body, keyed with your agency API key. Use it to verify the callback genuinely came from Flywire. See Verifying signatures.
Custom auth headerIf configured for your agency, Flywire adds an additional authentication header (for example an API-key header) with a value you provide. Use it as a second layer of verification.

Verifying signatures ​

The Message-Signature header lets you confirm a callback is authentic and untampered. Compute Base64(HMAC-SHA256(apiKey, rawRequestBody)) over the exact bytes of the request body and compare it against the header value using a constant-time comparison.

The signing key is your agency API key — the same key you send as X-Authentication-Key on inbound requests (see Authentication).

WARNING

Verify against the raw request body exactly as received. Re-serializing the parsed JSON can change whitespace or key order and produce a different signature.

python
import base64
import hashlib
import hmac

def is_signature_valid(api_key: str, raw_body: bytes, signature_header: str) -> bool:
    expected = base64.b64encode(
        hmac.new(api_key.encode(), raw_body, hashlib.sha256).digest()
    ).decode()
    return hmac.compare_digest(expected, signature_header)
javascript
import crypto from "node:crypto";

function isSignatureValid(apiKey, rawBody, signatureHeader) {
  const expected = crypto
    .createHmac("sha256", apiKey)
    .update(rawBody)
    .digest("base64");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Configuration ​

Callbacks are set up with Flywire on a per-agency basis. The relevant settings are:

SettingDescription
Callbacks enabledA flag that turns outbound callbacks on for your agency. When disabled, no callbacks are sent.
Default callback URLThe endpoint Flywire delivers callbacks to.
Allowed callback domainThe callback URL must match this domain — a safeguard against misconfigured or unexpected destinations.
Custom auth header (optional)An extra authentication header (name and value) added to every callback request.

Contact Flywire to enable callbacks and register your endpoint.

Delivery and retries ​

Flywire uses your HTTP response status to decide whether a callback was accepted:

ResponseOutcome
2xxAccepted. No further delivery attempts.
4xx (except 429)Rejected. The callback is not retried.
429 or 5xxTreated as a transient failure and retried.
Network error / timeoutTreated as a transient failure and retried.

To integrate reliably:

  • Respond quickly with a 2xx. Acknowledge receipt first, then do heavier processing asynchronously so you don't risk a timeout and an unnecessary retry.
  • Be idempotent. Because an event may be delivered more than once, use the envelope id to recognize and ignore duplicates.
  • Verify every callback. Check the Message-Signature (and any custom auth header) before acting on the payload.

Available callbacks ​

CallbackEvent typeDescription
Payment Status Updatedpayment.status.updatedSent when a payment is recorded or its status changes.

TIP

More callback types will be documented here over time. If you rely on an event that isn't listed yet, reach out to Flywire.

Flywire Agents API Documentation