Keep the receipt and the conversion separate
An expense preview shows the equivalent amount at the ECB reference rate for a stated reference date. Keep the receipt amount and original currency immutable. Add separate converted amount, reference date and rate fields so the rounded display value never replaces accounting evidence.
Use one request identity for one intent
Generate one Idempotency-Key per expense conversion intent and retain it alongside the input fingerprint. Reusing it for changed parameters should fail. After a timeout, inspect the existing request state; a new key is not a harmless retry because the operation may already have run.
Reconcile weekends explicitly
For a Saturday receipt, historical or convert may return a Friday reference date. Present both the requested day and the actual response date. Decide with your accounting policy whether that fallback is acceptable; do not silently relabel a Friday rate as Saturday.
Round once, at your display boundary
Keep the input amount, rate and unrounded result in the preview model. Select a currency-aware decimal rounding rule before generating accounting entries. JavaScript binary floating point in these examples is not a monetary ledger and must not be used to calculate wallet credits.
Turn one response into a preview
The code below turns one convert response into a preview record that keeps the original amount and currency, the reference date and the requested date side by side. A code absent from rates, or a stop_reason, needs an explicit user-visible state, never a zero substitute.
// Example convert response: 100 USD requested for Saturday 2024-01-06 uses the Friday 2024-01-05 reference rate.
const response = { ok: true, data: { from: 'USD', to: 'EUR', amount: 100,
rate: 0.9, result: 90, date: '2024-01-05', requested_date: '2024-01-06' } };
if (!response.ok || !Number.isFinite(response.data.result)) throw new Error('Invalid preview');
const preview = { originalAmount: response.data.amount, originalCurrency: response.data.from,
referenceDate: response.data.date, requestedDate: response.data.requested_date,
indicativeAmount: response.data.result, targetCurrency: response.data.to };
console.log(preview); // Original amount and currency, both dates and the converted amount, kept side by side.
Server-side request template
This server-side template shows authentication and request identity using the first operation of this API. Choose the operation for your use case and check its current availability and price on the API page. After a timeout, resend the unchanged request with the same Idempotency-Key.
The gateway request is always POST.
Use the documented flat JSON object. Keep the fields at the top level; do not wrap them in body.
# Server-side only. Set ATLAS_API_KEY in your secret manager.
# Set ATLAS_API_ORIGIN to your configured deployment origin.
# Every gateway operation is called with POST.
# Only operations shown as enabled on the API page can be called.
# Generate once per intent; retain the same value on status checks.
REQUEST_ID="$(uuidgen)"
curl --request POST 'https://apigate.vercel.app/api/v1/currency/latest' \
--header "Content-Type: application/json" \
--header "x-api-key: $ATLAS_API_KEY" \
--header "Idempotency-Key: $REQUEST_ID" \
--data '{"base":"EUR","symbols":"USD,GBP,JPY"}'Integration checklist
- The API key is stored in a server-side secret manager and never sent to a browser.
- Each request carries its own Idempotency-Key, kept until the request has a final answer.
- The integration reads ok and error.code and handles each error code as the error table describes.
- An uncertain POST is inspected using its original identity, never blindly repeated with a new one.
- The operation’s current availability and price have been checked on its API page.