CryptoPay API

CryptoPay API

API para integración de pagos con criptomonedas

URL Base: https://cryptopay.lat

Versión: 1.0.0

Introducción

La API de CryptoPay te permite integrar pagos con criptomonedas en tu aplicación de manera rápida y segura. Nuestra API RESTful sigue los estándares de la industria y proporciona endpoints intuitivos para gestionar pagos, transacciones y billeteras.

Características Principales

Ambientes Disponibles

Formato de Respuesta

Todas las respuestas de la API están en formato JSON y siguen la siguiente estructura:

{
    "status": 200,
    "error": null,
    "data": {
        // Datos específicos del endpoint
    }
}

Autenticación

Todas las peticiones a la API requieren autenticación mediante una API Key. Para obtener tu API Key:

  1. Regístrate en CryptoPay
  2. Completa el proceso de onboarding
  3. Obtén tu API Key en la sección de integraciones

Headers de Autenticación

Incluye tu API Key en el header de todas las peticiones:

X-API-KEY: tu_api_key

Seguridad

Endpoints

POST /api/crypto-payment Crear pago cripto

Parámetros

  • amount number
    Monto a pagar
  • currency string
    Moneda de pago (default: USDT)
  • description string
    Descripción del pago

Las notificaciones se configuran una sola vez por cliente (menú Webhooks o POST /api/webhook), no por petición. Ver la sección Webhooks.

Respuestas

Código Descripción Schema
201 Creado
{
    "request_id": "string",
    "address": "string",
    "amount": "number",
    "network": "string",
    "expires_at": "timestamp"
}
GET /api/crypto-payment/status/{request_id} Consultar estado de pago

Parámetros

  • request_id string
    ID de la solicitud de pago

Respuestas

Código Descripción Schema
200 Éxito
{
    "request_id": "string",
    "status": "string",
    "amount": "number",
    "total_paid": "number",
    "transactions": [],
    "created_at": "timestamp",
    "updated_at": "timestamp"
}
GET /api/transactions Listar transacciones

Parámetros de Consulta

  • page number
    Número de página
  • limit number
    Límite de resultados por página
  • status string
    Filtrar por estado
  • start_date string
    Fecha de inicio
  • end_date string
    Fecha de fin

Respuestas

Código Descripción Schema
200 Éxito
{
    "status": 200,
    "error": null,
    "data": {
        "transactions": [
            {
                "id": "string",
                "timestamp": "string",
                "amount": "number",
                "currency": "string",
                "status": "string",
                "type": "string"
            }
        ],
        "pagination": {
            "total": "number",
            "page": "number",
            "limit": "number",
            "pages": "number"
        }
    }
}

Webhooks

CryptoPay envía notificaciones salientes (webhooks) a tu servidor cuando ocurre un evento de pago. Se entregan de forma asíncrona con reintentos automáticos y firma HMAC, para que no dependas de hacer polling.

Configuración

Hay dos formas de configurar el destino:

  1. Panel: menú Webhooks → ingresa la URL de destino y genera el Secreto de firma (HMAC).
  2. API (con tu X-API-KEY):
    # Registrar/actualizar la URL
    POST /api/webhook   { "webhook_url": "https://tu-app.com/webhooks/cryptopay" }
    
    # (Re)generar el secreto (se muestra UNA sola vez)
    POST /api/webhook/secret
    
    # Ver la configuración actual (nunca devuelve el secreto)
    GET  /api/webhook

Eventos Disponibles

Formato del Payload

CryptoPay hace un POST con este cuerpo:

{
    "event": "payment.completed",
    "data": {
        "request_id": 140,
        "client_id": 3,
        "txid": "0x…",
        "amount": "97.000000",
        "currency": "USDT",
        "network": "BSC",
        "status": "completed"
    }
}

Headers de la Petición

Verificación de la Firma (receptor)

// Node.js / Express (body crudo)
const crypto = require('crypto');
const raw = req.rawBody; // el cuerpo SIN parsear
const expected = 'sha256=' + crypto.createHmac('sha256', WEBHOOK_SECRET)
                                    .update(raw).digest('hex');
const ok = crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(req.get('X-CryptoPay-Signature') || '')
);
if (!ok) return res.status(401).end();
# PHP
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $WEBHOOK_SECRET);
if (! hash_equals($expected, $_SERVER['HTTP_X_CRYPTOPAY_SIGNATURE'] ?? '')) {
    http_response_code(401); exit;
}

Reintentos e Idempotencia

Mejores Prácticas

Seguridad

Manejo de Errores

Optimización

Manejo de Errores

La API utiliza códigos de estado HTTP estándar para indicar el éxito o fallo de las peticiones:

Formato de Error

{
    "status": "error_code",
    "error": "Mensaje de error descriptivo",
    "details": {
        "field": "Descripción del error específico"
    }
}

Errores Comunes

Ejemplos de Integración

<?php

namespace App\Libraries;

class CryptoPay
{
    private $apiKey;
    private $baseUrl;
    private $client;

    public function __construct()
    {
        $this->apiKey = getenv('CRYPTOPAY_API_KEY');
        $this->baseUrl = getenv('CRYPTOPAY_API_URL');
        $this->client = \Config\Services::curlrequest();
    }

    public function createPayment($amount, $description = null)
    {
        try {
            $response = $this->client->request('POST', $this->baseUrl . '/api/crypto-payment', [
                'headers' => [
                    'X-API-KEY' => $this->apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => [
                    'amount' => $amount,
                    'description' => $description
                ]
            ]);

            return json_decode($response->getBody(), true);
        } catch (\Exception $e) {
            log_message('error', '[CryptoPay::createPayment] Error: ' . $e->getMessage());
            throw new \RuntimeException('Error creating payment: ' . $e->getMessage());
        }
    }

    public function checkPaymentStatus($requestId)
    {
        try {
            $response = $this->client->request('GET', $this->baseUrl . '/api/crypto-payment/status/' . $requestId, [
                'headers' => [
                    'X-API-KEY' => $this->apiKey
                ]
            ]);

            return json_decode($response->getBody(), true);
        } catch (\Exception $e) {
            log_message('error', '[CryptoPay::checkPaymentStatus] Error: ' . $e->getMessage());
            throw new \RuntimeException('Error checking payment status: ' . $e->getMessage());
        }
    }
}
const axios = require('axios');

class CryptoPayClient {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://cryptopay.lat';
        this.client = axios.create({
            baseURL: this.baseUrl,
            headers: {
                'X-API-KEY': this.apiKey,
                'Content-Type': 'application/json'
            }
        });
    }

    async createPayment(amount, description = null) {
        try {
            const response = await this.client.post('/api/crypto-payment', {
                amount,
                description
            });
            return response.data;
        } catch (error) {
            throw new Error(error.response?.data?.error || 'Error creating payment');
        }
    }

    async checkPaymentStatus(requestId) {
        try {
            const response = await this.client.get(`/api/crypto-payment/status/${requestId}`);
            return response.data;
        } catch (error) {
            throw new Error(error.response?.data?.error || 'Error checking payment status');
        }
    }
}
import requests

class CryptoPayAPI:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = 'https://cryptopay.lat'
        self.headers = {
            'X-API-KEY': self.api_key,
            'Content-Type': 'application/json'
        }

    def create_payment(self, amount, description=None):
        try:
            response = requests.post(
                f'{self.base_url}/api/crypto-payment',
                headers=self.headers,
                json={
                    'amount': amount,
                    'description': description
                }
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f'Error creating payment: {str(e)}')

    def check_payment_status(self, request_id):
        try:
            response = requests.get(
                f'{self.base_url}/api/crypto-payment/status/{request_id}',
                headers=self.headers
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f'Error checking payment status: {str(e)}')