Skip to content
FX-Port/Docs
GuidesAPI referenceChangelog
Get API keys
  • Introduction
  • Quickstart
  • Security
  • Authentication
  • Environments and Postman
  • Sandbox
  • Conventions and naming
  • Legacy names and twins
  • Errors
  • Rate limits and fair use
  • Streaming search results
  • Use these docs with AI

Get started

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 callback payloads

FX-Port does not send webhooks to API customers: poll a booking for its status. But if your application receives callbacks from anyone (a payment provider, your own front-end, a partner), 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 callback payload, instead of trusting fields inside the callback body directly.
  • Make callback handlers idempotent — a retried or duplicated delivery should not double-book, double-refund, or double-charge.

Links to tickets, vouchers and documents are not private

The links the API returns for files (bucket_link and voucher_url for tickets and vouchers, download_url for uploaded ACD documents) are plain HTTPS links that open without a key. Anyone who has the link can read the file, and a ticket, a voucher or a passport scan holds personal data.

  • Treat each link like a secret: do not put it in a public page, an e-mail to a third party, a URL that gets logged or an analytics event.
  • Serve files to your own users through your authenticated backend (fetch the link server-side and stream it, after your ownership check) instead of handing the link to a browser.
  • Do not keep the links for longer than you need them: fetch the booking again when you need a fresh one.

Rate limiting and abuse protection

FX-Port limits each key per minute (see Rate limits) and refuses malformed requests before they reach a supplier. 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.
  • Log the request_id of every FX-Port call (the X-Request-Id header, also in every body) next to your own ids: it is what support needs to find a request.
  • 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].

PreviousQuickstartNext Authentication

On this page

  • Always keep keys server-side
  • Minimal-permission keys
  • Key rotation
  • Enforce booking ownership in your own backend
  • Validate and sanitize callback payloads
  • Links to tickets, vouchers and documents are not private
  • Rate limiting and abuse protection
  • Logging and data retention
  • Broader security hygiene
  • Questions?

© 2026 FX-Port

TermsPrivacy[email protected]