Crea cobros en cripto directamente desde tu sistema y libera el acceso del cliente automáticamente cuando se confirme el pago.
El flujo típico de una integración (suscripción, hosting, streaming):
1. Tu sistema crea un cobro vía API → POST https://api.stackfy.io/v1/invoices
2. Llevas al cliente al pago → enlace de checkout O QR transparente
3. El cliente paga en cripto
4. Stackfy llama a tu webhook → POST a tu notification_url
5. Confirmas el cobro vía API → GET https://api.stackfy.io/v1/invoices/{id}
6. Status "complete" → liberas/renuevas el acceso del cliente
Recurrencia: cripto no tiene débito automático — en cada ciclo, tu sistema repite el paso 1.
| Dirección de la API | https://api.stackfy.io/v1 |
| Tu store_id | SEU_STORE_ID |
| Moneda predeterminada | BRL |
Crea una clave en API e integración y envíala en la cabecera de cada llamada:
Authorization: Bearer SUA_CHAVE
La clave da acceso a tu cuenta — guárdala como una contraseña. Si se filtra, revócala al instante desde el panel.
POSThttps://api.stackfy.io/v1/invoices
| Campo | Obligatorio | Descripción |
|---|---|---|
price | sí | Importe (string), ej.: "49.90" |
currency | sí | Moneda del importe: BRL, USD, EUR… (o USDT para precio directo en dólar 1:1, solo con pay_currency=USDT) |
store_id | sí | Tu tienda: SEU_STORE_ID |
pay_currency | no | Omitido = multi-moneda (el comprador elige la cripto — ver abajo). Para FIJAR la red: BTC, USDT (Tron/TRC-20) o USDT-MATIC (Polygon). Fijar USDT requiere que la tienda tenga dirección en esa red. El price se mantiene en fiat. |
notification_url | no | Tu webhook (recibe el aviso de pago) |
redirect_url | no | A dónde enviar al cliente tras pagar |
metadata | no | Objeto libre (ej.: tu id de pedido/usuario) |
Solo omite el campo pay_currency: Stackfy crea un pedido y el comprador elige entre BTC, USDT-Tron y USDT-Polygon en la pantalla de pago (las opciones dependen de lo que la tienda tenga habilitado). El price se mantiene en fiat; la conversión se hace al tipo de cambio del momento, cuando el comprador elige. La respuesta trae pay_currency: "ANY" y el checkout_url del selector.
curl -X POST https://api.stackfy.io/v1/invoices \
-H "Authorization: Bearer SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{
"price": "49.90",
"currency": "BRL",
"store_id": "SEU_STORE_ID"
}'
# sin pay_currency = el comprador elige la cripto en el checkout
curl -X POST https://api.stackfy.io/v1/invoices \
-H "Authorization: Bearer SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{
"price": "49.90",
"currency": "BRL",
"store_id": "SEU_STORE_ID",
"notification_url": "https://seusite.com/webhooks/stackfy",
"metadata": {"pedido": "1234", "usuario": "[email protected]"}
}'
const r = await fetch("https://api.stackfy.io/v1/invoices", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.STACKFY_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
price: "49.90", currency: "BRL", store_id: "SEU_STORE_ID",
notification_url: "https://seusite.com/webhooks/stackfy",
metadata: { pedido: "1234" },
}),
});
const invoice = await r.json();
// invoice.id -> guárdalo en tu pedido
// redirige al cliente al checkout (ver abajo)
$ch = curl_init("https://api.stackfy.io/v1/invoices");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("STACKFY_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"price" => "49.90", "currency" => "BRL", "store_id" => "SEU_STORE_ID",
"notification_url" => "https://seusite.com/webhooks/stackfy",
]),
]);
$invoice = json_decode(curl_exec($ch), true);
La respuesta es el cobro creado, con id, status ("pending") y los métodos de pago en payments (dirección, importe en cripto y URI para QR).
Envía al cliente al checkout listo de Stackfy, usando el id del cobro:
https://pay.stackfy.io/c/<invoice_id>
El cliente ve el QR, paga y (si definiste redirect_url) vuelve a tu sitio.
Usa los datos de payments de la respuesta para montar tu propio QR/dirección:
{
"id": "...",
"status": "pending",
"payments": [{
"payment_address": "bc1q...", // dirección de cobro
"amount": "0.00071", // importe en cripto
"currency": "BTC",
"payment_url": "bitcoin:bc1q...?amount=0.00071" // se vuelve QR
}]
}
Cuando se paga el cobro, Stackfy hace un POST firmado a tu servidor. Verificas la firma con tu secreto y listo — no necesitas volver a consultar nada.
En API e integración, guarda la URL de tu servidor (recibe el aviso) y copia tu secreto de firma (whsec_…). No necesitas configurar notification_url: todo cobro creado por Stackfy (API https://api.stackfy.io/v1 o panel) ya apunta por sí solo a nuestro relay.
Stackfy recibe la confirmación, verifica el estado real del cobro internamente y solo entonces lo reenvía, ya firmado, a tu servidor.
Cabecera X-Stackfy-Signature: t=<timestamp>,v1=<hmac_sha256> y cuerpo JSON:
{
"id": "<invoice_id>",
"status": "complete",
"price": "49.90",
"currency": "BRL",
"paid_currency": "BTC",
"metadata": { "pedido": "1234" },
"store_id": "SEU_STORE_ID"
}
La firma es HMAC-SHA256 del texto "<timestamp>.<corpo_cru>" usando tu secreto. Compara en tiempo constante. El mismo esquema que Stripe.
const crypto = require("crypto");
// usa el cuerpo CRUDO (raw), no el JSON ya parseado:
app.post("/webhooks/stackfy", express.raw({type:"*/*"}), (req, res) => {
const raw = req.body.toString("utf8");
const [t, v1] = req.headers["x-stackfy-signature"].split(",")
.map(p => p.split("=")[1]);
const expected = crypto.createHmac("sha256", process.env.STACKFY_WHSEC)
.update(t + "." + raw).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
if (!ok) return res.status(401).end(); // falsificado -> rechaza
const ev = JSON.parse(raw);
if (ev.status === "complete") liberar(ev.metadata.pedido);
res.status(200).end(); // responde 200 rápido
});
$raw = file_get_contents("php://input");
parse_str(str_replace(",", "&", $_SERVER["HTTP_X_STACKFY_SIGNATURE"]), $sig);
$expected = hash_hmac("sha256", $sig["t"] . "." . $raw, getenv("STACKFY_WHSEC"));
if (!hash_equals($expected, $sig["v1"])) { http_response_code(401); exit; }
$ev = json_decode($raw, true);
if ($ev["status"] === "complete") liberar_acesso($ev["metadata"]["pedido"]);
http_response_code(200);
complete (o confirmed).Si prefieres no exponer un endpoint, consulta el estado cuando quieras: GEThttps://api.stackfy.io/v1/invoices/<id> con tu clave. La verdad siempre está en la API.
| status | Significado | ¿Liberar acceso? |
|---|---|---|
pending | Esperando pago | No |
paid | Visto en la red, 0 confirmaciones | Todavía no (puede revertirse) |
confirmed | Confirmado en la red (≥1 conf) | Sí |
complete | Pagado y liquidado | Sí |
expired | Tiempo agotado sin pagar | No |
invalid | Pago inválido | No |
¿Dudas de integración? [email protected]