Referencia de rutas y errores
Base de la API: https://api.zarelafact.com/partner/v1. Todas las rutas requieren X-PARTNER-KEY, salvo la carga binaria del certificado. Los esquemas exactos están en el OpenAPI público.
Rutas
Cuentas fiscales
| Ruta | Uso |
|---|---|
PUT /fiscal-accounts/by-external-id/{externalTenantId} | Crea o recupera la cuenta de un tenant (201 / 200). Un RNC nuevo debe estar ACTIVO en el padrón de la DGII. |
GET /fiscal-accounts?limit=50&offset=0 | Lista tus cuentas, paginadas. |
GET /fiscal-accounts/{id} | Una cuenta con su certificación actual. |
GET /fiscal-accounts/{id}/status | Estado consolidado de CerteCF y eCF. |
PATCH /fiscal-accounts/{id}/profile | Actualiza datos del perfil. El RNC no se cambia aquí. Con printedRepresentationEmail (production y/o testecf, true o false) activa o desactiva la factura por correo al comprador. |
Certificado
| Ruta | Uso |
|---|---|
POST /fiscal-accounts/{id}/certificate-upload-sessions | Sesión de carga ligada al browserOrigin de tu UI. |
POST /fiscal-accounts/{id}/certification-sessions | Enlace temporal a la pantalla de pasos de la certificación, para un iframe desde browserOrigin (Incrustar los pasos). |
POST /fiscal-accounts/{id}/certificate-rotation-requests | Sesión para reemplazar el certificado. |
PUT /certificate-upload-sessions/{uploadId} | Carga multipart con Authorization: Upload <uploadToken>. Una contraseña o un archivo equivocado no gasta la sesión: admite cinco intentos y la respuesta trae details.attemptsRemaining. |
GET /fiscal-accounts/{id}/certificate | Metadata del certificado, nunca la clave privada. |
Certificación
| Ruta | Uso |
|---|---|
GET /fiscal-accounts/{id}/dgii-registration | Datos que el tenant declara en su postulación DGII. |
POST /fiscal-accounts/{id}/certification-xml-signatures | Firma la postulación o la declaración jurada. |
POST /fiscal-accounts/{id}/certification-test-sets | Sube el set de pruebas que la DGII entregó al cliente (el Excel tal cual o JSON); devuelve testSetRef. |
GET /fiscal-accounts/{id}/certification-test-sets | Sets subidos para la cuenta. |
GET /certification/official-sets | Sets del catálogo de ZarelaFact y defaultRef (null si no hay). No incluye el set modelo de la simulación. |
POST /fiscal-accounts/{id}/certification-cases | Crea el caso con el testSetRef del Excel de la DGII que subiste. |
GET /fiscal-accounts/{id}/certification-cases/{caseId} | Checklist, estado y siguiente acción. |
POST .../certification-cases/{caseId}/attestations | Registra una acción humana. |
POST .../certification-cases/{caseId}/runs | Ejecuta el set en CerteCF (requiere Idempotency-Key). |
GET .../certification-cases/{caseId}/runs | Runs recientes. |
GET .../runs/{runId} | Resultado de un run. |
GET .../runs/{runId}/evidence | ZIP de evidencia en base64. |
GET .../certification-cases/{caseId}/runs/{runId}/printed-pdfs | ZIP con el PDF impreso de cada comprobante del run, para subirlos a la DGII. |
GET .../certification-cases/{caseId}/runs/{runId}/consumer-invoices | XML íntegro (e-CF) de cada Factura de Consumo menor a RD$250,000 aceptada, lo que se sube en Facturas de consumo < 250Mil (ZIP, o un XML suelto con ?encf=), como RNC + e-NCF. |
GET .../certification-cases/{caseId}/runs/{runId}/consumer-summaries | Copia del resumen RFCE firmado que ZarelaFact envió por cada una (ZIP, o un XML suelto con ?encf=). No se sube en el portal. |
POST .../certification-cases/{caseId}/official-set | Cambia el set de pruebas del caso (officialSetRef) sin cerrarlo; reinicia las pruebas de datos con el set nuevo. |
POST .../certification-cases/{caseId}/restart | Reinicia las pruebas de datos o la simulación (part) sin cerrar el caso; conserva el certificado y las atestaciones. |
POST .../certification-cases/{caseId}/commercial-approvals | Envía a la DGII las aprobaciones comerciales de prueba (paso 3) del Excel que el contribuyente descargó en CerteCF (workbookBase64). Requiere Idempotency-Key. |
GET .../certification-cases/{caseId}/commercial-approvals | Avance del último envío de las aprobaciones comerciales. |
POST .../certification-cases/{caseId}/documents/{documentId}/resend | Reenvía a la DGII un comprobante de las pruebas trabado por un problema de envío. |
POST .../certification-cases/{caseId}/close | Cierra el caso para cambiar de set (no con un envío en curso, esperando a la DGII ni aprobado). |
Producción y emisión
| Ruta | Uso |
|---|---|
POST /fiscal-accounts/{id}/production-activation-requests | Reintenta la activación (normalmente es automática al aprobarse el caso). |
GET /fiscal-accounts/{id}/production | Estado real de la autorización eCF. |
POST /fiscal-accounts/{id}/production/documents?validate=true | Prevalidación sin efectos fiscales. |
POST /fiscal-accounts/{id}/production/documents | Valida como ?validate=true (422 sin registrar nada si falla), convierte, firma y encola el e-CF. Con Prefer: wait=N (1-15 s) responde 201 con los datos para imprimir si la DGII responde a tiempo. |
POST /fiscal-accounts/{id}/production/documents/status/batch | Estado de varios documentos. |
GET /fiscal-accounts/{id}/production/documents/{documentId} | Estado de un documento. |
GET /fiscal-accounts/{id}/production/documents/{documentId}/xml | XML firmado (archivo, no JSON). |
GET /fiscal-accounts/{id}/production/documents/{documentId}/pdf | Representación impresa en PDF tamaño carta. |
POST /fiscal-accounts/{id}/production/annulments/prevalidate | Prevalida una anulación (ANECF). |
Sandbox (TesteCF)
Las mismas operaciones que producción, en el ambiente de pruebas de la DGII. No exigen producción activa ni plan, y lo que se emite aquí no cuenta en tu plan.
| Ruta | Uso |
|---|---|
POST /fiscal-accounts/{id}/testecf/documents?validate=true | Prevalidación sin efectos fiscales. |
POST /fiscal-accounts/{id}/testecf/documents | Valida, firma con el certificado del cliente y envía el e-CF de prueba a TesteCF. Mismo contrato y Prefer: wait=N que producción. |
POST /fiscal-accounts/{id}/testecf/documents/status/batch | Estado de varios documentos de prueba. |
GET /fiscal-accounts/{id}/testecf/documents/{documentId} | Estado de un documento de prueba (environment: "testecf"). |
GET /fiscal-accounts/{id}/testecf/documents/{documentId}/xml | XML firmado. |
GET /fiscal-accounts/{id}/testecf/documents/{documentId}/pdf | Representación impresa en PDF. |
POST /fiscal-accounts/{id}/production/annulments | Anula eNCF no usados (requiere Idempotency-Key). |
GET /fiscal-accounts/{id}/production/annulments | Anulaciones del cliente. |
GET /fiscal-accounts/{id}/production/annulments/{annulmentId} | Estado de una anulación. |
GET / POST /fiscal-accounts/{id}/production/sequences | Lista o registra rangos autorizados (opcional; anular no los exige). |
GET /fiscal-accounts/{id}/production/inbound-documents | e-CF que los proveedores enviaron al cliente, del más reciente al más antiguo. Pagina por cursor (limit hasta 100 y cursor con el nextCursor anterior) y filtra por group, documentType, encf, issuerRnc, from y to, como la lista de la cuenta directa. Cada elemento trae group, view, dgiiValidity (validez en la DGII según Consulta Estado; ver Validez en la DGII) y, si falta responder, commercialApprovalDeadline. |
POST /fiscal-accounts/{id}/production/inbound-documents/{inboundDocumentId}/commercial-approval | Acepta o rechaza comercialmente un e-CF recibido (ACECF). Aprobar un e-CF que la DGII reporta rechazado o no encontrado responde 409 RECEIVED_ECF_NOT_VALID_IN_DGII. |
GET /billing/usage[?month=YYYY-MM] | e-CF aceptados por DGII entre todas tus cuentas: en el periodo de cobro actual de tu plan o, con month, en ese mes calendario de RD. |
Webhooks
| Ruta | Uso |
|---|---|
GET / POST /webhook-endpoints | Lista o crea endpoints. |
PATCH /webhook-endpoints/{endpointId} | Cambia status, name, url o eventTypes. |
DELETE /webhook-endpoints/{endpointId} | Retira el endpoint y conserva el historial. |
POST /webhook-endpoints/{endpointId}/test | Encola una entrega webhook.test. |
POST /webhook-endpoints/{endpointId}/rotate-secret | Secreto nuevo con ventana de doble firma. |
GET /webhook-deliveries | Entregas por cursor, filtrables. |
GET /webhook-deliveries/{deliveryId} | Estado e intentos de una entrega. |
POST /webhook-deliveries/{deliveryId}/replay | Reencola una entrega fallida. |
Detalle en Webhooks Partner.
Permisos
Cada clave tiene un perfil de permisos. Por defecto es full, con todos los permisos; los perfiles limitados sirven si quieres una clave por proceso de tu backend.
| Permiso | Rutas | Perfiles |
|---|---|---|
fiscal-accounts:manage | Alta, listado, consulta y perfil de cuentas | onboarding |
certificates:manage | Sesiones de carga, rotación y metadata del certificado | onboarding |
certification:read | Estado, datos de postulación, sets, casos, runs y evidencia | onboarding |
certification:execute | Subir sets de pruebas, crear y cerrar casos y ejecutar runs | onboarding |
certification:attest | Atestaciones y firma de XML de certificación | onboarding |
production:request | Solicitar la activación | onboarding |
production:read | Estado de producción y consumo mensual | onboarding, runtime |
documents:validate | Prevalidación de documentos y anulaciones | onboarding, runtime |
documents:create | Emisión, anulación, registro de rangos y aprobación comercial | runtime |
documents:read | Estado, XML y PDF de documentos; anulaciones, rangos y recibidos | runtime |
webhooks:manage | Endpoints y entregas de webhooks | webhooks |
El perfil full reúne todos los permisos y lo pueden crear el owner y los developers.
Reglas de payload
- Contratos cerrados. Las rutas de cuentas, certificado, certificación, activación y webhooks rechazan propiedades desconocidas (como
autoApprove) con400 INVALID_PARTNER_PAYLOADen vez de ignorarlas. Enproduction/documentssolo se leedocument. - Tipos estrictos. Textos como cadenas,
ecfTypesyevidenceRefscomo listas de cadenas,b2bSimulationbooleano yoccurredAten ISO 8601. Omite los opcionales que no tengas; no envíesnull. - Identificadores.
fiscalAccountId,caseIdy demás son UUID opacos.by-external-idsolo existe para elPUTde alta. - Perfil fiscal. Con el contrato simplificado,
fiscalEmail,phone,address,provinceCodeymunicipalityCodecompletan los datos del emisor que falten. Con el JSON DGII/XSD envía el emisor completo: ZarelaFact valida queRNCEmisorsea el de la Cuenta fiscal. UnPATCHde perfil necesita al menos un campo.
| Campo | Máximo |
|---|---|
Idempotency-Key, correlationId, actorRef | 200 caracteres |
notes | 4000 caracteres |
evidenceRefs | 50 referencias de 500 caracteres |
| Nombre del webhook / URL del webhook | 200 / 2048 caracteres |
Errores
Todos los errores tienen la forma {"ok": false, "error": {"code", "message", "details"}, "correlationId"}. Guarda el correlationId para soporte.
| Código | Qué pasó | Qué hacer |
|---|---|---|
400 INVALID_PARTNER_PAYLOAD | Payload, tipo o identificador inválido. | Corrige y reintenta con la misma intención. |
401 / 403 | Clave ausente, inválida o sin el permiso. | No reintentes automáticamente. |
403 PARTNER_INACTIVE | El Partner fue suspendido durante una carga. | Contacta a ZarelaFact. |
404 FISCAL_ACCOUNT_NOT_FOUND | La cuenta no existe para ti (o su reserva se liberó). | Provisiona o corrige el ID. |
409 RNC_NOT_AVAILABLE | El RNC está con otra plataforma o es cliente directo. | Ver titularidad. |
409 ACCOUNT_LINK_CONFLICT | El externalTenantId ya usa otro RNC, o el RNC está en otro tenant tuyo. | Revisa el vínculo en tu ERP. |
409 RNC_CHANGE_REQUIRES_RECERTIFICATION | Intentaste cambiar el RNC en el perfil. | Crea otra cuenta. |
409 CERTIFICATION_*_NOT_READY | Falta un paso previo. | Muestra la acción pendiente y espera el webhook. |
409 CERTIFICATION_PREREQUISITES_MISSING | El caso no tiene el certificado validado. | Pide al usuario que cargue su certificado. |
409 CERTIFICATION_SET_ALREADY_USED | Los eNCF del set subido ya se emitieron. | No reintentes: reinicia las pruebas de datos o pide a la DGII un set nuevo. |
409 / 422 CERTIFICATION_OWN_SET_REQUIRED | Pediste las pruebas de datos con el set modelo (dgii-model). | Sube el Excel de la DGII del contribuyente y usa su testSetRef. |
409 CERTIFICATION_NOT_APPROVED | Activación pedida antes de la aprobación. | Espera a que el caso esté approved. |
409 PRODUCTION_STATE_CONFLICT | La cuenta ya está activa o deshabilitada. | Consulta GET .../production. |
409 IDEMPOTENCY_CONFLICT | Misma Idempotency-Key con otros parámetros. | Usa otra clave para un intento nuevo. |
422 CERTIFICATE_PASSWORD_INVALID / CERTIFICATE_FILE_INVALID / CERTIFICATE_PRIVATE_KEY_MISSING / CERTIFICATE_KEY_PAIR_NOT_FOUND | El certificado no se pudo cargar: la contraseña no abre el .p12, el archivo está dañado o usa un cifrado que no se puede leer, no trae la clave privada o no trae el certificado de esa clave. | Muestra message al usuario y deja que corrija; la sesión admite otro intento (details.attemptsRemaining). |
422 CERTIFICATE_HOLDER_ID_MISSING / CERTIFICATE_KEY_USAGE_INVALID / CERTIFICATE_EXPIRED / CERTIFICATE_NOT_YET_VALID | El certificado no sirve para firmar e-CF: su SN (serialNumber) no trae el RNC, la cédula o el pasaporte del titular, su uso de clave no incluye firma digital ni no repudio, o no está vigente. | Muestra message: el cliente debe pedir a su entidad de certificación un certificado para procesos tributarios. La sesión admite otro intento. |
422 CERTIFICATION_SET_ISSUER_MISMATCH | El set es de otro RNC. | Usa el set de ese contribuyente. |
422 RNC_NOT_IN_DGII_REGISTRY | Al vincular un RNC nuevo, no aparece en el padrón de contribuyentes de la DGII. | Verifica el número; si el cliente se inscribió hace poco, espera la próxima actualización del padrón. |
422 RNC_NOT_ACTIVE_IN_DGII | Al vincular un RNC nuevo, figura con otro estado en la DGII (details.status). | Solo un contribuyente ACTIVO puede emitir e-CF: el cliente debe regularizarse en la DGII. |
422 ACECF_DGII_REJECTED | La DGII rechazó la aprobación comercial (details.dgiiSubmission.dgiiMessages). | Corrige y envía la decisión otra vez. |
503 ACECF_DGII_CERTIFICATE_UNAVAILABLE / DIRECTORY_DGII_AUTH_FAILED / DIRECTORY_ACCESS_TOKEN_MISSING | La aprobación comercial no pudo autenticarse ante la DGII o consultar su directorio. | Reintenta más tarde; revisa el certificado del cliente si persiste. |
400 INVALID_BROWSER_ORIGIN / 422 BROWSER_ORIGIN_NOT_ALLOWED | El origen del iframe no es HTTPS exacto o no está entre tus orígenes de integración. | Usa el origen exacto de tu UI. |
410 CERTIFICATION_EMBED_EXPIRED | El enlace de la certificación incrustada venció. | Pide uno nuevo con POST .../certification-sessions. |
422 en emisión | Documento inválido o RNC emisor distinto. | Corrige el documento. |
423 PRODUCTION_NOT_ACTIVE | eCF aún no está activo. | Espera production.state_changed. |
402 PAYMENT_REQUIRED | Emisión en eCF sin plan Partner pagado o con el pago vencido tras la gracia. | No reintentes; el propietario del Partner paga en details.billingUrl. |
429 PLAN_LIMIT_EXCEEDED | Cupo mensual del plan agotado, sumando todos tus clientes. | No reintentes con otro cliente; cambia a un plan mayor desde el portal. |
429 RATE_LIMIT_EXCEEDED | Límite de tasa. | Respeta Retry-After y aplica backoff con jitter. |
Límites de tasa
Ventanas fijas de 60 segundos, iguales para todos los planes:
| Ámbito | Solicitudes por ventana |
|---|---|
| Por IP | 1000 |
| Por Partner (todas sus claves suman) | 1000 |
| Por Cuenta fiscal | 300 |
| Por permiso de operación | 600 |
Cambiar de clave no reinicia los contadores. Coordina las colas de tus tenants para no disparar reintentos simultáneos y conserva la identidad del documento o intento al reintentar.