Crear Oferta P2P
Crear una nueva oferta de compra o venta P2P.
POST /p2p/create
Crea una nueva oferta P2P de compra o venta. Para ofertas de venta (sell), el monto se deduce automáticamente del saldo del usuario. El usuario debe tener KYC verificado.
Autenticación
Bearer Token (Authorization: Bearer <token>) o Credenciales de App (app-id + app-secret en headers).
Cuando se usa Credenciales de App, la oferta se crea en nombre del usuario propietario de la app. Dicho usuario debe cumplir todos los requisitos de P2P (p2p_enabled, KYC verificado, Telegram vinculado y teléfono verificado), y para ofertas de tipo sell el saldo se descuenta de su cuenta.
Request
Con Bearer Token:
curl -X POST "https://api.qvapay.com/p2p/create" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"type": "buy",
"coin": "BANK_CUP",
"amount": 50,
"receive": 12500,
"details": [{ "name": "cuenta", "value": "1234567890" }],
"only_vip": 0,
"private": 0,
"message": "Pago rápido",
"webhook": "https://example.com/webhook"
}'Con Credenciales de App:
curl -X POST "https://api.qvapay.com/p2p/create" \
-H "app-id: {tu-app-uuid}" \
-H "app-secret: {tu-app-secret}" \
-H "Content-Type: application/json" \
-d '{
"type": "buy",
"coin": "BANK_CUP",
"amount": 50,
"receive": 12500,
"details": [{ "name": "cuenta", "value": "1234567890" }],
"only_vip": 0,
"private": 0,
"message": "Pago rápido",
"webhook": "https://example.com/webhook"
}'Parámetros (body JSON)
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
type | string | Sí | Tipo de oferta: buy o sell |
coin | string | number | Sí | Tick de la moneda (ej: BANK_CUP) o ID numérico |
amount | number | Sí | Cantidad en QUSD (0.1 - 100,000) |
receive | number | Sí | Cantidad a recibir en la moneda seleccionada (0.1 - 1,000,000) |
details | array | Sí | Datos de pago según los campos de la moneda (ej: cuenta bancaria) |
only_kyc | number | No | 1 para restringir a usuarios con KYC verificado |
only_vip | number | No | 1 para restringir a usuarios VIP |
private | number | No | 1 para crear oferta privada (no se publica en Telegram) |
message | string | No | Mensaje público de la oferta (máx. 79 caracteres, URLs eliminadas) |
webhook | string | No | URL de webhook para notificaciones de estado |
tags | array | No | Etiquetas para la oferta (máx. 10 tags) |
idempotency_key | string | No | Clave de idempotencia (8-64 caracteres, [A-Za-z0-9._-]) para reintentos seguros en conexiones inestables. Repetir la misma clave en 24h devuelve la oferta original con 200 y duplicate: true en vez de crear un duplicado |
Response (201)
{
"msg": "Oferta P2P creada correctamente",
"p2p": {
"uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"type": "buy",
"coin": "BANK_CUP",
"amount": 50.00,
"receive": 12500.00,
"only_kyc": 0,
"private": 0,
"only_vip": 0,
"status": "open",
"details": { "cuenta": "1234567890" },
"message": "Pago rápido",
"webhook": "https://example.com/webhook",
"created_at": "2024-06-20T14:30:00.000Z",
"updated_at": "2024-06-20T14:30:00.000Z"
}
}Webhook
Si se proporciona un webhook, se enviará un POST con el siguiente payload cuando la oferta sea creada:
{
"operation": "created",
"p2p": { ... }
}Idempotencia
Si se envía idempotency_key y una oferta ya fue creada con esa misma clave, la respuesta es 200 con la oferta original y el campo adicional "duplicate": true (no se crea una segunda oferta ni se debita saldo de nuevo). Si la creación original aún está en proceso, se responde 409 con "code": "DUPLICATE_REQUEST" — reintenta unos segundos después.
Errores
| Código | Descripción |
|---|---|
400 | Datos inválidos, moneda no encontrada, KYC requerido, saldo insuficiente, o límite de ofertas pendientes alcanzado |
401 | Token de autenticación inválido o ausente |
409 | DUPLICATE_REQUEST: ya hay una creación en proceso con la misma idempotency_key |
429 | Demasiadas solicitudes (límite: 1 cada 5 segundos, 100 diarias) |
500 | Error interno al crear la transacción |