Saltar al contenido principal

Polling asíncrono y webhooks

DGII confirma los e-CFs asíncronamente vía un trackId. ERPly Pro abstrae este patrón por ti.

Polling

curl https://sandbox.api.erply.pro/v1/invoices/{docId}/status \
-H "Authorization: Bearer $ERPLYPRO_API_KEY"
{
"docId": "01HW9X4G…",
"trackId": "20260501-DGII-9988",
"status": "accepted",
"dgii": { "approvedAt": "2026-05-01T17:42:11Z" }
}

Webhook

ERPly Pro envía un POST al webhook configurado del tenant:

POST /tu-webhook HTTP/1.1
Content-Type: application/json
X-ErplyPro-Event: invoice.accepted
X-ErplyPro-Signature: t=1714583811,v1=4f9d…
X-ErplyPro-Delivery: 01HW9X4G…

Verifica la firma (constant-time) usando el secreto compartido:

import hmac, hashlib, time

def verify(body: bytes, header: str, secret: bytes, *, max_skew=300) -> bool:
parts = dict(p.split("=") for p in header.split(","))
t = int(parts["t"])
if abs(time.time() - t) > max_skew:
return False
expected = hmac.new(secret, f"{t}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])

Reintentos

ERPly Pro reintenta el webhook con back-off exponencial (1s/4s/16s/64s/256s) hasta 5 intentos. Si todos fallan, el evento queda en una DLQ y el operador recibe un PagerDuty.