Platform guide

How FxPortal Works

A plain-language walkthrough of the complete consumer → broker loop. Three audiences, one flow.

Finding and locking the best rate

Everything a remittance customer does from landing on the site to receiving their broker's final quote.

1
Choose your corridor and enter an amount
The consumer goes to /compare and selects where they're sending from (UK, US, Canada, or Australia) — all routes lead to Nigeria for now. They enter the amount they want to send. The page shows live rates from every registered broker, refreshed every 30 seconds.
2
Compare brokers side-by-side
Each broker row shows the rate (NGN per unit of source currency), any fee, and the total NGN the recipient receives. The table is sorted so the best total always comes first. Consumers can click a broker name to read the trust profile — FCA registration, response time, monthly volume, recent activity.
See an example broker profile →
3
Click "Lock this rate" and enter their email
A modal opens with a quote summary (broker name, amount, rate, recipient total). The consumer enters their email address and optionally the recipient's name. On submit, a POST /api/quotes call fires. The consumer gets a confirmation email immediately. A broker rep gets notified within minutes.
4
Wait for the broker's response
The broker receives the quote in their inbox (/broker/quotes?broker_id=1), claims it, and sends a final rate. The consumer receives an email with the final rate, their transfer amount, and any notes from the broker. They then fund the transfer directly with the broker via bank transfer.
Important: FxPortal is a marketplace, not a transfer service

FxPortal connects consumers to brokers. We don't hold funds, initiate transfers, or take custody of money. Once a consumer locks a rate, the transaction happens directly with the broker. FxPortal's role ends at introducing the two parties.


Receiving and managing quotes

What a broker does when a quote lands in their inbox.

Consumer locks rate
Postmark email to consumer
Quote appears in broker inbox
Broker claims
Broker sends final rate
Consumer notified
1
Access your quote inbox
Open /broker/quotes?broker_id={id} — substitute your broker ID. You see all incoming quote requests, filterable by status: pending (not yet claimed), quoted (claimed and responded to), won, or lost. Pending quotes are shown first.
2
Read the quote details
Click any quote to see the full detail: consumer's email, the source currency and amount, the rate they locked at, and the corridor. If the consumer added a recipient name, that's shown too. Use this to decide whether to quote.
3
Claim the quote to mark it as yours
Clicking Claim sets the quote status from pending to quoted and records claimed_at. Only one broker can claim a quote (the consumer chose one broker when they locked the rate). Claiming signals to your team that the lead is live.
4
Send your final rate
Enter the final rate you're willing to transact at, plus an optional note (e.g. "Rate valid for 2 hours — please transfer before 3pm GMT"). On submit, Postmark sends a response email directly to the consumer with your quoted rate and notes. The quote is marked as responded.
5
Mark won or lost
Once the consumer and broker complete the transfer offline, mark the quote as won (transfer happened) or lost (consumer went elsewhere). This keeps your pipeline clean and gives FxPortal data on broker conversion rates.

What the confirmation emails look like

There are two automated emails in the loop, both sent via Postmark through the Polsia email proxy.

Email 1 — sent to consumer
Subject: Your rate is locked — {amount} {source} → NGN
Trigger: Consumer clicks "Lock this rate"
From: FxPortal <hello@fxportalos.polsia.app>

Hi,

Your rate has been locked with {broker_name}. A broker representative will be in touch within 24 hours.

This rate is indicative. The final rate will be confirmed by the broker directly.

Compare this rate against others at fxportalos.polsia.app/compare

Email 2 — sent to consumer (broker response)
Subject: {broker_name} has responded to your quote
Trigger: Broker enters a final rate in /broker/quotes
From: {broker_name} via FxPortal <hello@fxportalos.polsia.app>

Hi{recipient_name ? ', ' + recipient_name : ''},

{broker_name} has sent their final quote for your transfer:

The broker will contact you directly to complete the transfer. Please reply to this email or use the contact details provided to fund the transfer.


Adding a new broker to the database

New brokers are added via a direct SQL migration or by running the seed script. Broker rates are managed separately in broker_rates.

1
Create a migration file
Add a new file in migrations/ following the naming convention {unix-timestamp}_{name}.sql. The migration runs automatically on every deploy via npm run migrate.
-- migrations/1750000000_add_new_broker.sql
INSERT INTO brokers (name, rating, active, slug, fca_reg_number,
                     years_operating, avg_response_minutes, monthly_volume_gbp,
                     rating_count, about, supported_corridors)
VALUES (
  'ClearFX UK',         -- name
  4.7,                      -- rating (1–5)
  't',                       -- active flag
  'clearfx-uk',            -- slug (URL-safe, unique)
  '123456',                 -- fca_reg_number
  8,                         -- years_operating
  15,                        -- avg_response_minutes
  2400000,                   -- monthly_volume_gbp
  312,                       -- rating_count
  'Specialist in GBP/NGN transfers with FCA authorisation.',
  'GBP/NGN,USD/NGN'    -- supported_corridors (comma-separated)
);
2
Add broker rates
Each broker needs at least one row in broker_rates per corridor they operate in. Run this after inserting the broker — use the broker's id from the insert above.
INSERT INTO broker_rates (broker_id, currency_pair, rate, spread, volume_24h)
VALUES
  ((SELECT id FROM brokers WHERE slug = 'clearfx-uk'),
   'GBP/NGN', 1995.50, 0.45, 850000),
  ((SELECT id FROM brokers WHERE slug = 'clearfx-uk'),
   'USD/NGN', 1550.00, 0.50, 420000);
3
Push and deploy
The migration runs on the next npm run migrate (called automatically after each deploy). The broker will appear on /compare immediately after, and their trust profile becomes available at /broker/{slug}.
Bulk broker setup

If you're adding several brokers at once, edit seed-brokers.js and run node seed-brokers.js once. The seed script uses the same INSERT pattern and can be run against a live DB. It's a one-off — don't leave it in automated deploys.


URL cheat sheet

Consumer-facing rate comparison table. Select corridor, enter amount, lock rate.
SEO corridor pages (uk-to-nigeria, us-to-nigeria, canada-to-nigeria, australia-to-nigeria). Live broker table + FAQ.
Broker quote inbox. Filter by status, claim quotes, send final rates.
Public broker trust profile. FCA badge, rating, volume, response time, recent activity.
/onboarding (you're here)
This page. The master guide for consumers, brokers, and admins.
/admin/rates
Admin dashboard — internal use only. Shows broker rates, spread, 24h volume.