Skip to main content

Creating Cards

This guide walks you through creating and managing cards using the Issuing API.

Card Types

The API supports two types of cards:

Virtual Cards

Digital cards for online transactions. Instant issuance.

Physical Cards

Physical cards shipped to cardholders. 5-7 business days delivery.

Step 1: Create a Card Account

Before creating a card, you must first create a card account:
curl -X POST https://access.utgl.io/v1/cardaccounts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "your-account-id",
    "accountType": "prepaid",
    "currency": "USD"
  }'

Step 2: Create a Card

Once you have a card account, create a card:
curl -X POST https://access.utgl.io/v1/cards \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "cardAccountId": "c8e2752d-6bd7-4244-a9f6-580f5640eaeb",
    "type": "virtual",
    "productId": "your-product-id-uuid",
    "embossedName": "John Doe"
  }'
Required Fields:
  • cardAccountId: The card account ID (from Step 1)
  • type: Either "physical" or "virtual"
  • productId: UUID of the card product (provided by your solution manager)
  • embossedName: Name to appear on card (max 22 chars, letters/spaces/hyphens only)
The productId determines card features, benefits, and capabilities. Contact your solution manager for available product IDs.

Response

{
  "id": "b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3",
  "cardAccountId": "c8e2752d-6bd7-4244-a9f6-580f5640eaeb",
  "type": "virtual",
  "status": "active",
  "productId": "your-product-id-uuid",
  "embossedName": "John Doe",
  "createdAt": "2025-11-27T10:00:00Z"
}
Virtual cards are instantly active and ready to use!

Step 3: Retrieve Card Details

curl "https://access.utgl.io/v1/cards?cardId=b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3" \
  -H "Authorization: Bearer YOUR_API_KEY"

Get Sensitive Card Details

To retrieve full PAN, CVV, and expiry, use the sensitive info endpoint:
curl "https://access.utgl.io/v1/cards/card-sensitive-info?cardAccountId=c8e2752d-6bd7-4244-a9f6-580f5640eaeb&cardId=b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3&ipAddress=8.8.8.8" \
  -H "Authorization: Bearer YOUR_API_KEY"
This returns a short-lived URL that you must consume directly from the client’s IP address:
{
  "url": "https://access.utgl.io/v1/secure-content/2e91c5ac-eaaf-4274-9afd-520aa35c190e",
  "expiry": "2025-11-27T10:05:00Z"
}
Sensitive card data should be handled securely and never logged or stored in plain text. The URL must be consumed from the client’s IP address.

Step 4: Fund the Card Account

Fund the card account (for prepaid accounts):
curl -X POST https://access.utgl.io/v1/cardaccounts/topup \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "your-source-account-id",
    "cardAccountId": "c8e2752d-6bd7-4244-a9f6-580f5640eaeb",
    "amount": 5000,
    "currency": "USD"
  }'

Step 5: Update Card Spending Controls

Update spending controls for a card:
curl -X POST https://access.utgl.io/v1/cards/spending-controls \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardId": "b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3",
    "singleTransactionLimit": 100000
  }'

Creating Physical Cards

Physical cards follow the same process. The card account and card creation steps are identical:
curl -X POST https://access.utgl.io/v1/cards \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "cardAccountId": "c8e2752d-6bd7-4244-a9f6-580f5640eaeb",
    "type": "physical",
    "productId": "your-product-id-uuid",
    "embossedName": "Jane Smith"
  }'
Shipping information is typically handled separately through your card product configuration or via the cardholder info fields. Check with your solution manager for specific requirements.

Card Lifecycle Management

Activate a Card

curl -X POST https://access.utgl.io/v1/cards/activate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardId": "b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3"
  }'

Suspend a Card

Temporarily block transactions:
curl -X POST https://access.utgl.io/v1/cards/suspend \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardId": "b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3"
  }'

Unsuspend a Card

Resume transactions:
curl -X POST https://access.utgl.io/v1/cards/unsuspend \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardId": "b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3"
  }'

Cancel a Card

Permanently cancel (irreversible):
curl -X POST https://access.utgl.io/v1/cards/cancel \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardId": "b39fcdfe-2ca0-49fc-b941-9b94ea1a51b3"
  }'
Closing a card is permanent and cannot be undone. Funds will be returned to your account balance.

Best Practices

1. Use Idempotency Keys

Always use idempotency keys when creating cards to prevent duplicates: Header: Idempotency-Key: <unique-value> Concept:
  • Generate a unique identifier (UUID recommended)
  • Include in request headers
  • Same key = same result (prevents duplicate cards)
Endpoint: POST /v1/cards Example:
curl -X POST https://access.utgl.io/v1/cards \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

2. Set Appropriate Limits

Start with conservative limits and increase as needed: Endpoint: POST /v1/cards/spending-controls Recommended Starting Limits:
  • Daily: $1,000
  • Monthly: $5,000
  • Per Transaction: $500
Concept:
  • Set limits based on cardholder risk profile
  • Adjust limits dynamically as needed
  • Monitor spending patterns

3. Use Metadata for Tracking

Store application-specific data in metadata: Field: xmetadata (object with key-value pairs) Use Cases:
  • Customer ID tracking
  • Department/cost center assignment
  • Audit trail (who created the card)
  • Integration with your systems
Example:
{
  "cardAccountId": "...",
  "productId": "...",
  "embossedName": "John Doe",
  "xmetadata": {
    "customerId": "cust_123",
    "department": "marketing",
    "costCenter": "CC-123",
    "createdBy": "[email protected]"
  }
}

4. Monitor Card Status with Webhooks

Subscribe to card events for real-time updates: Webhook Events:
  • card.created - Card successfully created
  • card.suspended - Card suspended
  • card.unsuspended - Card unsuspended
  • card.cancelled - Card cancelled
Concept:
  • Configure webhook endpoint in dashboard
  • Receive events when card status changes
  • Update your systems accordingly
See Webhooks Guide for setup details.

Complete Workflow Example

Here’s a complete workflow for creating and funding a card:

Step-by-Step Process

1. Create Card Account Endpoint: POST /v1/cardaccounts Request:
{
  "accountId": "your-source-account-id",
  "accountType": "prepaid",
  "currency": "USD"
}
Response: Returns cardAccountId
2. Create Card Endpoint: POST /v1/cards Headers:
  • Authorization: Bearer <JWT_TOKEN>
  • Idempotency-Key: <unique-uuid>
  • Content-Type: application/json
Request:
{
  "cardAccountId": "c8e2752d-6bd7-4244-a9f6-580f5640eaeb",
  "type": "virtual",
  "productId": "your-product-id-uuid",
  "embossedName": "John Doe"
}
Response: Returns card with id and status
3. Fund Card Account (Optional) Endpoint: POST /v1/cardaccounts/topup Request:
{
  "accountId": "your-source-account-id",
  "cardAccountId": "c8e2752d-6bd7-4244-a9f6-580f5640eaeb",
  "amount": 500000,
  "currency": "USD"
}
Note: Amount is in smallest currency unit (cents for USD)
4. Retrieve Card Details Endpoint: GET /v1/cards?cardId=<card-id> Response: Returns complete card information
5. Set Spending Controls (Optional) Endpoint: POST /v1/cards/spending-controls Request:
{
  "cardId": "card-id-from-step-2",
  "dailyLimit": 100000,
  "monthlyLimit": 500000,
  "perTransactionLimit": 50000
}
For language-specific implementation examples, see the Recipes section which contains code examples in various programming languages.

Troubleshooting

Card Creation Failed

Problem: 400 Bad Request - Invalid cardAccountId Solution: Ensure the card account exists and you have the correct cardAccountId. Create a card account first using /v1/cardaccounts. Problem: 400 Bad Request - Invalid productId Solution: The productId must be a valid UUID provided by your solution manager. Contact them for available product IDs.

Card Not Active

Problem: Created card shows status: "pending" Solution: For physical cards, status remains “pending” until the card is activated. Use the /v1/cards/activate endpoint to activate.

Sensitive Data Access Denied

Problem: 400 Bad Request when accessing /cards/card-sensitive-info Solution: Ensure you provide all required parameters: cardAccountId, cardId, and ipAddress. The ipAddress must match the client IP that will consume the returned URL.

Next Steps