> ## Documentation Index
> Fetch the complete documentation index at: https://payer.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Retrieve Payment

> Get the status and details of a payment

## Endpoint

```
GET /api/v1/payments/:id
```

Retrieves the current status and details of a payment by its ID.

## Request

### Headers

| Header          | Required | Description                    |
| --------------- | -------- | ------------------------------ |
| `Authorization` | Yes      | Bearer token with your API key |

### Path Parameters

| Parameter | Type   | Required | Description                         |
| --------- | ------ | -------- | ----------------------------------- |
| `id`      | string | Yes      | The payment ID (e.g., `pay_abc123`) |

### Example Request

```bash theme={null}
curl https://card2crypto.cc/api/v1/payments/pay_abc123xyz789 \
  -H "Authorization: Bearer c2c_live_your_api_key"
```

## Response

### Success Response (200 OK)

#### Pending Payment

```json theme={null}
{
  "success": true,
  "data": {
    "id": "pay_abc123xyz789",
    "amount": 10000,
    "currency": "usd",
    "status": "pending",
    "checkout_url": "https://card2crypto.cc/checkout/pay_abc123xyz789",
    "customer_email": "customer@example.com",
    "customer_name": "John Doe",
    "metadata": {
      "order_id": "1234",
      "product": "Premium Plan"
    },
    "created_at": "2025-10-16T12:00:00Z",
    "completed_at": null
  }
}
```

#### Completed Payment

```json theme={null}
{
  "success": true,
  "data": {
    "id": "pay_abc123xyz789",
    "amount": 10000,
    "currency": "usd",
    "status": "completed",
    "checkout_url": "https://card2crypto.cc/checkout/pay_abc123xyz789",
    "customer_email": "customer@example.com",
    "customer_name": "John Doe",
    "metadata": {
      "order_id": "1234",
      "product": "Premium Plan"
    },
    "created_at": "2025-10-16T12:00:00Z",
    "completed_at": "2025-10-16T12:01:30Z"
  }
}
```

#### Failed Payment

```json theme={null}
{
  "success": true,
  "data": {
    "id": "pay_abc123xyz789",
    "amount": 10000,
    "currency": "usd",
    "status": "failed",
    "checkout_url": "https://card2crypto.cc/checkout/pay_abc123xyz789",
    "customer_email": "customer@example.com",
    "customer_name": "John Doe",
    "metadata": {
      "order_id": "1234",
      "product": "Premium Plan"
    },
    "created_at": "2025-10-16T12:00:00Z",
    "completed_at": null
  }
}
```

#### Refunded Payment

```json theme={null}
{
  "success": true,
  "data": {
    "id": "pay_abc123xyz789",
    "amount": 10000,
    "currency": "usd",
    "status": "refunded",
    "checkout_url": "https://card2crypto.cc/checkout/pay_abc123xyz789",
    "customer_email": "customer@example.com",
    "customer_name": "John Doe",
    "metadata": {
      "order_id": "1234",
      "product": "Premium Plan"
    },
    "created_at": "2025-10-16T12:00:00Z",
    "completed_at": "2025-10-16T12:01:30Z"
  }
}
```

### Response Fields

| Field            | Type           | Description                                                             |
| ---------------- | -------------- | ----------------------------------------------------------------------- |
| `id`             | string         | Unique payment identifier                                               |
| `amount`         | integer        | Payment amount in cents                                                 |
| `currency`       | string         | Currency code (always `"usd"`)                                          |
| `status`         | string         | Payment status: `pending`, `completed`, `failed`, or `refunded`         |
| `checkout_url`   | string         | URL where customer can complete payment                                 |
| `customer_email` | string \| null | Customer's email (if provided)                                          |
| `customer_name`  | string \| null | Customer's name (if provided)                                           |
| `metadata`       | object         | Custom data attached to payment                                         |
| `created_at`     | string         | ISO 8601 timestamp when payment was created                             |
| `completed_at`   | string \| null | ISO 8601 timestamp when payment was completed (null for pending/failed) |

## Payment Statuses

| Status      | Description                                                                 |
| ----------- | --------------------------------------------------------------------------- |
| `pending`   | Payment created but not yet completed. Customer needs to complete checkout. |
| `completed` | Payment successfully processed. Seller balance has been credited.           |
| `failed`    | Payment failed or was declined by the card processor.                       |
| `refunded`  | Payment was completed but has been refunded by an admin.                    |

## Error Responses

### 401 Unauthorized

Invalid or missing API key:

```json theme={null}
{
  "success": false,
  "error": "Invalid API key"
}
```

### 404 Not Found

Payment doesn't exist or doesn't belong to your shop:

```json theme={null}
{
  "success": false,
  "error": "Payment not found"
}
```

Possible causes:

* Payment ID is incorrect
* Payment belongs to a different shop
* Payment was deleted (rare)

### 429 Too Many Requests

Rate limit exceeded:

```json theme={null}
{
  "success": false,
  "error": "Rate limit exceeded. Try again in 30 seconds."
}
```

## Use Cases

### 1. Verify Payment After Return URL

When customer returns to your site after payment:

```javascript theme={null}
// Customer redirected to: https://yoursite.com/success?payment_id=pay_abc123

app.get('/success', async (req, res) => {
  const paymentId = req.query.payment_id;

  // Retrieve payment to verify status
  const response = await fetch(
    `https://card2crypto.cc/api/v1/payments/${paymentId}`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.CARD2CRYPTO_API_KEY}`
      }
    }
  );

  const payment = await response.json();

  if (payment.data.status === 'completed') {
    // Payment successful - grant access
    res.send('Payment successful! Thank you for your purchase.');
  } else if (payment.data.status === 'pending') {
    // Still processing
    res.send('Payment is being processed...');
  } else {
    // Failed
    res.send('Payment failed. Please try again.');
  }
});
```

### 2. Check Payment Status in Webhook

Verify payment details when webhook is received:

```javascript theme={null}
app.post('/webhooks/card2crypto', async (req, res) => {
  // Return 200 immediately
  res.status(200).send('OK');

  // Process webhook asynchronously
  const { payment } = req.body;

  // Optional: Retrieve payment to double-check status
  const response = await fetch(
    `https://card2crypto.cc/api/v1/payments/${payment.id}`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.CARD2CRYPTO_API_KEY}`
      }
    }
  );

  const verifiedPayment = await response.json();

  if (verifiedPayment.data.status === 'completed') {
    // Process payment
    await fulfillOrder(verifiedPayment.data.metadata.order_id);
  }
});
```

### 3. Poll Payment Status

For synchronous payment verification (not recommended - use webhooks instead):

```javascript theme={null}
async function waitForPayment(paymentId, maxWaitSeconds = 300) {
  const startTime = Date.now();

  while ((Date.now() - startTime) / 1000 < maxWaitSeconds) {
    const response = await fetch(
      `https://card2crypto.cc/api/v1/payments/${paymentId}`,
      {
        headers: {
          'Authorization': `Bearer ${process.env.CARD2CRYPTO_API_KEY}`
        }
      }
    );

    const payment = await response.json();

    if (payment.data.status === 'completed') {
      return { success: true, payment: payment.data };
    } else if (payment.data.status === 'failed') {
      return { success: false, payment: payment.data };
    }

    // Wait 5 seconds before next check
    await new Promise(resolve => setTimeout(resolve, 5000));
  }

  return { success: false, error: 'Timeout waiting for payment' };
}
```

<Warning>
  Polling is inefficient and can hit rate limits. Use webhooks for real-time notifications instead.
</Warning>

## Implementation Examples

### Node.js / Express

```javascript theme={null}
const express = require('express');
const fetch = require('node-fetch');

const app = express();
const API_KEY = process.env.CARD2CRYPTO_API_KEY;

app.get('/payment/:id', async (req, res) => {
  try {
    const response = await fetch(
      `https://card2crypto.cc/api/v1/payments/${req.params.id}`,
      {
        headers: {
          'Authorization': `Bearer ${API_KEY}`
        }
      }
    );

    const payment = await response.json();

    if (payment.success) {
      res.json(payment.data);
    } else {
      res.status(404).json({ error: payment.error });
    }

  } catch (error) {
    console.error('Failed to retrieve payment:', error);
    res.status(500).json({ error: 'Failed to retrieve payment' });
  }
});
```

### PHP

```php theme={null}
<?php

function getPayment($paymentId) {
    $apiKey = getenv('CARD2CRYPTO_API_KEY');

    $ch = curl_init('https://card2crypto.cc/api/v1/payments/' . $paymentId);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $apiKey
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $result = json_decode($response, true);

    if ($httpCode === 200 && $result['success']) {
        return $result['data'];
    } else {
        throw new Exception($result['error'] ?? 'Payment not found');
    }
}

// Usage
try {
    $payment = getPayment('pay_abc123');

    if ($payment['status'] === 'completed') {
        echo 'Payment successful!';
    } else {
        echo 'Payment status: ' . $payment['status'];
    }
} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage();
}
```

### Python / Flask

```python theme={null}
import os
import requests
from flask import Flask, jsonify

app = Flask(__name__)
API_KEY = os.getenv('CARD2CRYPTO_API_KEY')

@app.route('/payment/<payment_id>')
def get_payment(payment_id):
    try:
        response = requests.get(
            f'https://card2crypto.cc/api/v1/payments/{payment_id}',
            headers={
                'Authorization': f'Bearer {API_KEY}'
            }
        )

        payment = response.json()

        if payment['success']:
            return jsonify(payment['data'])
        else:
            return jsonify({'error': payment['error']}), 404

    except Exception as e:
        return jsonify({'error': str(e)}), 500
```

## Best Practices

### 1. Use Webhooks Instead of Polling

Webhooks provide instant notifications when payment status changes:

```javascript theme={null}
// Bad - Polling
async function checkPayment(paymentId) {
  setInterval(async () => {
    const payment = await getPayment(paymentId);
    if (payment.status === 'completed') {
      fulfillOrder();
    }
  }, 5000); // Check every 5 seconds - inefficient!
}

// Good - Webhook
app.post('/webhooks/card2crypto', (req, res) => {
  if (req.body.event === 'payment.completed') {
    fulfillOrder(req.body.payment.metadata.order_id);
  }
  res.send('OK');
});
```

### 2. Verify Payment Belongs to Your Shop

The API only returns payments for your shop, but double-check in production:

```javascript theme={null}
const payment = await getPayment(paymentId);

if (payment.metadata.order_id !== expectedOrderId) {
  throw new Error('Payment does not match order');
}
```

### 3. Handle All Statuses

Don't assume payments are always completed:

```javascript theme={null}
switch (payment.status) {
  case 'completed':
    await fulfillOrder();
    break;
  case 'pending':
    await sendReminderEmail();
    break;
  case 'failed':
    await logFailedPayment();
    break;
  case 'refunded':
    await revokeAccess();
    break;
  default:
    console.error('Unknown payment status:', payment.status);
}
```

### 4. Cache Payment Data

Reduce API calls by caching payment data:

```javascript theme={null}
const cache = new Map();

async function getPayment(paymentId) {
  // Check cache first
  if (cache.has(paymentId)) {
    const cached = cache.get(paymentId);
    // Only cache completed/failed/refunded (final states)
    if (['completed', 'failed', 'refunded'].includes(cached.status)) {
      return cached;
    }
  }

  // Fetch from API
  const payment = await fetchPayment(paymentId);

  // Cache if in final state
  if (['completed', 'failed', 'refunded'].includes(payment.status)) {
    cache.set(paymentId, payment);
  }

  return payment;
}
```

## Testing

Test payment retrieval with real payment IDs from your shop.

See [Testing Guide](/resources/testing) for details.

## Related Resources

<CardGroup cols={2}>
  <Card title="Create Payment" icon="plus" href="/api-reference/payments/create">
    Create a new payment
  </Card>

  <Card title="Webhook Events" icon="list" href="/webhooks/events">
    Get real-time payment updates
  </Card>

  <Card title="Payment Concepts" icon="book" href="/concepts/payments">
    Understand payment lifecycle
  </Card>

  <Card title="Error Reference" icon="triangle-exclamation" href="/resources/errors">
    Complete list of error codes
  </Card>
</CardGroup>
