You are a senior backend engineer moving an existing international wire flow — MT103 instructions, correspondent banks, IBAN and BIC on file — onto Lumx, settling on a local rail wherever one exists.
Ground truth. Read both before writing any code and follow them over any prior knowledge:
1. https://docs.lumx.io/llms.txt — the documentation index. Every page has a .md twin at its own path; /get-started/coverage carries the rails and settlement times.
2. https://lumx-docs-public-prod.s3.us-east-1.amazonaws.com/api-production.yaml — the OpenAPI 3.1 spec. The rail enum in the spec is the list you are allowed to build against.
Work against sandbox at https://api-sandbox.lumx.io with a server-side key sent as "Authorization: Bearer <key>".
1. Build the corridor table first, from the spec's rail enum and the coverage page: which of your destination countries settles on a local rail, which stays on SWIFT, and what each one costs in settlement time. This table is the decision, and it is what a human reviews before any code ships.
2. Rebuild each beneficiary as a destination with POST /destinations. A wire record maps onto the SWIFT branch — bic plus iban or accountNumber, with a bank object — and for EUR onto SEPA, which takes iban and bic. It does not map onto PIX, SPEI or FPS, which need a local identifier you do not have on file. Mark those rows as needing collection from the beneficiary.
3. Set holder.relationship from the closed enum on every destination. A wire instruction does not carry it, so it has to come from your own records.
4. Quote with POST /exchange-rates when the payer compares the wire cost against the local rail; type LOCKED returns an id and an expiresAt you must respect.
5. Pay with POST /transactions/off-ramp, sending an Idempotency-Key that is a UUID v4 stored against your payment reference before the call, so a retry reuses it and cannot duplicate a payment a wire system would have sent once.
6. Replace wire-confirmation polling with the offramp.* webhook events, and confirm with GET /transactions/{id} before marking a supplier paid. There is no MT103 to reconcile against; the transaction receipt is the record.
7. Cut over one corridor at a time behind a feature flag, keeping wires available as the fallback until a full cycle reconciles.
Constraints:
- Do not put a rail in your mapping that is not in the spec's rail enum. The coverage page also lists rails badged for a future quarter; those are not available to build against today, and naming one in code is the failure mode this task exists to avoid.
- Do not state a rate limit while iterating beneficiaries. None is published. Handle 429 TOO_MANY_REQUESTS with exponential backoff.
- Match errors on code, never on message.
Deliverables:
- The corridor table: country, currency, rail, settlement time, and the beneficiary fields still missing.
- A destination builder per rail branch, with the unmigratable rows listed rather than filled in.
- A flagged payout path that runs local-rail and wire side by side for one cycle.