Payment methods

How global and per-user P2P payment methods work, what the metadata field is actually for, why details are snapshotted onto a trade, and what blocks a deletion.

5 min readUpdated 6 August 2026payment-methods, offers

A P2P payment method is a label plus a set of instructions telling the buyer how to send fiat. That is all it is. Nothing here connects to a bank, verifies a transfer or reconciles anything — the platform holds crypto and arbitrates, and the fiat leg happens entirely between the two people.

Every published offer must name at least one, so this list is a prerequisite for having a marketplace at all.

A method and a trader's details are two different records

This is the single most important thing to understand on this page, and it changed in 6.2.5.

A payment method used to be one row carrying two unrelated things: the identity — "PayPal" — and one trader's own credentials. So every trader who accepted PayPal created another row named PayPal, and the marketplace filter (which groups on the row) ended up with one "PayPal" entry per trader. A taker who picked one narrowed the whole board to a single maker without being told.

They are separate records now:

The rail (shared) The trader's details (private)
What it holds The name, and the fields a buyer must be given One trader's actual account information
Who sees it Everyone — it is the filter entry Only the counterparty, and only once a trade opens
Managed at /admin/p2p/payment-rail The trader's own payment methods
How many One per real-world method One per trader who uses it

The filter groups on the rail, so PayPal is one entry however many people accept it.

An offer still points at the trader's own record, and a trade still copies that record's details at the instant it opens. No live offer changed and no settled trade was rewritten — only the grouping above them is new.

Two kinds

Global Personal
Created at /admin/p2p/payment-method the user's own P2P settings
userId on the row null the owner
isGlobal true always false
Who can attach it to an offer everyone only the owner
Who can edit or delete it admins the owner, and admins
Default sort rank whatever you set 999, so personal methods list after global ones

A user may hold up to 20 personal methods, and may not have two with the same name. They can reuse the name of a global method — a user's "Bank Transfer" carrying their own account details is a different thing from yours.

Personal method creation is rate-limited to 15 per hour.

Seed the global list first

An empty payment-method list means nobody can publish an offer. Before you announce P2P, create the methods your market actually uses.

Each global method takes:

Field Required Notes
name yes 2–50 characters
icon yes an icon reference or URL
description no up to 200 characters, shown in listings
instructions no up to 500 characters — how to actually pay
metadata no key/value payment details, see below
processingTime no free text, e.g. "instant", "1–2 business days"
fees no free text, informational only — the platform charges nothing here
available no off takes it out of circulation without deleting it
popularityRank no lower sorts first

It exists so a maker can warn takers that a rail costs the sender something. The platform's only fee is the escrow fee on the crypto side. Nothing reads this field to compute money.

Personal methods created by users go through a stricter validator: the name is sanitised and length-checked, and the icon is matched against an allowlist (credit-card, bank, wallet, cash, bitcoin, ethereum, paypal, venmo, zelle, wire-transfer), falling back to credit-card. Description, instructions and processing time are truncated at 200, 500 and 50 characters.

The metadata field

This is the part that does real work, and the part that gets misused.

metadata is a free-form map of up to 20 key/value pairs, keys capped at 100 characters and values at 500. It is where the actual payment coordinates live:

{
  "Bank name": "Example Bank",
  "Account holder": "A. Trader",
  "IBAN": "GB00EXMP00000000000000",
  "Reference": "Use the trade ID"
}

Keeping details here rather than mashed into instructions is what lets the trade room render them as a labelled list the buyer can copy, and it is what gets snapshotted onto the trade.

Metadata on a global method is visible to every user who attaches it. Put generic guidance there — which reference to quote, what the rail is called — and leave the account numbers to personal methods, where they belong to the maker who typed them.

What the taker sees, and when

When a trade is opened, the selected method's name, icon, instructions, processing time and all of its metadata are copied onto the trade as paymentDetails.

That copy is deliberate. If the maker later edits their bank details, or the method is edited by an admin, or it is switched to unavailable, the running trade still shows exactly what the buyer agreed to pay against. It also means the record of an old trade survives the method being deleted.

The snapshot is the agreement. A counterparty who posts different account details in the trade chat after the trade opens is running the single most common P2P fraud there is. Support should treat "I paid the details they sent me in the chat" as a red flag, not as evidence of payment.

Availability

available: false hides a method from new use. Trade initiation checks it — a taker cannot open a trade on a method that is no longer available, even if the offer still lists it.

Use this rather than deletion when a rail goes down temporarily. Deleting is final for the user's list; unavailability is reversible and leaves running trades alone.

What blocks a deletion

Deleting a personal method is refused while it is in use:

  • Used by an offer in ACTIVE, PENDING_APPROVAL or PAUSED — the error names how many offers, and the user must detach it from those offers first.
  • Used by a trade in PENDING, PAYMENT_SENT or DISPUTED — the user has to wait for those trades to finish.

A user can only delete their own methods; global methods are refused outright with a 401 message saying so.

Deletion is a soft delete, so historical rows keep resolving.

Admins deleting a global method from /admin/p2p/payment-method should check the offers using it first — offers keep the association, and a taker on such an offer will find the method missing at initiation.

Choosing which methods to offer

Two operational points worth thinking about before you seed the list.

Reversible rails are where disputes come from. Card payments and anything with a chargeback window let a buyer take their money back long after the crypto has gone, and the trade is terminal by then. If you allow them, expect fraud cases; many operators simply do not list them.

One method per rail, not one per bank. A list with forty near-identical entries makes the market board's payment filter useless. Keep the global list short and let makers put their specifics in personal methods.

Where they appear

Surface What it shows
Offer creation The maker's attachable methods — global plus their own
Market board filter One entry per rail, not per trader
Trade room The snapshot: instructions, processing time and every metadata pair
/admin/p2p/payment-method Every method, global and personal, with the owner
/admin/p2p/payment-rail The shared rails the public filter is built from
/admin/p2p/payment-method/setup The setup console — field shapes for the common rails

When a trader's own method reaches the public filter

A rail a trader defines themselves does not go straight into the filter every visitor sees. It:

  • works immediately, on their own offers
  • is findable by name by the next trader who needs the same thing
  • shows on the offers that carry it

It enters the public filter only when more than one maker is using it, or when you list it yourself in Admin → P2P → Payment Rails.

That threshold is what stops the filter refilling with one-off entries — which is the problem the split was made to solve.

The setup console

/admin/p2p/payment-method/setup ships field shapes for the rails most operators already have: bank transfer, SEPA, PayPal, Wise, Revolut, Zelle, Cash App, UPI, IMPS/NEFT, Pix, M-Pesa, Mercado Pago, GCash, Papara and cash in person.

Anything else has its fields inferred from what traders using it have actually filled in, and you can correct any of it afterwards.

The console refuses everyone except a Super Admin until you grant the payment-method permissions in Admin → Roles. Do that before handing the screen to whoever runs your payment operations.