Skip to content

Tutorial: Issue your first card

This tutorial takes an issuer tenant from authenticating to holding a card, in the QPay sandbox. It is the short path: each step links to the how-to guide that covers the same ground with every option.

Prerequisites:

export BASE="https://sandbox.qpay.quecto.com.br"
export ISSUER="$BASE/api/issuer"

1. Get an access token

TOKEN=$(curl -s -X POST \
  $BASE/realms/qpay/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  | jq -r '.access_token')

Confirm it works:

curl -s $BASE/api/credentials/whoami \
  -H "Authorization: Bearer $TOKEN" | jq .

Expected response:

{
  "tenant_type": "issuer",
  "tenant_id": "your-issuer-tenant-id",
  "parent_tenant_id": "your-processor-tenant-id"
}

Every API call goes through /api

The sandbox is fronted by a gateway: the Issuer API lives at /api/issuer, credentials at /api/credentials, the ledger at /api/issuer/ledger. A request without the prefix reaches the console web app instead and comes back as HTML.


2. Pick a card template

Your processor publishes card templates — pre-certified BIN-level configurations. You build a product on one; you do not create one.

curl -s $ISSUER/card-templates \
  -H "Authorization: Bearer $TOKEN" | jq '.[] | {id, name, currency_numeric_code}'

Note an id — it is TEMPLATE_ID in the next step. Its currency_numeric_code is the currency your product will inherit.


3. Create a product and make it issuable

A product is the offering; a layout is one design of it; an embosser is certified against a layout. A card needs all three, so this is four calls:

# the template you noted in step 2, and an embosser from GET $ISSUER/embossers
TEMPLATE_ID=7
EMBOSSER_ID=$(curl -s $ISSUER/embossers \
  -H "Authorization: Bearer $TOKEN" | jq -r '.[0].embosser_id')

# the product
PRODUCT_ID=$(curl -s -X POST $ISSUER/card-products \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d "{\"card_template_id\": $TEMPLATE_ID, \"name\": \"My First Product\", \"description\": \"Tutorial product\"}" \
  | jq -r '.product_id')

# a layout under it
LAYOUT_ID=$(curl -s -X POST $ISSUER/card-products/$PRODUCT_ID/layouts \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"layout": "tutorial-v1", "prints_pan_on_face": false, "cardholder_name_zone": "bottom_left"}' \
  | jq -r '.layout_id')

# link that embosser to the layout
PE_ID=$(curl -s -X POST $ISSUER/card-products/$PRODUCT_ID/layouts/$LAYOUT_ID/embossers \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d "{\"embosser_id\": $EMBOSSER_ID, \"embosser_reference_id\": \"TUTORIAL-REF\"}" \
  | jq -r '.id')

# approve the link — the last segment is the link id, not the embosser id
curl -s -X PUT $ISSUER/card-products/$PRODUCT_ID/layouts/$LAYOUT_ID/embossers/$PE_ID/approve \
  -H "Authorization: Bearer $TOKEN"

Check that the product is now issuable — it appears here only if it is active and has a layout with an approved embosser:

curl -s $ISSUER/card-products/issuing-data \
  -H "Authorization: Bearer $TOKEN" | jq .

Full detail, including artwork and the certification export: Manage Card Products.


4. Issue a card

A card is backed by ledger accounts, so how you issue depends on whose ledger holds them. In the sandbox the quickest route is QPay's own ledger, which creates the accounts and then calls the Issuer API for you:

curl -s -X POST $BASE/api/issuer/ledger/accounts/cards \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d "{
    \"idempotency_key\": \"$(uuidgen)\",
    \"product_id\": $PRODUCT_ID,
    \"layout_id\": $LAYOUT_ID,
    \"cardholder_id\": \"YOUR_CARDHOLDER_ID\",
    \"currency_numeric_code\": 986,
    \"reference_id\": \"TUTORIAL-CARD-001\",
    \"card_holder_name\": \"JOAO DA SILVA\",
    \"billing_address\": { \"name\": \"JOAO DA SILVA\", \"address_line1\": \"Av. Paulista 1000\", \"city\": \"Sao Paulo\", \"state\": \"SP\", \"country\": \"BR\", \"postal_code\": \"01310100\" },
    \"shipping_address\": { \"name\": \"JOAO DA SILVA\", \"address_line1\": \"Av. Paulista 1000\", \"city\": \"Sao Paulo\", \"state\": \"SP\", \"country\": \"BR\", \"postal_code\": \"01310100\" }
  }" | jq .

The cardholder must exist and be KYC-approved for that currency first — Use the QPay Ledger covers those steps, and it is the guide to follow if this call fails.

Running your own ledger instead? Call POST $ISSUER/cards/create directly and pass your own account_links — see Create a Card.


5. Check card status

curl -s $ISSUER/cards/CARD_ID \
  -H "Authorization: Bearer $TOKEN" | jq .

A new card is PROVISIONED. It advances only when the embosser reports progress through the Embosser API, so in a sandbox with no bureau attached it stays there.


What's next?

Browse the full API Reference to explore all available endpoints.