Issue and Manage a Card

Issue virtual and physical payment cards linked to user wallets.

Before You Start

Read the following guides before proceeding:

GuideWhy
Getting StartedPlatform overview and setup
Api BasicsRequired headers and request configuration
AuthenticationHow to obtain access tokens
OnboardingUser and wallet registration
KYCKYC verification requirements

Overview

Wirex BaaS supports issuing Visa payment cards linked to user Smart Wallets. Cards can be:

  • Virtual — Digital cards for online payments, issued instantly
  • Physical — Plastic cards delivered to the user's address

Cards are funded from the user's unified balance (WUSD/WEUR) and can be used anywhere Visa is accepted.


Prerequisites

Before issuing a card, check user eligibility via the user endpoint. Capabilities are returned as part of the user response.

GET /api/v2/user
const response = await fetch(`${baseUrl}/api/v2/user`, {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});
const user = await response.json();

const virtualCardCapability = user.capabilities.find(c => c.type === 'VisaVirtualCard');
if (virtualCardCapability?.status === 'Active') {
  // User can issue virtual cards
}
import requests

response = requests.get(
    f"{base_url}/api/v2/user",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id
    }
)
user = response.json()

virtual_card = next((c for c in user["capabilities"] if c["type"] == "VisaVirtualCard"), None)
if virtual_card and virtual_card["status"] == "Active":
    # User can issue virtual cards
    pass
req, _ := http.NewRequest("GET", baseURL+"/api/v2/user", nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var user UserResponse
json.NewDecoder(resp.Body).Decode(&user)

for _, cap := range user.Capabilities {
    if cap.Type == "VisaVirtualCard" && cap.Status == "Active" {
        // User can issue virtual cards
    }
}

Response (relevant fields):

{
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "user_address": "0x1234567890abcdef1234567890abcdef12345678",
  "verification": {
    "status": "Approved",
    "levels": [
      {
        "status": "Approved",
        "type": "SDD",
        "name": "Wirex SDD Level"
      }
    ]
  },
  "capabilities": [
    {
      "type": "VisaVirtualCard",
      "verification_requirements": [
        { "type": "BDD", "order": 1 }
      ],
      "prerequisites": null,
      "status": "Active"
    },
    {
      "type": "VisaPlasticCard",
      "verification_requirements": [
        { "type": "SDD", "order": 1 }
      ],
      "prerequisites": null,
      "status": "Active"
    }
  ]
}

Card Capabilities

CapabilityDescription
VisaVirtualCardIssue virtual Visa cards
VisaPlasticCardIssue physical Visa cards
BridgeVirtualCardIssue virtual cards on the Bridge rail. See Bridge-Rail Issuance
BridgePlasticCardIssue physical cards on the Bridge rail. See Bridge-Rail Issuance

On v3, an issuance order never names its own rail. Wirex resolves it from whichever of the pair above is
Active for the user — Visa first, Bridge only when Visa is not available. Metal cards have no Bridge
counterpart; VisaMetalCard is the only capability that gates them.

Capability Fields

FieldDescription
typeCapability identifier
statusCurrent status (see below)
status_reasonExplanation when status is not Active
verification_requirementsKYC levels required for this capability
prerequisitesOther capabilities that must be active first

Capability Status

StatusDescriptionAction
ActiveReady to issue cardsProceed with issuance
NotFulfilledRequirements not metCheck status_reason for details
NotAvailableNot available for user/regionCannot issue this card type

Example: NotFulfilled Due to Verification Level

{
  "type": "VisaPlasticCard",
  "verification_requirements": [
    { "type": "SDD", "order": 1 }
  ],
  "prerequisites": null,
  "status": "NotFulfilled",
  "status_reason": "Verification level SDD is required"
}

The user has completed BDD verification but VisaPlasticCard requires SDD level. The user must complete SDD verification before ordering a plastic card


Order Fees & Delivery

These lookups are shared by both issuance flows. Use them to check fees and present delivery options before issuing; the issue calls are in Issuing a Card below.

Check Order Fees

Returns the order fee for a given card type in a given country.

GET /api/v1/cards/{type}/fees/{country}

Path parameters (values that go directly into the URL):

ParameterDescription
{type}Card type to price: virtual, plastic, or metal (case-insensitive)
{country}Cardholder's country as an ISO 3166-1 alpha-2 code, e.g. GB

Response:

{
  "currency": "USD",
  "order_fee": 9.99,
  "estimated_payment_amounts": [
    {
      "amount": 10.05,
      "precise_amount": "10050000",
      "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "token_symbol": "USDC",
      "rate": 0.9940
    }
  ]
}
FieldDescription
order_feeFee amount in fiat currency
estimated_payment_amountsFee converted to supported tokens

If the endpoint returns a 400 error with "Card fees are not enforced", fees are not applicable for your company — skip the fee steps and issue the card directly (v1 Step 4 / v2 Step 3).

const feesResponse = await fetch(`${baseUrl}/api/v1/cards/virtual/fees/${country}`, {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});

if (feesResponse.status === 400) {
  // Fees not enforced, skip to issuing card
} else {
  const fees = await feesResponse.json();
  // Proceed to create fees invoice
}
response = requests.get(
    f"{base_url}/api/v1/cards/virtual/fees/{country}",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id
    }
)

if response.status_code == 400:
    # Fees not enforced, skip to issuing card
    pass
else:
    fees = response.json()
    # Proceed to create fees invoice
req, _ := http.NewRequest("GET", baseURL+"/api/v1/cards/virtual/fees/"+country, nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

if resp.StatusCode == 400 {
    // Fees not enforced, skip to issuing card
} else {
    var fees FeesResponse
    json.NewDecoder(resp.Body).Decode(&fees)
    // Proceed to create fees invoice
}

Delivery Countries

GET /api/v1/cards/delivery/countries

Response:

["GB", "DE", "FR", "ES", "IT"]
const countriesResponse = await fetch(`${baseUrl}/api/v1/cards/delivery/countries`, {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});
const countries = await countriesResponse.json();
response = requests.get(
    f"{base_url}/api/v1/cards/delivery/countries",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id
    }
)
countries = response.json()
req, _ := http.NewRequest("GET", baseURL+"/api/v1/cards/delivery/countries", nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var countries []string
json.NewDecoder(resp.Body).Decode(&countries)

Delivery Methods

GET /api/v1/cards/delivery/methods/{country}

Path parameters (values that go directly into the URL):

ParameterDescription
{country}Delivery country as an ISO 3166-1 alpha-2 code, e.g. GB

Response:

[
  {
    "fee": 15.00,
    "currency": "USD",
    "provider": "DHL",
    "estimated_payment_amounts": [
      {
        "amount": 15.10,
        "precise_amount": "15100000",
        "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "token_symbol": "USDC",
        "rate": 0.9934
      }
    ]
  }
]
FieldDescription
feeDelivery fee in fiat currency
currencyFiat currency for the fee
providerCourier provider (pass when issuing the card)
estimated_payment_amountsFee converted to supported tokens

Display available methods to the user and use the selected provider value when issuing the card.

const methodsResponse = await fetch(`${baseUrl}/api/v1/cards/delivery/methods/${country}`, {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});
const methods = await methodsResponse.json();
const selectedProvider = methods[0].provider; // e.g., 'DHL'
response = requests.get(
    f"{base_url}/api/v1/cards/delivery/methods/{country}",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id
    }
)
methods = response.json()
selected_provider = methods[0]["provider"]  # e.g., 'DHL'
req, _ := http.NewRequest("GET", baseURL+"/api/v1/cards/delivery/methods/"+country, nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var methods []DeliveryMethod
json.NewDecoder(resp.Body).Decode(&methods)
selectedProvider := methods[0].Provider // e.g., "DHL"

Card Order Configuration (v3)

Returns the products your company may order, grouped by card format — the payment system, designs, card
programs and billing countries of each. Use it to populate design, card_program and payment_system on
a v3 issuance call. A company with nothing configured for a
format receives an empty offerings array for it, not an error.

GET /api/v3/cards/config

Response:

{
  "formats": [
    {
      "format": "Virtual",
      "offerings": [
        {
          "payment_system": "Visa",
          "designs": ["WirexBlack", "WirexBlue"],
          "card_programs": ["WIREX_ATM_EU"],
          "countries": ["GB", "DE", "FR"]
        }
      ]
    }
  ]
}
FieldDescription
formats[].formatCard format the offerings below are ordered as: Virtual, Plastic, or Metal
formats[].offerings[].payment_systemPayment system the offering issues on
formats[].offerings[].designsCard designs the offering may be ordered with
formats[].offerings[].card_programsCard programs the offering may be issued on. Empty where none are configured
formats[].offerings[].countriesBilling countries the offering may be ordered from

A market that offers two designs on different card programs appears as two offerings over the same
countries — filter by country and union the results rather than expecting one offering per country.

const response = await fetch(`${baseUrl}/api/v3/cards/config`, {
  headers: { 'Authorization': `Bearer ${accessToken}`, 'X-User-Wallet': userEoaAddress, 'X-Chain-Id': chainId }
});
const config = await response.json();
response = requests.get(
    f"{base_url}/api/v3/cards/config",
    headers={"Authorization": f"Bearer {access_token}", "X-User-Wallet": user_eoa_address, "X-Chain-Id": chain_id}
)
config = response.json()
req, _ := http.NewRequest("GET", baseURL+"/api/v3/cards/config", nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var config CardOrderConfigResponse
json.NewDecoder(resp.Body).Decode(&config)

Delivery Address Fields

The same delivery_address object and validation apply to all physical cards (Plastic and Metal) on v1, v2, and v3 endpoints.

FieldRequiredValidation (regex)Notes
line1Yes^[A-Za-z0-9&.,'’\-/() :+#]{2,100}$Street address
line2No^[A-Za-z0-9&.,'’\-/() :+#]{2,100}$Apartment, suite, etc.
cityYes^[A-Za-z\s\-'.]{2,100}$Letters only — no digits
stateNo^[A-Za-z][A-Za-z\s\-']{1,99}$State or province
zip_codeYes^[A-Za-z0-9\s\-]{3,12}$3–12 chars; always required
countryYes^[A-Z]{2}$ISO 3166-1 alpha-2, uppercase (e.g. GB)

Notes:

  • zip_code is always required, even for countries that have no postal code. Send a placeholder that matches the regex (3+ chars), e.g. "00000". Only the format is validated, not real postal validity.
  • A missing required field returns 400 ErrorMissingField; a bad format returns 400 ErrorInvalidField. The offending field is named in error_details (e.g. delivery_address.zip_code).
  • These are the platform's format checks, applied before the order is sent to the card processor. If they pass but the processor rejects the order (e.g. address or limit), the issue call returns a synchronous 400 "Request failed due to external validation failure" — no card is created and no card webhook is sent.

Response:

{
  "id": "64120850-73a1-4df5-a074-d463258c9deb"
}
const issueResponse = await fetch(`${baseUrl}/api/v2/cards/plastic`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    delivery_id: deliveryId,
    delivery_provider: 'DHL',
    card_name: 'My Travel Card',
    name_on_card: 'Alex Grey',
    delivery_address: {
      line1: '10 Downing Street',
      line2: 'Flat 2',
      city: 'London',
      state: '',
      zip_code: 'SW1A 2AA',
      country: 'GB'
    }
  })
});
const card = await issueResponse.json();
response = requests.post(
    f"{base_url}/api/v2/cards/plastic",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id,
        "Content-Type": "application/json"
    },
    json={
        "delivery_id": delivery_id,
        "delivery_provider": "DHL",
        "card_name": "My Travel Card",
        "name_on_card": "Alex Grey",
        "delivery_address": {
            "line1": "10 Downing Street",
            "line2": "Flat 2",
            "city": "London",
            "state": "",
            "zip_code": "SW1A 2AA",
            "country": "GB"
        }
    }
)
card = response.json()
body, _ := json.Marshal(map[string]interface{}{
    "delivery_id":       deliveryId,
    "delivery_provider": "DHL",
    "card_name":         "My Travel Card",
    "name_on_card":      "Alex Grey",
    "delivery_address": map[string]string{
        "line1":    "10 Downing Street",
        "line2":    "Flat 2",
        "city":     "London",
        "state":    "",
        "zip_code": "SW1A 2AA",
        "country":  "GB",
    },
})
req, _ := http.NewRequest("POST", baseURL+"/api/v2/cards/plastic", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var card CardResponse
json.NewDecoder(resp.Body).Decode(&card)

Issuing a Card

Issuing a card always carries an issuance fee, paid in crypto. All versions issue the same cards with the same delivery options — they differ in how that fee is collected, and v3 additionally differs in which rail the card lands on:

  • v1 — External Fee — you settle the issuance fee yourself. Wirex returns an on-chain invoice (a recipient_address and an amount); you send the payment from a wallet you control and pass the transaction hash back to Wirex when issuing the card. Because you cover the fee directly instead of relying on the cardholder's balance, v1 fits both standard on-chain integrations and External Authorization, where funds are held on your Master Account rather than in per-user on-chain balances.
  • v2 — Direct Fee — Wirex debits the fee automatically at the moment of issuance, so you never move funds yourself. In a standard on-chain integration the fee is drawn from the cardholder's own on-chain balance; under External Authorization, where cardholders have no on-chain balance, it is drawn from your Master Account instead.
  • v3 — Bridge Rail & Configurable Issuance — same fee collection as v2, plus optional design, card_program and payment_system selection (see Card Order Configuration), and the only version that can resolve to a card funded from a wallet you name rather than the cardholder's own balance. See Bridge-Rail Issuance.

v1 and v2 work in standard on-chain integrations and under External Authorization. v3 is on-chain only — a
Bridge-rail order takes its own funding wallet regardless, and a Visa-rail v3 order still reads the
cardholder's on-chain balance, which External Authorization does not provide.

In every flow the fee is paid from crypto — the difference is only whose balance it comes from, who
initiates the transfer, and, on v3, which rail the card lands on. Pick one flow and follow its steps end to end.

v1 — External Feev2 — Direct Feev3 — Bridge Rail, Configurable
How the fee is collectedYou transfer it on-chain yourselfAuto-debited by Wirex at issuanceAuto-debited by Wirex at issuance
Funded fromA wallet you controlThe cardholder's on-chain balance — or your Master Account under External AuthorizationThe cardholder's on-chain balance (Visa rail), or a card wallet you name (Bridge rail)
Fee invoice returnsrecipient_address (where to send the fee)delivery_id (reference for issuance)delivery_id (reference for issuance)
Field passed at issuancepayment_transaction_hashdelivery_iddelivery_id, plus optional design / card_program / payment_system / card_wallet_address
Works inOn-chain and External AuthorizationOn-chain and External AuthorizationOn-chain only

Issuance endpoints are /api/v1/cards/plastic and /api/v1/cards/virtual (and the /api/v2/ equivalents).
v3 issues each format on its own path instead: POST /api/v3/cards/virtual, POST /api/v3/cards/plastic,
POST /api/v3/cards/metal. Physical (plastic and metal) cards require a delivery_address; virtual cards
do not — see Delivery Address Fields.

v1 — External Fee

Step 1: Check order fees & delivery options

Look up the fee with Check Order Fees, and for physical cards the supported Delivery Countries and Delivery Methods. If fees are not enforced for your company, skip Steps 2–3 and issue the card with no fee field.

Step 2: Create the fee invoice

POST /api/v1/cards/{type}/fees/{country}/payment

Path parameters (values that go directly into the URL):

ParameterDescription
{type}Card type being issued: virtual, plastic, or metal (case-insensitive)
{country}Cardholder's country as an ISO 3166-1 alpha-2 code, e.g. GB

Request body:

{ 
  "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 
  "delivery_provider": "DHL" 
}
FieldRequiredDescription
token_addressYesToken used to pay the fee
delivery_providerConditionalRequired for physical cards

Response — returns a recipient_address and a payment_amount, but no delivery_id (in v1 the fee is not auto-debited; you pay it yourself in Step 3):

{
  "recipient_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "payment_amount": { 
    "amount": 10.05, 
    "precise_amount": "10050000", 
    "token_address": "0xA0b8...", 
    "token_symbol": "USDC", 
    "rate": 0.9940 
  }
}

Step 3: Pay the fee on-chain

Transfer payment_amount.precise_amount of payment_amount.token_address to recipient_address from a wallet you control, and keep the transaction hash.

Step 4: Issue the card

POST /api/v1/cards/{type}

Path parameters (values that go directly into the URL):

ParameterDescription
{type}Card type to issue: virtual or plastic (lowercase). Virtual cards are issued instantly and take no delivery_address; plastic cards are physical and require a delivery_address
{
  "payment_transaction_hash": "0x1234...cdef",
  "delivery_provider": "DHL",
  "name_on_card": "Alex Grey",
  "delivery_address": { 
    "line1": "10 Downing Street", 
    "city": "London", 
    "zip_code": "SW1A 2AA", 
    "country": "GB"
  }
}
FieldTypeRequiredDescription
payment_transaction_hashstringConditionalHash of the Step 3 transfer. Required when fees are enforced; omit otherwise
delivery_addressobjectYes (physical)Omit for virtual cards. See Delivery Address Fields
delivery_providerstringNoCourier provider
card_namestringNoDisplay name (1–50 chars)
name_on_cardstringNoName printed on card (2–26 chars)
const res = await fetch(`${baseUrl}/api/v1/cards/plastic`, {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${accessToken}`, 'X-User-Wallet': userEoaAddress, 'X-Chain-Id': chainId, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    payment_transaction_hash: paymentTxHash, // omit if fees not enforced
    name_on_card: 'Alex Grey',
    delivery_address: { line1: '10 Downing Street', city: 'London', zip_code: 'SW1A 2AA', country: 'GB' }
  })
});
const card = await res.json(); // { id }
res = requests.post(
    f"{base_url}/api/v1/cards/plastic",
    headers={"Authorization": f"Bearer {access_token}", "X-User-Wallet": user_eoa_address, "X-Chain-Id": chain_id, "Content-Type": "application/json"},
    json={
        "payment_transaction_hash": payment_tx_hash,  # omit if fees not enforced
        "name_on_card": "Alex Grey",
        "delivery_address": {"line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB"},
    },
)
card = res.json()  # { id }
body, _ := json.Marshal(map[string]interface{}{
    "payment_transaction_hash": paymentTxHash, // omit if fees not enforced
    "name_on_card":             "Alex Grey",
    "delivery_address":         map[string]string{"line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB"},
})
req, _ := http.NewRequest("POST", baseURL+"/api/v1/cards/plastic", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var card CardResponse
json.NewDecoder(resp.Body).Decode(&card)

v2 — Direct Fee

Step 1: Check order fees & delivery options

Look up the fee with Check Order Fees, and for physical cards the supported Delivery Countries and Delivery Methods. If fees are not enforced for your company, skip Step 2 and issue the card with no fee field.

Step 2: Create the fee invoice

POST /api/v2/cards/{type}/fees/{country}/payment

Path parameters (values that go directly into the URL):

ParameterDescription
{type}Card type being issued: virtual, plastic, or metal (case-insensitive)
{country}Cardholder's country as an ISO 3166-1 alpha-2 code, e.g. GB

Request body:

{ 
  "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 
  "delivery_provider": "DHL" 
}
FieldRequiredDescription
token_addressYesToken used to pay the fee
delivery_providerConditionalRequired for physical cards

Response — the delivery_id is passed to the issue call; the fee is debited automatically at issuance:

{
  "delivery_id": 12345,
  "recipient_address": "0x...",
  "payment_amount": { "amount": 10.05, "precise_amount": "10050000", "token_address": "0xA0b8...", "token_symbol": "USDC", "rate": 0.9940 }
}

Step 3: Issue the card

POST /api/v2/cards/{type}

Path parameters (values that go directly into the URL):

ParameterDescription
{type}Card type to issue: virtual or plastic (lowercase). Virtual cards are issued instantly and take no delivery_address; plastic cards are physical and require a delivery_address
{
  "delivery_id": 12345,
  "delivery_provider": "DHL",
  "name_on_card": "Alex Grey",
  "delivery_address": { "line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB" }
}
FieldTypeRequiredDescription
delivery_idintegerConditionalFrom Step 2. Required when fees are enforced; omit otherwise
delivery_addressobjectYes (physical)Omit for virtual cards. See Delivery Address Fields
delivery_providerstringNoCourier provider
card_namestringNoDisplay name (1–50 chars)
name_on_cardstringNoName printed on card (2–26 chars)
const res = await fetch(`${baseUrl}/api/v2/cards/plastic`, {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${accessToken}`, 'X-User-Wallet': userEoaAddress, 'X-Chain-Id': chainId, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    delivery_id: deliveryId, // omit if fees not enforced
    name_on_card: 'Alex Grey',
    delivery_address: { line1: '10 Downing Street', city: 'London', zip_code: 'SW1A 2AA', country: 'GB' }
  })
});
const card = await res.json(); // { id }
res = requests.post(
    f"{base_url}/api/v2/cards/plastic",
    headers={"Authorization": f"Bearer {access_token}", "X-User-Wallet": user_eoa_address, "X-Chain-Id": chain_id, "Content-Type": "application/json"},
    json={
        "delivery_id": delivery_id,  # omit if fees not enforced
        "name_on_card": "Alex Grey",
        "delivery_address": {"line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB"},
    },
)
card = res.json()  # { id }
body, _ := json.Marshal(map[string]interface{}{
    "delivery_id":      deliveryId, // omit if fees not enforced
    "name_on_card":     "Alex Grey",
    "delivery_address": map[string]string{"line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB"},
})
req, _ := http.NewRequest("POST", baseURL+"/api/v2/cards/plastic", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var card CardResponse
json.NewDecoder(resp.Body).Decode(&card)

Pass delivery_id (there is no invoice_id field). If fees are enforced and delivery_id is missing or 0, issuance returns 400 "Delivery ID is required and must be positive".

v3 — Bridge Rail & Configurable Issuance

Step 1: Check order fees & delivery options

Look up the fee with Check Order Fees, and for physical cards the supported Delivery Countries and Delivery Methods. If fees are not enforced for your company, skip Step 2 and issue the card with no fee field.

Step 2: Create the fee invoice

Same call as v2 — there is no v3 fee-invoice endpoint:

POST /api/v2/cards/{type}/fees/{country}/payment

See Step 2 of v2 for the request and response shape. Carry delivery_id into Step 3.

Step 3: Issue the card

POST /api/v3/cards/virtual
POST /api/v3/cards/plastic
POST /api/v3/cards/metal

Each format has its own path — there is no {type} parameter. Plastic and metal require a delivery_address; virtual does not.

{
  "delivery_id": 12345,
  "delivery_provider": "DHL",
  "card_name": "My Travel Card",
  "name_on_card": "Alex Grey",
  "design": "WirexBlack",
  "card_program": "WIREX_ATM_EU",
  "payment_system": "Visa",
  "card_wallet_address": "0xA7E41d5680dE394EaA2ed417169DFf56840Fb3EE",
  "delivery_address": { "line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB" }
}
FieldTypeRequiredDescription
delivery_idintegerConditionalFrom Step 2. Required when fees are enforced; omit otherwise
delivery_addressobjectYes (plastic/metal)Omit for virtual cards. See Delivery Address Fields
delivery_providerstringNoCourier provider
card_namestringNoDisplay name (1–50 chars)
name_on_cardstringNoName printed on card (2–26 chars)
designstringNoOne of the company's designs for this format, from Card Order Configuration. Omitted means the issuer's default
card_programstringNoCard program to issue on, which carries the card's cash-withdrawal terms — from Card Order Configuration. Omitted means the first program configured for the format and billing country
payment_systemstringNoVisa or MasterCard. Any other value returns 400 ErrorGeneral — Payment system must be one of Visa, MasterCard
card_wallet_addressstringConditionalSee Bridge-Rail Issuance — required when the order resolves to Bridge, rejected when it resolves to Visa, always rejected for metal
const res = await fetch(`${baseUrl}/api/v3/cards/plastic`, {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${accessToken}`, 'X-User-Wallet': userEoaAddress, 'X-Chain-Id': chainId, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    delivery_id: deliveryId, // omit if fees not enforced
    name_on_card: 'Alex Grey',
    card_program: 'WIREX_ATM_EU', // omit for the issuer's default
    card_wallet_address: cardWalletAddress, // only when the order resolves to Bridge
    delivery_address: { line1: '10 Downing Street', city: 'London', zip_code: 'SW1A 2AA', country: 'GB' }
  })
});
const card = await res.json(); // { id }
res = requests.post(
    f"{base_url}/api/v3/cards/plastic",
    headers={"Authorization": f"Bearer {access_token}", "X-User-Wallet": user_eoa_address, "X-Chain-Id": chain_id, "Content-Type": "application/json"},
    json={
        "delivery_id": delivery_id,  # omit if fees not enforced
        "name_on_card": "Alex Grey",
        "card_program": "WIREX_ATM_EU",  # omit for the issuer's default
        "card_wallet_address": card_wallet_address,  # only when the order resolves to Bridge
        "delivery_address": {"line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB"},
    },
)
card = res.json()  # { id }
body, _ := json.Marshal(map[string]interface{}{
    "delivery_id":         deliveryId, // omit if fees not enforced
    "name_on_card":        "Alex Grey",
    "card_program":        "WIREX_ATM_EU", // omit for the issuer's default
    "card_wallet_address": cardWalletAddress, // only when the order resolves to Bridge
    "delivery_address":    map[string]string{"line1": "10 Downing Street", "city": "London", "zip_code": "SW1A 2AA", "country": "GB"},
})
req, _ := http.NewRequest("POST", baseURL+"/api/v3/cards/plastic", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var card CardResponse
json.NewDecoder(resp.Body).Decode(&card)

Bridge-Rail Issuance (v3)

A v3 issuance order never states its own rail. Wirex resolves it from the user's card capabilities: Visa is
tried first, and the order resolves to Bridge only where the corresponding Bridge capability
(BridgeVirtualCard / BridgePlasticCard) is Active and the Visa one is not. Metal cards have no Bridge
counterpart and always resolve to Visa.

Visa railBridge rail
Resolved whenVisaVirtualCard / VisaPlasticCard is ActiveVisa is not active and BridgeVirtualCard / BridgePlasticCard is Active
card_wallet_addressMust be omittedRequired — a wallet of type Card you deployed, confirmed on-chain
Funded fromThe cardholder's own primary wallet, on the chain the request is made onThe named card wallet, on whichever chain it was deployed on
Card's chain_idThe session's X-Chain-IdThe card wallet's own chain — not necessarily the session's

Trap: the rail is not a request choice. Sending card_wallet_address does not request the Bridge
rail — it is only accepted because the order already resolved to Bridge from the user's capabilities.
Sending it on an order that resolves to Visa is rejected; naming a wallet you do not hold, one that is not
type Card, or one not yet confirmed on-chain is rejected the same way a missing wallet is — see
Error Handling.

All versions return { "id": "..." }; the card starts in Requested and transitions to NotActivated once processed. Capabilities, order fees, delivery options, address validation, lifecycle, activation, and webhooks in this guide apply to every version.


Card Lifecycle

Requested → NotActivated → Active
                             ↓
                          Blocked ←→ Active
                             ↓
                           Closed
StatusDescription
RequestedCard order submitted, processing
NotActivatedCard issued, awaiting activation
ActiveCard is active and usable
BlockedTemporarily blocked (can be unblocked)
ClosedPermanently closed

Action Gates

Every card action is evaluated against the card's current status before it runs, and the same evaluator
produces the allowed_actions array on each card. Read allowed_actions and act on what it lists —
it is the API's own answer to what is possible right now.

ActionAllowed inRefused in, with
ActivateNotActivatedRequested — Card is not issued yet; everything else — Card is already activated
BlockActiveRequested, NotActivated, Closed — Card is not active; Blocked — Card is already blocked
UnblockBlockedeverything else — Card is not blocked
CloseActive, BlockedRequested, NotActivated — Card status does not allow closing; Closed — Card is already closed
Change limitActiveeverything else — Card status does not allow limit changes
Get details, CVV, PINActiveeverything else — Card is not active

Refusals carry ErrorInvalidStatus and name the action in error_details. allowed_actions reflects
status only — it does not account for the caller's token scope, so an action can be listed and
still be refused by authentication.


Activate Card

Activation is required only for physical cards. This protects user funds if the card is stolen during shipment.

PUT /api/v1/cards/{cardId}/activate

Path parameters (values that go directly into the URL):

ParameterDescription
{cardId}The card's id, returned when the card was issued (see Get Cards)

Request:

{
  "card_number_last4": "1234",
  "expiry_date": "12/2027"
}
FieldTypeRequiredDescription
card_number_last4stringYesLast 4 digits of card number
expiry_datestringYesExpiration date in MM/YYYY format

Response: Empty on success (200 OK)

await fetch(`${baseUrl}/api/v1/cards/${cardId}/activate`, {
  method: 'PUT',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    card_number_last4: '1234',
    expiry_date: '12/2027'
  })
});
requests.put(
    f"{base_url}/api/v1/cards/{card_id}/activate",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id,
        "Content-Type": "application/json"
    },
    json={
        "card_number_last4": "1234",
        "expiry_date": "12/2027"
    }
)
body, _ := json.Marshal(map[string]string{
    "card_number_last4": "1234",
    "expiry_date":       "12/2027",
})
req, _ := http.NewRequest("PUT", baseURL+"/api/v1/cards/"+cardId+"/activate", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")

http.DefaultClient.Do(req)

Get Cards

Retrieve all cards for a user.

GET /api/v1/cards

GET /api/v3/cards reads the same list across every chain the user holds a card on, regardless of the
chain the request is made on — useful once a user holds a Bridge card whose wallet lives on a chain other
than the session's. GET /api/v3/cards/{cardId} reads one card the same way. Both take the same query
parameters and return the same CardResponse shape as v1, with chain_id naming which chain each entry
belongs to.

const response = await fetch(`${baseUrl}/api/v1/cards`, {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});
const { data: cards } = await response.json();
response = requests.get(
    f"{base_url}/api/v1/cards",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id
    }
)
cards = response.json()["data"]
req, _ := http.NewRequest("GET", baseURL+"/api/v1/cards", nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var result CardsResponse
json.NewDecoder(resp.Body).Decode(&result)
cards := result.Data

Response:

{
  "data": [
    {
      "id": "64120850-73a1-4df5-a074-d463258c9deb",
      "correlation_id": "64120850-73a1-4df5-a074-d463258c9deb",
      "card_wallet_address": "0xAAFF0821A09A1Aac28B72dD3Ff410A7ea5FEb874",
      "status": "Active",
      "status_reason": "",
      "previous_status": "NotActivated",
      "generation": "Gen2",
      "provider": "Wirex",
      "chain_id": 8453,
      "limit": {
        "daily_limit": 10000.00,
        "daily_limit_precise": "10000000000000000000000",
        "daily_usage": 250.00,
        "daily_usage_precise": "250000000000000000000",
        "decimals": 18,
        "currency": "USD"
      },
      "allowed_actions": [
        { "type": "Block", "relative_path": "/api/v1/cards/:cardId/block" },
        { "type": "Close", "relative_path": "/api/v1/cards/:cardId/close" },
        { "type": "SetLimit", "relative_path": "/api/v1/cards/:cardId/limit" },
        { "type": "GetDetails", "relative_path": "/api/v1/cards/:cardId/details" },
        { "type": "GetCvv", "relative_path": "/api/v1/cards/:cardId/cvv" }
      ],
      "card_data": {
        "card_name": "My Card",
        "name_on_card": "Alex Grey",
        "card_number_last_4": "0333",
        "expiry_date": "12/2027",
        "payment_system": "Visa",
        "format": "Virtual"
      },
      "created_at": "2024-01-01T10:00:00Z",
      "updated_at": "2024-01-01T10:05:00Z"
    }
  ]
}
FieldDescription
data[].correlation_idThe id the issuance order returned. Stays on the card after the issuer re-keys it under an id of its own, so a client that only kept the order's id can still find the card here. Absent if the issuer never re-keyed it
data[].chain_idEIP-155 chain the card belongs to. On the Visa rail this is the chain it was ordered on; on the Bridge rail it is the funding wallet's own chain
data[].providerWirex (Visa rail) or Bridge
data[].funding_tokenPresent only for a card funded by its own wallet (Bridge rail): address, symbol, decimals, chain_id of the token it debits
data[].issuer_spender_addressPresent only for a card funded by its own wallet: the address the funding wallet grants its spending allowance to
data[].limit.*_preciseEach limit and usage figure in base units, as a decimal string scaled by data[].limit.decimals (18, fiat scale)

Allowed Action Types

TypeDescription
ActivateActivate the card
BlockBlock the card
UnblockUnblock the card
CloseClose the card
SetLimitChange card limits
GetDetailsGet full card details (PAN)
GetCvvGet card CVV
GetPinGet card PIN

Card Data Visibility

FieldVisible When
card_number_first_4Status is Requested or NotActivated
card_number_last_4Status is Active, Blocked, or Closed
expiry_dateStatus is Active, Blocked, or Closed

Manage Cards

In every call below, {cardId} in the URL is the card's id returned at issuance (see Get Cards).

Block Card

Temporarily block a card. Can be unblocked later.

PUT /api/v1/cards/{cardId}/block

Unblock Card

Restore a blocked card to active status.

PUT /api/v1/cards/{cardId}/unblock

Close Card

Permanently close a card. This action cannot be undone.

PUT /api/v1/cards/{cardId}/close

Change Card Name

Updates the card's display name. This is the only card action with no status gate — a card in any
status can be renamed.

PUT /api/v1/cards/{cardId}/name

Request body:

{
  "name": "For unsafe sites"
}
FieldTypeRequiredDescription
namestringYesNew display name. Must match ^[a-zA-Z0-9\-':+# @]{1,50}$

Response:

{}

This changes card_data.card_name only — the display label. It does not change name_on_card, which
is embossed at issuance and cannot be changed afterwards.

// Block
await fetch(`${baseUrl}/api/v1/cards/${cardId}/block`, {
  method: 'PUT',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});

// Unblock
await fetch(`${baseUrl}/api/v1/cards/${cardId}/unblock`, {
  method: 'PUT',
  headers: { /* same headers */ }
});

// Close
await fetch(`${baseUrl}/api/v1/cards/${cardId}/close`, {
  method: 'PUT',
  headers: { /* same headers */ }
});
headers = {
    "Authorization": f"Bearer {access_token}",
    "X-User-Wallet": user_eoa_address,
    "X-Chain-Id": chain_id
}

# Block
requests.put(f"{base_url}/api/v1/cards/{card_id}/block", headers=headers)

# Unblock
requests.put(f"{base_url}/api/v1/cards/{card_id}/unblock", headers=headers)

# Close
requests.put(f"{base_url}/api/v1/cards/{card_id}/close", headers=headers)
actions := []string{"block", "unblock", "close"}
for _, action := range actions {
    req, _ := http.NewRequest("PUT", baseURL+"/api/v1/cards/"+cardId+"/"+action, nil)
    req.Header.Set("Authorization", "Bearer "+accessToken)
    req.Header.Set("X-User-Wallet", userEoaAddress)
    req.Header.Set("X-Chain-Id", chainId)
    http.DefaultClient.Do(req)
}

Webhooks

Card status changes trigger webhook notifications. The payload structure matches the Get Cards response.

Card Status Webhook

Endpoint: POST {your_webhook_base_url}/v2/webhooks/cards

The payload structure matches the Get Cards response item, including correlation_id,
chain_id, precise limit fields, and funding_token / issuer_spender_address on a Bridge-rail card.

{
  "id": "64120850-73a1-4df5-a074-d463258c9deb",
  "card_wallet_address": "0xAAFF0821A09A1Aac28B72dD3Ff410A7ea5FEb874",
  "status": "Active",
  "status_reason": "",
  "previous_status": "NotActivated",
  "generation": "Gen2",
  "provider": "Wirex",
  "limit": {
    "daily_limit": 10000.00,
    "daily_usage": 0.00,
    "currency": "USD"
  },
  "allowed_actions": [
    { "type": "Block", "relative_path": "/api/v1/cards/:cardId/block" },
    { "type": "Close", "relative_path": "/api/v1/cards/:cardId/close" }
  ],
  "card_data": {
    "card_name": "My Card",
    "name_on_card": "Alex Grey",
    "card_number_last_4": "0333",
    "expiry_date": "12/2027",
    "payment_system": "Visa",
    "format": "Virtual"
  },
  "created_at": "2024-01-01T10:00:00Z",
  "updated_at": "2024-01-01T10:05:00Z"
}

Card Limit Webhook

Endpoint: POST {your_webhook_base_url}/v2/webhooks/card-limits

{
  "card_id": "64120850-73a1-4df5-a074-d463258c9deb",
  "transaction_limit": 500.00,
  "daily_limit": 1000.00,
  "daily_usage": 200.00,
  "monthly_limit": 5000.00,
  "monthly_usage": 1500.00,
  "lifetime_limit": 100000.00,
  "lifetime_usage": 25000.00
}

Field Validation

Card Name

Pattern: ^[a-zA-Z0-9\-':+# @]{1,50}$

Name on Card

Pattern: ^[A-Za-z][A-Za-z .'-]{1,25}$

  • Must start with a letter
  • Only letters, spaces, periods, apostrophes, and hyphens
  • 2-26 characters total

Delivery Address

FieldPattern
line1^[A-Za-z0-9&.,''\-/() :+#]{2,100}$
line2^[A-Za-z0-9&.,''\-/() :+#]{2,100}$
city^[A-Za-z\s\-'.]{2,100}$
state^[A-Za-z][A-Za-z\s\-']{1,99}$
zip_code^[A-Za-z0-9\s\-]{3,12}$
country^[A-Z]{2}$ (ISO 3166-1 alpha-2)

Error Handling

All errors return JSON with the following structure:

{
  "error_reason": "ErrorInvalidField",
  "error_description": "Human-readable message",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "field_name" }
  ]
}

Validation Errors (400)

Missing Required Field

{
  "error_reason": "ErrorMissingField",
  "error_description": "delivery_address is required",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "delivery_address" },
    { "key": "issue", "details": "missing" }
  ]
}

Invalid Field Format

{
  "error_reason": "ErrorInvalidField",
  "error_description": "Invalid format for card number last4",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "card_number_last4" },
    { "key": "issue", "details": "invalid_format" },
    { "key": "pattern", "details": "^\\d{4}$" }
  ]
}

Invalid Card Status

Returned when attempting an action not allowed for the card's current status.

{
  "error_reason": "ErrorInvalidStatus",
  "error_description": "Card is not in valid status for this action",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "card_status" },
    { "key": "value", "details": "Requested" }
  ]
}
ActionInvalid Statuses
ActivateRequested, Active, Blocked, Closed
BlockNotActivated, Requested, Closed, Blocked
UnblockAny status except Blocked
CloseNotActivated, Requested, Closed

Delivery ID Required

When fees are enforced and delivery_id is missing or invalid.

{
  "error_reason": "ErrorGeneral",
  "error_description": "Delivery ID is required and must be positive",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "delivery_id" }
  ]
}

Bridge-Rail Funding Wallet Errors (v3)

Returned by v3 issuance only, all 400 under CategoryValidationFailure with card_wallet_address in error_details:

Error ReasonCauseResolution
ErrorMissingFieldOrder resolved to Bridge and card_wallet_address was omittedName a confirmed wallet of type Card you hold
ErrorInvalidFieldOrder resolved to Bridge, card_wallet_address did not parse to a non-zero address, or order resolved to Visa and card_wallet_address was sent (Visa never accepts a funding wallet)Correct the address, or omit the field on a Visa-rail order
ErrorGeneralcard_wallet_address sent on a metal-card orderOmit the field — metal cards have no Bridge rail
ErrorNotFoundThe named address is not a wallet of type Card the caller holdsRegister the wallet first, or name a different one
ErrorNotSupportedThe wallet's on-chain implementation was confirmed rejectedUnrecoverable for this address — deploy and confirm a different card wallet
ErrorNotYetValidThe wallet exists but on-chain confirmation has not completed yetWait for the wallet registration webhook to report it Confirmed, then retry

Not Found Errors (400)

Delivery Countries/Methods Not Found

{
  "error_reason": "ErrorNotFound",
  "error_description": "No delivery methods found for country",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "country" },
    { "key": "value", "details": "XX" }
  ]
}

Fees Not Found

{
  "error_reason": "ErrorNotFound",
  "error_description": "No fees found for specified country and method",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "fields", "details": "type,country" },
    { "key": "type", "details": "Virtual" },
    { "key": "country", "details": "XX" }
  ]
}

Fees Not Enforced

Returned when calling fees endpoints but fees are not configured for your company.

{
  "error_reason": "ErrorGeneral",
  "error_description": "Request validation failed",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "request", "details": "Card fees are not enforced" }
  ]
}

Server Errors (500)

Error DescriptionCause
Failed to get cardCard not found or service unavailable
Failed to issue virtual cardCard issuer service error
Failed to issue plastic cardCard issuer service error
Failed to activate cardCard issuer service error
Failed to process delivery paymentPayment processing error
Virtual card capability is not activeCapability is not Active for this user

Capability Not Active

Returned when the user's card capability is not Active at the moment of issuance. Despite being a
precondition failure, it is returned as a 500 under CategoryInternalFailure — not a 400. Check
capability status before issuing (see Prerequisites) rather than treating this as a
transient error to retry.

{
  "error_reason": "ErrorGeneral",
  "error_description": "Virtual card capability is not active",
  "error_category": {
    "category": "CategoryInternalFailure",
    "http_status_code": 500
  }
}

Did this page help you?