Previous
ECF API Launch DGII Engineering

Launching ECF SSD API: DGII electronic invoicing as infrastructure, not as a task

Dawlin Peña
Dawlin Peña
May 20, 2026 8 min read

Why we built another e-CF API

There are dozens of electronic invoicing solutions for the Dominican Republic. Before we started, we asked ourselves honestly: does the world need one more?

The answer came from the clients. Companies we work with arrived saying things like:

  • “My vendor charges per document, and my volume makes it unviable.”
  • “The API we use doesn’t let us sign locally; they receive an unsigned XML on their server.”
  • “I have no visibility into what happened when a document fails.”
  • “Every time DGII changes something, I wait two weeks for my vendor to update.”

What was missing wasn’t another API. It was an API designed for integrators, not end users.

Today we’re publicly launching ECF SSD API — the same one already running in production for several clients in banking, retail, and manufacturing.

Design principles

1. You sign, not us

XAdES-BES signing happens where your certificate lives, not on our servers. We offer:

  • An SDK that signs locally with your P12 certificate.
  • An endpoint that accepts already-signed XML and only handles submission to DGII.

Why it matters: your private key should never leave your infrastructure. If an e-CF vendor asks you to upload your P12, switch vendors.

2. Real idempotency

Every operation accepts an Idempotency-Key. Retry three times if you want: you’ll only generate one e-CF.

POST /v1/comprobantes
Authorization: Bearer ssd_live_...
Idempotency-Key: 8f3d2c9a-7b1e-4a5f-9d2c-1e8b3f7a9c4d
Content-Type: application/xml

<ECF xmlns="...">...</ECF>

Implemented correctly: if the first call fails halfway through (after submission to DGII but before returning a response to you), your retry recovers the actual state — it doesn’t duplicate the submission.

3. End-to-end observability

Every e-CF has a tracking_id that follows the transaction through:

  • Your submission to SSD.
  • Our submission to DGII.
  • The acknowledgement (ACECF) response.
  • Your confirmation webhook.
GET /v1/comprobantes/E310000000123/timeline

{
  "tracking_id": "trk_01HXY...",
  "events": [
    { "at": "2026-05-25T10:14:02Z", "type": "received", "duration_ms": 12 },
    { "at": "2026-05-25T10:14:02Z", "type": "signed_locally" },
    { "at": "2026-05-25T10:14:03Z", "type": "submitted_to_dgii", "duration_ms": 847 },
    { "at": "2026-05-25T10:14:04Z", "type": "acecf_received", "result": "ACEPTADO" },
    { "at": "2026-05-25T10:14:04Z", "type": "webhook_delivered", "endpoint": "https://..." }
  ]
}

4. Webhooks with exponential retries

When a DGII acknowledgement arrives, we notify you. If your endpoint is down, we retry for 24 hours with exponential backoff. Every webhook is signed with HMAC-SHA256 so you can verify authenticity.

import { verifyWebhook } from '@ssd/ecf-sdk'

export async function POST(req: Request) {
  const signature = req.headers.get('x-ssd-signature')
  const body = await req.text()

  if (!verifyWebhook(body, signature, process.env.SSD_WEBHOOK_SECRET)) {
    return new Response('Invalid signature', { status: 401 })
  }

  const event = JSON.parse(body)
  // event.type === 'acecf.received'
  // event.data.tracking_id === 'trk_01HXY...'
}

5. Sandbox with real parity

Our sandbox environment points to DGII’s TesteCF, not an internal mock. When you issue a test e-CF, it goes through the same cycle as production — just against the official testing environment. If it works in sandbox, it’ll work in production.

Architecture under the hood

┌─────────────────┐    XML+P12     ┌──────────────────┐
│ Your app        │ ──────────────▶ │ SSD SDK          │
│ (ERP, POS, etc.)│                │ (local signing)  │
└─────────────────┘                └────────┬─────────┘
                                            │ signed XML

                                  ┌──────────────────┐
                                  │ SSD Edge Worker  │
                                  │ (Cloudflare)     │
                                  └────────┬─────────┘
                                           │ HTTPS

                                  ┌──────────────────┐
                                  │ DGII Endpoint    │
                                  │ (Production or   │
                                  │  TesteCF)        │
                                  └──────────────────┘
  • Edge runtime (Cloudflare Workers): the API lives in 300+ cities. Your call goes to the nearest node, not to a central server. Average latency to DGII: <45ms.
  • D1 + R2: we store tracking and signed XML (the originals, not the keys). Retention configurable to match your compliance requirements.
  • Zero in-RAM state: each request is independent. If a region goes down, the next one picks up traffic with no loss.

What it covers today

Document typeSupported
31 — Tax Credit Invoice
32 — Consumer Invoice
33 — Debit Note
34 — Credit Note
41 — Purchases
43 — Minor Expenses
44 — Special Regimes
45 — Government
46 — Exports
47 — Payments Abroad
RFCE — Summary of Issued Documents
ARECF — Commercial Approval

Pricing: pay per use, no surprises

We charge per document successfully submitted to DGII. Not per attempt. Not per status query. Not per test document. Full pricing details on the product page.

What’s next

  • Official SDKs: TypeScript/Node is live. C#/.NET, Python and PHP land next quarter.
  • Odoo integration: native module, no middleware.
  • 606 / 607 reports: accounting annexes generated from your e-CF history.
  • Multi-tenant: for software houses who want to offer e-CF to their clients without building from scratch.

If you want sandbox credentials, reach out. We respond in hours, not weeks.

The SSD team