Skip to main content
Every v3 response (success or error) carries an X-Trace-Id and an X-Request-Timestamp. X-Trace-Id is OpenFX’s correlation handle for the request. Log it on every call so you can stitch together your own logs across retries and services, and give OpenFX support the trace they need. For your own per-call correlation, send an optional X-Request-Id header. See Client request correlation. FX withdrawals additionally accept a persistent metadata object in the body that outlives the single request. See Withdrawal metadata.

Response headers

Server-side and client-side correlation are separate headers. X-Trace-Id is the server-generated request identifier, present on every response; there is no server requestId field in the response body. X-Request-Id is the client-side equivalent: optional, and echoed back only when it matches the required format. See Client request correlation. If you need a body-portable copy of the server handle (for queued retries or webhook envelopes that lose HTTP headers), capture X-Trace-Id into your own log record at call time.

Client request correlation

X-Trace-Id is the server’s correlation handle. For your own per-call correlation, send an optional X-Request-Id header on any request: X-Request-Id is independent of X-Trace-Id: it’s client-generated and lives in headers on both the request and the response when valid, for the lifetime of that one HTTP round-trip. There is no server-generated requestId field in any response body.
X-Request-Id vs X-Trace-Id. X-Request-Id is your correlation value, chosen by your client and echoed back only when you send it. X-Trace-Id is OpenFX’s debug/trace handle, present on every response (success and error) whether or not you sent an X-Request-Id. Include both when you log, and quote X-Trace-Id when filing a support ticket.

Withdrawal metadata

For bookkeeping that should persist with the resource (not just the one request/response round-trip), POST /v3/fx/withdrawals accepts an optional metadata object in the request body. This is a separate mechanism from X-Request-Id: X-Request-Id is per-call and lives in headers; metadata is per-resource, persists with the withdrawal, and travels in the body. Within the FX API (/v3/fx/...), metadata is accepted only on POST /v3/fx/withdrawals. The Payments API accepts its own metadata object on create account, create payout address, create payout quote, and create payout, with the same key-count, key-length, value-length, and total-size limits as below. Payments metadata keys are also limited to letters, digits, and underscores. It is a general-purpose, client-owned bag: keys are client-defined strings (for example metadata.customerId, metadata.reconId). All values must be strings. The server treats metadata as opaque pass-through: it enforces only size and structure limits, never interprets the contents, persists it with the withdrawal, and returns it nested inside the resource at data.metadata on the success response, not as a top-level sibling of data. Limits: at most 50 keys, each key ≤ 40 characters, each value ≤ 500 characters, and the serialized object under 8 KB. A request that exceeds any of these limits is rejected with 400 VALIDATION_BODY_FAILED.
Request: POST /v3/fx/withdrawals
The success response nests the Withdrawal resource inside data, with metadata nested inside it, not as a sibling of data:
Success response: metadata nested inside data.metadata, not a sibling of data
Metadata is visible in the OpenFX platform, API, and MCP server, including connected AI tools. Don’t include sensitive or personal data in metadata.
metadata is set at creation and can’t be changed afterward. v3 has no PATCH endpoints, so a withdrawal’s metadata is fixed once the withdrawal is created. It is also not currently filterable on GET /v3/fx/withdrawals. Fetch and filter client-side.
metadata is returned on success responses only. It is never echoed on error responses. An error envelope carries code, type, message, and details, with no metadata. To correlate a failed call, read the X-Trace-Id response header (and your own logged copy of the metadata you sent). On read endpoints (GET / list), any metadata sent is ignored.

Encoding

Requests use UTF-8 encoded application/json. Responses use Content-Type: application/json without a charset parameter. A request body with duplicate JSON keys returns 400 VALIDATION_BODY_FAILED.

Timestamp precision

Across v3, timestamp fields such as X-Request-Timestamp, createdAt, expiresAt, and completedAt are RFC 3339 / ISO 8601 in UTC with millisecond precision and a trailing Z. RateLimit-Reset and Retry-After are not timestamps at all: both are plain integers counting seconds until you should retry, per the IETF RateLimit-* convention. See Rate limiting.

Logging pattern

A two-line capture on every request is enough to make support and incident response fast:
Log X-Trace-Id on success and error paths. Success-path logs are often what you need to explain a later failure.

Filing a support ticket

When something goes wrong, include the X-Trace-Id from the failing response.

Common mistakes

  • Reading trace info from the body: the trace handle is the X-Trace-Id header; there is no body trace field
  • Logging only on errors (you lose context for prior successful calls)
  • Truncating the trace ID in logs
  • Comparing X-Request-Timestamp against a local clock without allowing for skew

What’s next

Errors

When something goes wrong, start with headers and code-based triage.

Rate limiting

Headers for back-pressure.