CryptoPayIn
Documentación para desarrolladores

Cree pagos que liquidan on-chain.

Todo lo necesario para crear un pago, enviar al cliente a un checkout alojado, seguir las confirmaciones y procesar webhooks firmados en producción.

URL base de la APIVersión 1
https://cryptopayin.com/v1
ProtocoloREST / JSON
AutenticaciónSecreto Bearer
ModoSolo en vivo
Introducción

Una API, un flujo alojado

CryptoPayIn cotiza un pedido en la divisa de presentación que usted elija, bloquea instantáneas verificadas de los tipos fiat/USD y cripto/USD, asigna una dirección de depósito dedicada y vigila sus propios nodos de blockchain a la espera del pago. La contabilidad interna, las comisiones y los saldos se mantienen en USD. Su backend recibe de inmediato una URL de checkout y, después, eventos de ciclo de vida firmados.

URL base/v1
Importes fiatUnidades menores ISO
Valores en criptoCadenas decimales
Caducidad predeterminada30 minutos
!

Esta es una API en vivo. No existe un prefijo de entorno de pruebas (sandbox). Cada creación exitosa asigna una dirección on-chain real. Utilice un importe pequeño en una divisa admitida para las pruebas de extremo a extremo y mantenga las claves secretas en su servidor.

Cómo encaja la integración

1Crear una clave

Genere un secreto una sola vez en Panel -> Desarrolladores.

2Crear el pago

Envíe mediante POST la divisa del pedido, el importe y el activo seleccionado.

3Abrir el checkout

Envíe al cliente a la URL alojada devuelta.

4Procesar el evento

Verifique el HMAC y actualice su pedido de forma idempotente.

Comenzar

Cree su primer pago

Genere una clave de API en el panel de comerciante, guarde el secreto en una variable de entorno y, después, cree un pago desde su backend. El ejemplo utiliza ETH para poder probarlo sin tener que elegir una red de token.

curl --request POST https://cryptopayin.com/v1/payments \
  --header "Authorization: Bearer $CPI_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: order_1042" \
  --data '{
    "amount": 49.99,
    "currency": "USD",
    "asset": "ETH",
    "order_ref": "order_1042",
    "redirect_url": "https://shop.example/orders/1042/paid"
  }'

Utilice la respuesta

Guarde el id del pago junto con su pedido y, después, redirija al cliente a checkout_url. No calcule usted mismo un importe en cripto ni una dirección de depósito.

{
  "id": "P-9F27C1E4KD",
  "object": "payment",
  "status": "created",
  "amount": 49.99,
  "amount_decimal": "49.99",
  "amount_minor": 4999,
  "currency": "USD",
  "currency_minor_units": 2,
  "amount_usd": 49.99,
  "amount_usd_cents": 4999,
  "fx_rate_usd": "1.000000000000",
  "fx_source": "fixed:USD",
  "fx_observed_at": "2026-07-17T13:00:00+00:00",
  "fx_discrepancy_bps": 0,
  "asset": "ETH",
  "network": "mainnet",
  "crypto_amount": "0.01388612",
  "crypto_received": "0",
  "deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
  "exchange_rate": "3600.00000000",
  "exchange_rate_currency": "USD",
  "exchange_rate_source": "median:cb,cg,cl",
  "exchange_rate_source_count": 3,
  "exchange_rate_observed_at": "2026-07-17T13:00:00+00:00",
  "exchange_rate_discrepancy_bps": 12,
  "confirmations": 0,
  "confirmations_required": 12,
  "order_ref": "order_1042",
  "checkout_url": "https://cryptopayin.com/i/P-9F27C1E4KD",
  "expires_at": "2026-07-17T13:30:00+00:00",
  "created_at": "2026-07-17T13:00:00+00:00",
  "completed_at": null
}
Credenciales

Autenticación

Toda solicitud a la API utiliza la clave secreta en una cabecera HTTP Bearer. Las claves secretas comienzan con csk_live_. El valor cpk_live_ que la acompaña es un identificador público para su panel y no debe utilizarse como credencial Bearer.

AUTHAuthorization: Bearer csk_live_...Todos los endpoints
Se muestra una sola vez

El secreto en texto plano solo se devuelve al crear la clave. CryptoPayIn almacena un hash de contraseña más un índice SHA-256 de búsqueda, nunca el secreto en texto plano.

Claves independientes

Cree claves independientes por aplicación o entorno y revóquelas de forma independiente. Una cuenta puede tener hasta 50 claves activas.

Solo en el servidor

Nunca incluya un valor csk_live_ en JavaScript de navegador, un binario móvil, un repositorio público o una página de checkout.

Alcance de los webhooks

Un endpoint de webhook puede aplicarse a toda la cuenta o vincularse a una única clave de API, lo que mantiene las integraciones aisladas.

i

Un secreto ausente, mal formado, revocado o desconocido devuelve 401 unauthorized. Una cuenta de comerciante suspendida o cerrada se rechaza de la misma manera. Una clave válida utilizada fuera de los permisos concedidos devuelve 403 insufficient_scope.

Reintentos seguros

Idempotencia

Envíe un Idempotency-Key único en cada creación de pago. Si su conexión se interrumpe tras el envío, reintente con el mismo JSON idéntico y la misma clave: CryptoPayIn devuelve el pago original en lugar de asignar otra dirección.

CasoResultadoHTTP
Primer usoCrea y devuelve un nuevo pago.201
Misma clave + mismo JSONDevuelve el pago existente con Idempotent-Replayed: true.200
Misma clave + JSON diferenteRechaza la solicitud como idempotency_conflict.409

Las claves están vinculadas a la credencial de la API y pueden contener entre 1 y 128 letras, dígitos, puntos, guiones bajos, dos puntos o guiones. Un UUID de pedido duradero es una buena opción. El mismo mecanismo también protege los retiros, de modo que un retiro reintentado nunca puede mover fondos dos veces.

API REST

Referencia API

La API abarca pagos, enlaces de pago, tiendas, productos, saldos y retiros. Las respuestas utilizan JSON en UTF-8 sobre HTTPS; toda creación o actualización requiere Content-Type: application/json. Las mutaciones están controladas por los permisos de la clave que realiza la llamada. De forma intencionada no existe un flujo CORS de navegador: las llamadas pertenecen a su backend.

GET/v1/assetsDescubrir los activos disponibles
GET/v1/currenciesDescubrir las divisas fiat de presentación
POST/v1/paymentsCrear un pago
GET/v1/paymentsListar y filtrar pagos
GET/v1/payments/{id}Recuperar un pago
i

La versión 1 puede recibir campos y endpoints compatibles con versiones anteriores. Un cambio de contrato disruptivo utilizará una nueva ruta base en lugar de modificar /v1 de forma silenciosa.

Referencia API

Listar activos

GET/v1/assetsRequiere autenticación Bearer

Utilice este endpoint como fuente de verdad para las opciones de checkout. Devuelve las entradas del catálogo habilitadas, los tipos de cambio verificados de forma independiente, los importes mínimos equivalentes en USD y si el nodo y el feed de precios están listos. Una entrada puede permanecer listada con available: false mientras un nodo se está sincronizando o su precio no puede verificarse.

curl https://cryptopayin.com/v1/assets \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "data": [{
    "asset": "USDT",
    "network": "TRC20",
    "type": "token",
    "decimals": 6,
    "minimum_amount": 1,
    "currency": "USD",
    "base_confirmations": 19,
    "available": true,
    "rate_usd": "1.00000000",
    "rate_source": "median:cb,cg,cl",
    "rate_source_count": 3,
    "rate_discrepancy_bps": 4,
    "rate_status": "healthy",
    "rate_updated_at": "2026-07-17T13:00:00+00:00"
  }]
}

Catálogo e identificadores de red

ActivoValor de redAbreviaturaConfirmaciones base
BTCmainnetBTC2
ETHmainnetETH6
USDTTRC20 / ERC20USDT.TRC2019 / 6
USDCERC20USDC.ERC206
DAIERC20DAI6
SHIBERC20SHIB6
PEPEERC20PEPE6
LTCmainnetLTC6
TRXmainnetTRX19
DOGEmainnetDOGE20
XMRmainnetXMR10
SOLmainnetSOL32
!

La disponibilidad es dinámica. No incorpore la tabla anterior como una lista de activos permitidos fija. Para símbolos con varias redes, como USDT, envíe network de forma explícita o utilice la abreviatura ASSET.NETWORK.

Referencia API

Listar divisas fiat

GET/v1/currenciesRequiere autenticación Bearer

Devuelve las divisas de presentación habilitadas, su precisión ISO y el estado actual de la conversión a USD. Ofrezca únicamente las filas con available: true. El USD es intrínseco; cualquier otra divisa necesita una cotización en vivo reciente y una comprobación de referencia independiente. minimum_amount convierte a esa divisa el mínimo más bajo configurado entre los activos habilitados; el activo elegido puede requerir un importe mayor, así que consulte también siempre GET /v1/assets.

curl https://cryptopayin.com/v1/currencies \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "accounting_currency": "USD",
  "data": [{
    "currency": "EUR",
    "name": "Euro",
    "symbol": "€",
    "minor_units": 2,
    "available": true,
    "minimum_amount": "0.86",
    "rate_usd": "1.160000000000",
    "rate_source": "coinbase+ecb",
    "rate_source_count": 2,
    "rate_discrepancy_bps": 18,
    "rate_updated_at": "2026-07-17T13:00:00+00:00",
    "rate_reference_at": "2026-07-16T00:00:00+00:00"
  }]
}
i

Omitir la divisa en POST /v1/payments sigue significando USD por compatibilidad con versiones anteriores. Las divisas sin decimales, como el JPY, rechazan importes fraccionarios. Trate los mínimos y los tipos de cambio del catálogo como datos en vivo, nunca como constantes fijas.

Referencia API

Crear un pago

POST/v1/payments120 solicitudes / minuto / clave

Crea una factura en la divisa de presentación solicitada, bloquea instantáneas recién verificadas de los tipos fiat/USD y cripto/USD, calcula el importe exacto en cripto y vincula una dirección de depósito on-chain dedicada.

Cuerpo de la solicitud

CampoTipoRequisitoDescripción
amountnumber o cadena decimalobligatorioImporte en currency, con la precisión ISO de esa divisa. Su equivalente en USD bloqueado no debe superar $1,000,000.00; también se aplican los mínimos del activo.
currencystringopcionalDivisa habilitada de 3 letras de GET /v1/currencies. El valor predeterminado es USD.
assetstringobligatorioSímbolo como ETH, o abreviatura como USDT.TRC20.
networkstringcondicionalObligatorio cuando un símbolo existe en varias redes. Ejemplo: ERC20.
order_refstringopcionalSu identificador de pedido, máximo 128 caracteres. Se devuelve en las respuestas y los eventos de la API.
customer_emailstringopcionalDirección de correo electrónico válida, máximo 190 caracteres. Se almacena junto con el registro de pago del comerciante.
redirect_urlstringopcionalURL HTTPS, máximo 255 caracteres, que se ofrece tras un checkout exitoso.

Campos de la respuesta

CampoTipoDescripción
idstringIdentificador estable del pago que comienza con P-.
statusstringEstado actual del ciclo de vida.
amount / amount_decimal / amount_minornumber / string / integerImporte de presentación solicitado en sus formas práctica, decimal exacta y de unidad menor ISO.
currency / currency_minor_unitsstring / integerDivisa de presentación bloqueada y su precisión.
amount_usd / amount_usd_centsnumber / integerValor contable interno en USD, inmutable.
fx_rate_usd / fx_source / fx_observed_atdecimal string / string / ISO 8601Instantánea bloqueada de USD por unidad de presentación y sus metadatos de auditoría.
asset / networkstringActivo on-chain resuelto.
crypto_amountdecimal stringImporte exacto que el cliente debe enviar. Nunca interprete los decimales de cripto como números de punto flotante binarios.
crypto_receiveddecimal stringTotal observado actualmente en la dirección de depósito.
deposit_addressstringDirección dedicada asignada para este pago.
exchange_ratedecimal stringTipo de cambio cripto/USD bloqueado utilizado para calcular crypto_amount; este campo conserva su significado original de la v1.
exchange_rate_source / exchange_rate_observed_atstring / ISO 8601Instantánea de auditoría del tipo de cambio en cripto, inmutable.
confirmationsintegerConfirmaciones de red actuales.
confirmations_requiredintegerUmbral para este pago. Los niveles de USD más altos pueden requerir confirmaciones adicionales.
checkout_urlURLFactura alojada que se muestra al cliente.
expires_atISO 8601Plazo límite para una factura sin pagar.
completed_atISO 8601 / nullMomento de liquidación final una vez completado.

Ambas conversiones en vivo se validan por antigüedad, número de fuentes y divergencia antes de la creación. Si la verificación falla, la creación devuelve un error en lugar de utilizar un tipo de cambio obsoleto. El importe en cripto se redondea al alza con una precisión útil para el activo, de modo que el redondeo nunca deja al comerciante con menos de lo debido.

Referencia API

Listar pagos

GET/v1/payments240 solicitudes / minuto / clave

Devuelve primero los pagos más recientes de la cuenta de comerciante autenticada. Utilice la paginación por cursor para la conciliación y filtros exactos para localizar un pedido sin recorrer todo el historial.

Parámetros de consulta

ParámetroValor predeterminadoDescripción
limit20Tamaño de página de 1 a 100.
starting_afterID del pago devuelto como next_cursor de la página anterior.
statusEstado exacto del ciclo de vida, como pending, completed o expired.
order_refReferencia exacta del pedido del comerciante, máximo 128 caracteres.
curl "https://cryptopayin.com/v1/payments?status=completed&limit=20" \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "data": [{
    "id": "P-9F27C1E4KD",
    "object": "payment",
    "status": "completed",
    "amount": 49.99,
    "currency": "USD",
    "asset": "ETH",
    "network": "mainnet",
    "crypto_amount": "0.01388612",
    "crypto_received": "0.01388612",
    "order_ref": "order_1042",
    "confirmations": 12,
    "confirmations_required": 12,
    "completed_at": "2026-07-17T13:12:42+00:00"
  }],
  "has_more": true,
  "next_cursor": "P-9F27C1E4KD"
}
i

Cuando has_more es true, pase next_cursor sin modificar como starting_after. Los parámetros de consulta de tipo array desconocidos o repetidos se rechazan en lugar de ignorarse.

Referencia API

Recuperar un pago

GET/v1/payments/{id}240 solicitudes / minuto / clave

Devuelve el mismo objeto de pago que la creación, con el estado actualizado, el importe recibido, el hash de la transacción y las confirmaciones. Una clave solo puede recuperar los pagos que pertenecen a su cuenta de comerciante.

curl https://cryptopayin.com/v1/payments/P-9F27C1E4KD \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
i

Los webhooks deben impulsar las actualizaciones normales de los pedidos. Utilice la recuperación para conciliar tras un tiempo de espera agotado, verificar un evento, renderizar una página de estado en el backend o reparar entregas fallidas.

Modelo de estados

Ciclo de vida del pago

Trate siempre el estado de la API como la fuente autorizada. No infiera que un pago se ha completado a partir de una redirección del navegador ni de que el cliente afirme haber pagado.

created->pending->underpaidoconfirming->completed/overpaid
EstadoSignificadoAcción del comerciante
createdFactura y dirección asignadas; aún no se detecta financiación.Mostrar el checkout alojado.
pendingA la espera de un pago on-chain utilizable.Mantener el pedido abierto.
underpaidLos fondos recibidos están por debajo de la tolerancia del comerciante.Pedir al pagador que envíe el importe restante mostrado.
confirmingSe ha detectado el valor suficiente; a la espera de confirmaciones.No entregue el pedido todavía.
completedSe ha alcanzado el valor y las confirmaciones requeridos.Entregue el pedido exactamente una vez.
overpaidSe confirmó más de lo esperado.Entregue el pedido y revise el excedente.
expiredNo se detectó ningún pago válido antes de la caducidad.Cree un nuevo pago.
failedFalló la asignación de la dirección o el procesamiento.Registre el error y cree un nuevo pago.
!

Las transferencias on-chain son irreversibles y CryptoPayIn no dispone de un mecanismo de reembolso: un pago confirmado es definitivo. Cualquier devolución por cortesía se gestiona directamente entre usted y su cliente, al margen de la plataforma.

Experiencia del cliente

Checkout alojado

Cada pago de la API incluye un checkout_url adaptable. Muestra el comerciante, el importe de presentación solicitado, el equivalente en USD bloqueado cuando corresponde, el importe exacto en cripto, la dirección de depósito, el código QR, el aviso de red, la cuenta atrás y el progreso de confirmación en vivo.

Tipo de cambio bloqueado

El cliente ve el mismo crypto_amount que devuelve la API durante la ventana de la factura.

Sin cuenta de cliente

El pagador no crea una cuenta de CryptoPayIn ni comparte credenciales.

Estado en vivo

La página consulta el pago de forma segura y pasa de la espera a la confirmación y, después, al pago.

Redirección del comerciante

Se ofrece una redirect_url HTTPS tras el éxito; no constituye una prueba de pago.

i

Mantenga la entrega del pedido en su backend. La navegación del navegador se puede abandonar, repetir o falsificar; solo un webhook verificado o una solicitud GET autenticada demuestran el estado del pago.

Credenciales

Permisos & ámbitos

Cada clave de API lleva un conjunto fijo de permisos elegido al crearla en Panel → Desarrolladores. Cada endpoint comprueba los ámbitos de la clave antes de realizar cualquier operación; una llamada fuera del alcance concedido a una clave devuelve 403 insufficient_scope con una cabecera X-Required-Scope que indica el permiso que falta. Los ámbitos se establecen una sola vez al crear la clave y no se pueden ampliar después — emita una nueva clave en su lugar. Las claves creadas antes de que existieran los ámbitos conservan exactamente su capacidad original: payments:read y payments:write.

ÁmbitoConcedeEndpoints
payments:readListar y recuperar pagosGET /v1/payments, GET /v1/payments/{id}
payments:writeCrear pagos alojadosPOST /v1/payments
links:readListar y recuperar enlaces de pagoGET /v1/links, GET /v1/links/{id}
links:writeCrear, editar, pausar y eliminar enlaces de pagoPOST/PATCH/DELETE /v1/links
shops:readListar y recuperar tiendas y sus productosGET /v1/shops, GET .../products
shops:writeCrear y editar tiendas, productos y variantesPOST/PATCH/DELETE /v1/shops y productos
balance:readConsultar saldos en cripto y estimaciones en USDGET /v1/balance
payouts:readListar y recuperar retirosGET /v1/payouts, GET /v1/payouts/{id}
payouts:writeSolicitar retiros on-chainPOST /v1/payouts
!

payouts:write mueve fondos on-chain y es irreversible. Concédalo únicamente a claves en las que confíe plenamente, mantenga esas claves en el servidor y utilice preferiblemente una clave dedicada por cada proceso automatizado. GET /v1/account indica los ámbitos de la clave que realiza la llamada y los límites de su cuenta.

Compradores automatizados

Pago de agentes

Todo enlace de pago activo es también un checkout legible por máquinas: un agente de IA o cualquier script puede descubrirlo, crear una factura y leer la entrega sin necesidad de un navegador, y sin ninguna clave de API, porque se trata de endpoints públicos para compradores en el dominio del enlace, no de endpoints de comerciante. Contrato completo y ejemplo práctico: cryptopayin.com/agents.

GEThttps://cryptopaylink.co/pay/{link}.jsonpúblico · descubrimiento

Devuelve el estado, el precio, los activos aceptados y el contrato exacto de entrada para la llamada de facturación (campos obligatorios, esquema de envío, variantes).

POSThttps://cryptopaylink.co/pay/{link}/invoicepúblico · admite Idempotency-Key

Crea la factura mediante el mismo núcleo, la misma instantánea de precios y los mismos límites antiabuso que la página alojada, y devuelve la dirección de depósito, el importe exacto en cripto, un URI de cartera y la URL del recibo. El agente paga después on-chain desde cualquier cartera que controle.

GEThttps://cryptopaylink.co/pay/{link}/receipt?p={payment}público · consultar cada 5–10 s

Estado y confirmaciones en vivo; una vez que el pago se completa, la respuesta incluye la entrega (su contenido de texto, una URL privada o una clave de licencia reservada para ese pago), además de su mensaje de éxito y la URL de redirección.

Las tiendas hablan el mismo protocolo

Los escaparates exponen el mismo flujo en su propio dominio: el catálogo con existencias en vivo y, después, una única llamada que valida el carrito, reserva las existencias y devuelve la factura.

GEThttps://shopycrypto.com/s/{shop}.jsonpúblico · catálogo
POSThttps://shopycrypto.com/s/{shop}/orderpúblico · carrito → factura, admite Idempotency-Key
GEThttps://shopycrypto.com/s/{shop}/o/{order}/receipt?p={payment}público · consultar cada 5–10 s

Controles del vendedor

El pago de agentes está activado de forma predeterminada y cuesta la misma comisión fija del 1 %. Desactívelo para toda la cuenta en Panel → Configuración → General → IA y pago de agentes: los endpoints para máquinas de los enlaces y las tiendas responderán entonces 403 agents_disabled mientras sus páginas de checkout para humanos siguen funcionando. Los pagos creados por agentes no llevan ninguna marca especial: son pagos normales en su panel, sus webhooks y sus exportaciones.

Recursos del comerciante

Tiendas

Un escaparate alojado que agrupa productos bajo una única página de marca. Una cuenta puede tener hasta 10 tiendas. Los productos se gestionan mediante los endpoints de producto anidados que se muestran a continuación.

GET/v1/shopsshops:read
POST/v1/shopsshops:write
GET/v1/shops/{id}shops:read
PATCH/v1/shops/{id}shops:write
DELETE/v1/shops/{id}shops:write

Cuerpo de la solicitud

CampoTipoRequisitoDescripción
namestringobligatorio2–80 caracteres.
taglinestringopcionalHasta 160 caracteres.
themestringopcionallight (predeterminado) o dark.
accentstringopcionalColor de acento hexadecimal de la paleta de la tienda, devuelto como accent_palette en GET /v1/shops.
accepted_assetsarray de stringsopcionalActivos predeterminados para los productos de la tienda, p. ej. ["BTC","LTC","XMR"]. Se aplica a todos los productos cuando se modifica.
statusstringopcionalSolo en PATCH: active o paused.
i

Una tienda deshabilitada por CryptoPayIn por motivos de política no se puede reactivar ni eliminar mediante la API y devuelve admin_disabled (403). Eliminar una tienda elimina sus productos; los pagos pasados permanecen intactos.

Recursos del comerciante

Productos & variantes

Los productos residen dentro de una tienda. Cada tienda puede tener hasta 50 productos. Un producto puede ser digital (con entrega instantánea) o físico (con países de envío), y puede exponer hasta 30 combinaciones de variantes formadas a partir de 1–3 grupos de opciones.

GET/v1/shops/{shop}/productsshops:read
POST/v1/shops/{shop}/productsshops:write
GET/v1/shops/{shop}/products/{id}shops:read
PATCH/v1/shops/{shop}/products/{id}shops:write
DELETE/v1/shops/{shop}/products/{id}shops:write

Cuerpo de la solicitud

CampoTipoRequisitoDescripción
titlestringobligatorio3–120 caracteres.
description / blurbstringopcionalDescripción completa y una línea de tarjeta de tienda de ≤200 caracteres.
emojistringopcionalUn único emoji que se muestra en la tarjeta del producto.
featuredbooleanopcionalComo máximo un producto destacado por tienda.
product_typestringopcionaldigital (predeterminado) o physical.
shipping_countriesarray de stringscondicionalSolo para físicos: códigos ISO como ["FR","BE"], o ["*"] para todo el mundo.
amount_type / currency / amount / min / maxmixtocondicionalPrecio base, con las mismas reglas que los enlaces de pago. Los productos físicos deben ser fixed.
max_usesintegeropcionalLímite total de ventas (0 = ilimitado).
delivery_type + delivery_text/url/keysmixtoopcionalEntrega digital para el producto base, con la misma estructura que los enlaces de pago.
variant_optionsarrayopcional1–3 grupos {name, values[]}, cada uno con 2–10 valores. Las combinaciones no deben superar 30.
variantsarraycondicionalUn objeto por combinación (véase más abajo). Obligatorio y exhaustivo cuando está presente variant_options.
statusstringopcionalSolo en PATCH: active o paused.

Objeto de variante

CampoTipoDescripción
optionsarray de stringsUn valor por grupo de opciones, en el orden de los grupos, p. ej. ["Pro","Lifetime"].
pricenumber o stringPrecio de la variante en la divisa del producto.
stockinteger o nullUnidades restantes, o null para ilimitado.
delivery_type + delivery_text/url/keysmixtoAnulación opcional de la entrega digital por variante (inherit de forma predeterminada). Las claves deben ser únicas en todo el producto.
curl -X POST https://cryptopayin.com/v1/shops/SH-JYRK8TFJ/products \
  -H "Authorization: Bearer $CPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Software license",
    "amount": 30,
    "currency": "USD",
    "variant_options": [
      {"name": "Edition", "values": ["Standard", "Pro"]},
      {"name": "Term", "values": ["1 year", "Lifetime"]}
    ],
    "variants": [
      {"options": ["Standard","1 year"], "price": 30, "delivery_type": "keys", "delivery_keys": ["S1Y-1"]},
      {"options": ["Standard","Lifetime"], "price": 79, "stock": 10, "delivery_type": "keys", "delivery_keys": ["SLT-1"]},
      {"options": ["Pro","1 year"], "price": 59, "delivery_type": "keys", "delivery_keys": ["P1Y-1"]},
      {"options": ["Pro","Lifetime"], "price": 149, "stock": 5, "delivery_type": "keys", "delivery_keys": ["PLT-1"]}
    ]
  }'
i

PATCH conserva los pedidos existentes y las claves ya entregadas. Para ajustar precios o existencias, reenvíe el array variants correspondiente; las combinaciones que omita se pausan si tienen pedidos, o se eliminan en caso contrario. Un producto puede tener como máximo 10,000 claves de licencia activas entre su base y sus variantes, y cada clave debe ser única dentro del producto.

Recursos del comerciante

Saldo

GET/v1/balancebalance:read

Devuelve sus saldos liquidados en cripto por activo, con una estimación en USD hecha con la mejor información disponible y la comisión de red que se cobra en un retiro. La contabilidad interna siempre está en USD; los saldos se acumulan a partir de los pagos completados, netos de la comisión del comerciante.

{
  "object": "list",
  "accounting_currency": "USD",
  "minimum_payout_usd": 25,
  "data": [{
    "asset": "USDT",
    "network": "TRC20",
    "amount": "99.099",
    "usd_estimate": 99.02,
    "payout_network_fee": "2.445463"
  }]
}
i

usd_estimate es null cuando un tipo de cambio verificado en vivo no está disponible momentáneamente; el saldo subyacente sigue siendo exacto. Utilice estos valores para decidir los retiros, no para la contabilidad final.

Recursos del comerciante

Retiros

Mueva cripto liquidada a una cartera externa. Los retiros son irreversibles, por lo que este endpoint aplica todas las salvaguardas que aplica el panel: un destino válido para el activo, un tipo de cambio verificado en vivo, el mínimo de la cuenta, saldo suficiente incluyendo la comisión de red, y confirmación de dos factores cuando su cuenta tiene 2FA activado.

GET/v1/payoutspayouts:read
POST/v1/payoutspayouts:write · 30 / min / clave
GET/v1/payouts/{id}payouts:read

Cuerpo de la solicitud

CampoTipoRequisitoDescripción
assetstringobligatorioSímbolo o abreviatura, p. ej. LTC o USDT.TRC20.
networkstringcondicionalObligatorio cuando el símbolo existe en varias redes.
amountnumber o stringobligatorioImporte a enviar, sin incluir la comisión de red, con la precisión del activo. Su valor en USD debe cumplir el mínimo de la cuenta.
addressstringobligatorioDirección de destino, validada para la cadena del activo.
notestringopcionalSu propia referencia, hasta 255 caracteres.
totp_codestringcondicionalCódigo actual de 6 dígitos o código de recuperación. Obligatorio cuando el 2FA está activado en la cuenta.
curl -X POST https://cryptopayin.com/v1/payouts \
  -H "Authorization: Bearer $CPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: withdraw-2026-07-19-01" \
  -d '{
    "asset": "USDT.TRC20",
    "amount": "50",
    "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "note": "weekly settlement"
  }'
{
  "id": "W-EM64ZCJB",
  "object": "payout",
  "status": "requested",
  "asset": "USDT",
  "network": "TRC20",
  "amount": "50",
  "fee": "2.445463",
  "total_debited": "52.445463",
  "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "txid": null,
  "confirmations": 0,
  "created_at": "2026-07-19T19:10:00+00:00"
}

Ciclo de vida del estado

EstadoSignificado
requestedReservado de su saldo; a la espera de revisión del operador o aprobación automática.
approved / processingAprobado y en cola para su difusión por el ejecutor.
sentDifundido on-chain; se rellena txid.
confirmedAlcanzó las confirmaciones requeridas. Definitivo.
failedNo se pudo enviar; failure_message explica el motivo y el saldo se devuelve.
cancelledCancelado antes de la difusión; el saldo reservado se devuelve.

Envíe un Idempotency-Key para que un reintento de red nunca pueda crear un segundo retiro: la misma clave con el mismo cuerpo devuelve el retiro original (Idempotent-Replayed: true); la misma clave con un cuerpo diferente devuelve 409 idempotency_conflict. El código 2FA se excluye deliberadamente de la huella de idempotencia para que un código que cambia no provoque un conflicto falso. La reserva debita su saldo de inmediato; un retiro fallido o cancelado lo devuelve.

Recursos del comerciante

Cuenta

GET/v1/accountcualquier clave válida

Devuelve el perfil de su cuenta, los ámbitos de la clave que realiza la llamada, la comisión de la plataforma y todos los límites vigentes — útil para una integración autoconfigurable o una comprobación previa.

{
  "object": "account",
  "id": "MC67T3PHQZ",
  "fee_bps": 100,
  "fee_percent": 1,
  "default_currency": "USD",
  "two_factor_enabled": false,
  "api_key": {"label": "production", "scopes": ["payments:read","payments:write"]},
  "limits": {
    "shops": {"used": 1, "max": 10},
    "payment_links": {"used": 0, "max": 50},
    "products_per_shop_max": 50,
    "variant_combinations_per_product_max": 30,
    "license_keys_per_product_max": 10000,
    "active_api_keys_max": 50,
    "checkout_fields_per_link_max": 5
  },
  "minimum_payout_usd": 25
}
Eventos servidor a servidor

Webhooks

Añada hasta 10 endpoints públicos HTTPS en Panel -> Desarrolladores. Cada endpoint recibe su propio secreto de firma whsec_..., que se muestra una sola vez. Puede escuchar en toda la cuenta o vincularse a una clave de API activa concreta; los endpoints vinculados a una clave reciben únicamente los pagos creados con esa clave.

Verifique antes de procesar

CryptoPayIn firma el cuerpo exacto de la solicitud en bruto utilizando el secreto del endpoint. La versión 1 firma timestamp + "." + raw_body. Rechace las marcas de tiempo obsoletas antes de aceptar el evento.

import crypto from "node:crypto";

const timestamp = req.headers["x-cpi-timestamp"];
const signature = req.headers["x-cpi-signature"];
const rawBody = req.rawBody; // Buffer captured before JSON parsing

if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
  throw new Error("stale webhook");
}
const expected = "sha256=" + crypto
  .createHmac("sha256", process.env.CPI_WEBHOOK_SECRET)
  .update(Buffer.concat([Buffer.from(`${timestamp}.`), rawBody]))
  .digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
if (!valid) throw new Error("invalid webhook signature");

Cabeceras de entrega

CabeceraEjemploPropósito
Content-Typeapplication/jsonCuerpo JSON en UTF-8.
X-CPI-Timestamp1784293200Segundos Unix incluidos en el mensaje firmado.
X-CPI-Signaturesha256=...HMAC-SHA256 en hexadecimal.
X-CPI-Signature-Versionv1Versión del esquema de firma.
X-CPI-Event-Idevt_a12b...ID lógico estable del evento; idéntico en todos los reintentos.
X-CPI-Delivery-Id1842ID estable del registro de entrega del endpoint.

Carga útil del pago

{
  "event_id": "evt_a12b34c56d78e90f12345678",
  "event": "payment.completed",
  "id": "P-9F27C1E4KD",
  "status": "completed",
  "order_ref": "order_1042",
  "amount": 49.99,
  "amount_decimal": "49.99",
  "amount_minor": 4999,
  "currency_minor_units": 2,
  "currency": "USD",
  "amount_usd": 49.99,
  "amount_usd_cents": 4999,
  "fx_rate_usd": "1.000000000000",
  "fx_source": "fixed:USD",
  "fx_observed_at": "2026-07-17T13:00:00Z",
  "fx_discrepancy_bps": 0,
  "exchange_rate": "3600.00000000",
  "exchange_rate_currency": "USD",
  "exchange_rate_source": "median:cb,cg,cl",
  "exchange_rate_source_count": 3,
  "exchange_rate_observed_at": "2026-07-17T13:00:00Z",
  "exchange_rate_discrepancy_bps": 12,
  "asset": "ETH",
  "network": "mainnet",
  "crypto_amount": "0.01388612",
  "crypto_received": "0.01388612",
  "txid": "0x9d81...75af",
  "confirmations": 12,
  "confirmations_required": 12,
  "deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
  "sent_at": "2026-07-17T13:12:42Z"
}

Reintentos y seguridad del endpoint

Devuelva cualquier 2xx

Una entrega se considera exitosa con HTTP 200-299. Realice el trabajo costoso de forma asíncrona y responda rápidamente.

Seis intentos en total

Se conservan el cuerpo exacto y el ID del evento; los fallos se reintentan aproximadamente al cabo de 1 minuto, 5 minutos, 30 minutos, 2 horas y 6 horas.

Sin redirecciones

Las respuestas 3xx no se siguen. Registre directamente la URL HTTPS final.

Solo destinos públicos

Las IP privadas, de loopback, link-local y reservadas están bloqueadas; cada respuesta DNS se valida y la conexión queda anclada.

!

Las entregas son al menos una vez. Haga que su gestor sea idempotente registrando event_id con una restricción de unicidad antes de la entrega del pedido. Recupere el objeto de la API al conciliar un evento inesperado.

Webhooks

Referencia de eventos

payment.completedSe confirmó el valor esperado.
payment.overpaidSe confirmó más de lo esperado.
payment.underpaidSe detectó financiación por debajo de la tolerancia.
payment.expiredSe cerró la ventana de la factura sin pagar.
payment.failedFalló la configuración o el procesamiento del pago.
payout.sentRetiro difundido on-chain.
payout.confirmedEl retiro alcanzó las confirmaciones.
payout.failedEl retiro no pudo completarse.
webhook.testPrueba manual de conectividad.

Estructura del evento de retiro

{
  "event_id": "evt_b98c76d54e32a10f87654321",
  "event": "payout.sent",
  "id": "W-8J2K7M4RQP",
  "status": "sent",
  "asset": "ETH",
  "network": "mainnet",
  "amount": "0.25",
  "fee": "0.00081768",
  "address": "0x84f2...9bc1",
  "txid": "0xa1c4...07ee",
  "confirmations": 0,
  "note": "weekly treasury",
  "sent_at": "2026-07-17T14:08:31Z"
}
Fiabilidad

Errores y límites de frecuencia

Los errores siempre utilizan un único envoltorio JSON. Ramifique la lógica según error.type; el mensaje legible puede mejorarse sin que cambie la versión. Cite error.request_id o la cabecera de respuesta X-Request-Id correspondiente al contactar con soporte.

{
  "error": {
    "type": "ambiguous_asset",
    "message": "specify network (e.g. USDT.ERC20 or USDT.TRC20)",
    "request_id": "b942e21f8dca4b06b8672eb9"
  }
}
HTTPTipos habitualesSignificado
400invalid_request, unknown_parameterJSON, consulta o cabecera de idempotencia mal formados.
401unauthorizedCredencial o cuenta ausente, inválida o inactiva.
403insufficient_scope, admin_disabledClave válida sin el permiso requerido (véase X-Required-Scope), o un recurso bloqueado por un administrador.
404not_foundEndpoint desconocido, o un recurso fuera de esta cuenta de comerciante.
405method_not_allowedUtilice el método indicado en la cabecera Allow.
409idempotency_conflictClave reutilizada con un JSON diferente.
413request_too_largeEl cuerpo JSON supera los 64 KiB.
415unsupported_media_typeEl cuerpo del POST no se declara como application/json.
422invalid, limit, invalid_amount, below_minimum, bad_address, 2fa_required, unsupported_assetSolicitud bien formada que no superó la validación determinista o alcanzó un límite de recursos.
429rate_limitedEspere Retry-After.
500server_errorFallo inesperado; reintente de forma segura con la misma clave de idempotencia.
503maintenance, temporarily_unavailable, asset_unavailable, no_rate, price_stale, fiat_rate_unavailable, fiat_rate_stale, derive_failedFallo transitorio de la plataforma, del nodo, del precio o de la asignación de dirección. No se sustituye por una conversión obsoleta.

Límites actuales

ÁmbitoLímiteVentana
Techo de seguridad de Nginx por IP10 solicitudes/segundo, ráfaga de 30Continuo
Techo para IP no autenticada300 solicitudes60 segundos
POST /v1/payments, links, shops, products120 solicitudes por clave de API60 segundos
POST /v1/payouts30 solicitudes por clave de API60 segundos
Endpoints GET240 solicitudes por clave de API60 segundos

Límites de la cuenta

RecursoLímite
Tiendas por cuenta10
Enlaces de pago por cuenta50
Productos por tienda50
Combinaciones de variantes por producto30
Claves de licencia por producto o enlace10,000
Preguntas de checkout por enlace5
Claves de API activas por cuenta50

Consulte su uso en vivo frente a estos límites desde GET /v1/account.

Las respuestas correctas limitadas a nivel de aplicación exponen X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset. Reintente 429, 500 y 503 con retroceso exponencial y jitter. En las solicitudes POST, reutilice siempre el Idempotency-Key original y un JSON idéntico.

Seguridad en producción

Seguridad de la integración

Guarde los secretos de la API en un gestor de secretos

Cárguelos en tiempo de ejecución; nunca registre el valor completo en logs ni lo incluya en el control de versiones.

Llame a la API desde su backend

Un cliente de navegador o móvil no puede almacenar de forma segura un secreto de comerciante.

Verifique el cuerpo en bruto del webhook

Compruebe la vigencia de la marca de tiempo y utilice una comparación de firma en tiempo constante antes de analizar el JSON.

Haga que la entrega del pedido sea idempotente

Registre los eventos o pedidos procesados de forma transaccional para que los reintentos nunca generen un envío duplicado.

Confíe en el estado final de la API, no en las redirecciones

Recupere el pago cuando un evento sea inesperado o su estado local no coincida.

Rote las claves con solapamiento

Cree una clave de sustitución, despliéguela, verifique el tráfico y, después, elimine la clave anterior.

!

El acceso a la cuenta se controla mediante una clave de comerciante de 16 dígitos no recuperable, protegida opcionalmente con TOTP. Guarde tanto el acceso de comerciante como los secretos de la API con el mismo cuidado que las credenciales de una cartera.

Lanzamiento

Lista de verificación de lanzamiento

1
Cree una clave de API dedicada para producción

No reutilice la copia personal de un desarrollador entre distintos servicios.

2
Consulte ambos catálogos en vivo

Utilice GET /v1/assets y GET /v1/currencies; muestre únicamente las entradas presentes y available: true.

3
Añada y pruebe su endpoint de webhook

Guarde el secreto de firma una sola vez; verifique la marca de tiempo y la firma y, después, elimine duplicados usando el ID estable del evento.

4
Utilice una clave de idempotencia para cada pedido

Ponga a prueba un reintento duplicado y confirme que solo existe un ID de pago.

5
Pruebe las caídas de tipo de cambio, los pagos insuficientes y la caducidad

El estado de su pedido debe seguir siendo seguro ante tipos fiat obsoletos, activos no disponibles, confirmaciones retrasadas y cualquier otro escenario adverso.

6
Concilie a diario

Compare sus pedidos con los estados de pago de la API, los registros de webhooks y el libro contable del comerciante.

¿Listo para integrar?

Cree una cuenta en segundos, genere una clave y mantenga esta referencia junto a su código.

Crear cuenta