FX-Port API

Security

How to keep your FX-Port integration secure — key handling, booking authorization, and general API security hygiene.

An FX-Port API key with Read+Write permission can create bookings and trigger real financial debits from your agency balance. Treat it with the same care as a payment credential.

Always keep keys server-side

Never expose your FX-Port API key in:

  • Browser JavaScript (React client components, Vue, Angular, plain JS)
  • Mobile apps (React Native, Expo, Flutter, native iOS/Android)
  • Public repositories, commit history, or CI/CD environment variables visible in build logs
  • Client-side .env files shipped with a compiled app

Your app's backend (Node.js, Python, Go, etc.) should be the only code that ever reads and uses the FX-Port API key. If your front-end needs to trigger a booking, it should call your own authenticated backend, which then calls FX-Port on the user's behalf.

Browser/App  →  Your backend  →  FX-Port API

           API key lives here only

Minimal-permission keys

Use a Read-only key for integrations that only display search results, balances, or status. Reserve the Read+Write key for the backend service that actually creates bookings. See Authentication for what each permission level allows.

Key rotation

Rotate keys immediately if you suspect a leak. The dashboard lets you invalidate and replace a key without downtime. Rotate on a routine schedule too (e.g. every 90 days) rather than only after an incident — routine rotation limits how long a silently-leaked key stays useful to an attacker.

Enforce booking ownership in your own backend

FX-Port scopes every response to the agency that owns the API key — one agency's key can never return another agency's bookings, balances, or account data. But that only protects the FX-Port API boundary. If your own application lets multiple end-clients share one FX-Port key (a common pattern), you are responsible for authorization inside your own backend so one client cannot view, modify, or cancel another client's booking.

A booking reference, order ID, ICCID, or PNR is not a secret — it can be guessed, enumerated, logged, or leaked through a shared link. Never treat "the caller supplied a valid booking ID" as proof that the caller is entitled to see it. Concretely:

  • Store which of your own end-users/clients created or is entitled to each booking (a client_id / user_id column alongside the FX-Port booking_id you save).
  • On every read or mutation your backend exposes (get booking, get ticket, cancel, pay, request a refund, view usage, etc.), check that the authenticated caller in your system owns that booking before forwarding the request to FX-Port — do not rely on the booking ID alone as an access-control token.
  • Apply the same rule to balances, transaction/financial history, and account data: scope every query by the authenticated caller's own identity, never by an ID taken directly from the request path or query string.
  • If you use a database with row-level security (Supabase, Postgres RLS, etc.), enforce this at the database layer as well as in application code — defense in depth. A backend bug that forgets an owner_id filter should not be enough, on its own, to expose another client's data.
  • Test this explicitly: as client A, try to fetch/cancel a booking that belongs to client B by ID. It should fail with 403/404, not succeed. Treat this as a required test case for every booking, balance, and account endpoint you expose — for flights, hotels, eSIMs, and any other product — not an edge case to defer.

This is Broken Object Level Authorization (OWASP API Security Top 10, API1:2023) — the single most common vulnerability class in booking/travel APIs. It is entirely preventable with a per-request ownership check and is far cheaper to build in from day one than to retrofit after a data leak.

Validate and sanitize webhook/callback payloads

If you build a webhook receiver or callback endpoint for booking status updates, treat every incoming payload as untrusted input, not as fact:

  • Verify a signature/secret on every callback before acting on it, rather than trusting the sender because the request "looks right".
  • Re-fetch authoritative state from the FX-Port API before making a financial or booking decision based on a webhook payload, instead of trusting fields inside the webhook body directly.
  • Make callback handlers idempotent — a retried or duplicated webhook delivery should not double-book, double-refund, or double-charge.

Rate limiting and abuse protection

Search and pricing endpoints are inexpensive to call but not free to abuse:

  • Apply your own rate limiting in front of any public-facing feature that triggers an FX-Port call on user input (a search box, a price checker), so a single abusive user or bot can't exhaust your key's rate limit or run up unnecessary supplier calls.
  • Cache read-only, non-personalized responses (e.g. suppliers or airports) client-side or at your edge where appropriate, instead of re-querying on every page load.

Logging and data retention

  • Never log full API keys, even in debug/error logs — log a short prefix (fxp_live_ab12…) if you need to identify which key made a call.
  • Avoid logging full traveler PII (passport numbers, full card/payment details) in plaintext application logs. If you must retain it for support, encrypt it at rest and restrict access.
  • Apply a retention policy to logs and cached search/pricing responses containing personal data, rather than keeping it indefinitely by default.

Broader security hygiene

These rules apply to every sensitive credential in your application stack, not just FX-Port keys.

  • Supabase / database API keys — never expose the service_role key in a browser or mobile app. Only the anon key can be used client-side, and even that should be behind Row-Level Security policies.
  • Third-party vendor keys (Stripe, Twilio, etc.) — always consumed server-side. A leaked Stripe secret key or Twilio auth token can cause direct financial loss.
  • WordPress and open-source CMS plugins — themes and plugins are a frequent attack vector. Credentials stored in a WordPress database are regularly exfiltrated through plugin vulnerabilities. If you run a CMS alongside your booking integration, keep credentials in separate, isolated infrastructure and audit installed plugins regularly.
  • Dependency CVEs — keep your runtime and framework versions current. Subscribe to security advisories for your stack (nodejs.org/en/security, github.com/advisories) and apply patches promptly.
  • Least privilege everywhere — the same "minimal-permission key" principle above applies to cloud IAM roles, CI/CD service accounts, and internal admin tooling. A credential should only be able to do what its specific job requires.

Questions?

Found a vulnerability or want a security review of your integration? Email [email protected].

On this page