Marqeta & Airwallex
The Seller Card was originally issued by Marqeta and is being migrated to Airwallex. Both are live simultaneously, so the client must present a coherent "Your Cards" experience across two very different integrations.
The business rules are in Seller Card; this page covers the integration mechanics.
Marqeta
Module |
|
Modelled as |
A payment method — lives in the |
Status enum |
|
Form factor |
|
Key |
|
Because it is a payment method, Marqeta card actions and payout-method actions
share a slice. Actions such as sellerCardRequest, sellerCardSuccessResponse,
sellerCardActivate and sellerCardActivateSuccess sit alongside
savePaymentMethod and makePaymentMethodAsDefault.
instrument_type is a free-form string, normalized with a substring check:
const marqetaFormFactor = (instrumentType: string | undefined): string =>
(instrumentType ?? '').toUpperCase().includes('VIRTUAL')
? PCardTypeIndicator.Virtual
: PCardTypeIndicator.Physical;
Values like PHYSICAL_ICC and VIRTUAL_PAN therefore both resolve correctly, and
anything unrecognised defaults to physical.
Airwallex
Base URL |
|
Service |
|
Modelled as |
A card — lives in the |
Status enum |
|
Form factor |
|
Key |
|
Endpoints
|
Unified list across both issuers, each entry tagged with |
|
Which issuers and form factors the supplier may order. |
|
Cardholder consent status ( |
|
Record consent. |
|
Order a card. |
|
Short-lived token for revealing the PAN. |
|
Suspend, with |
|
Activate or unblock. |
|
|
Consent
/**
* Persist the supplier's acceptance of the Airwallex cardholder terms + privacy policy.
* Must be recorded before a card is ordered — if this fails, the order must not proceed.
*/
saveConsent(supplierKey: string): Observable<void> {
return this.http.post<void>(`${this.env.apiUrl}/suppliers/${supplierKey}/airwallex/consent`, {});
}
Consent is required both for new Airwallex cards and for migrating existing
Marqeta cardholders. The migration path is delivered as the
airwallex_pcard_terms dashboard notification.
Order request shaping
newCard(supplierKey, { provider, formFactor, recipientAddress, expediteCard }) {
return this.http.post(`${this.env.apiUrl}/suppliers/${supplierKey}/cards/newcard`, {
provider,
form_factor: formFactor,
...(recipientAddress ? { recipient_address: recipientAddress } : {}),
...(expediteCard != null ? { expedite_card: expediteCard } : {}),
});
}
recipient_address and expedite_card are omitted for Airwallex, which ships to
the cardholder address already on file. Only issuers with physical shipping —
Marqeta — receive them.
The unification layer
core/pyb/interfaces/unified-supplier-card.interface.ts maps both issuers onto
UnifiedSupplierCard with a common status, form factor, label keys and colours,
retaining the original model in raw so actions can be routed correctly.
Status normalisation:
UnifiedCardStatus |
PCardStatus |
AirwallexCardStatus |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
When a Marqeta card appears in /cards without a matching payment method,
synthesizeMarqetaPaymentMethod() fabricates a minimal stand-in carrying the
card token. That is sufficient for block and activate; the view details flow
needs a real paymentConfigKey and is only offered when a genuine payment method
was matched.
Card data handling
|
The application never handles a raw PAN, CVV or PIN. Card details are revealed
through a provider-issued short-lived token ( |
Decline codes
NetworkResponseCodeEnum maps roughly thirty issuer decline codes to explanatory
copy — expired card, lost or stolen pick-up, insufficient funds, limit exceeded,
CVV failure, account blocked, suspected fraud, closed account, and the
Mastercard Send-specific ZN / ZD / ZR codes. See
Enum Reference.