REST API v1.0Colombia DIAN

JCFlow API Documentation

Integrate DIAN electronic invoicing into your application

The JCFlow API allows you to issue electronic invoices, credit notes, debit notes, and support documents directly from your ERP, POS, or custom application.

Base URL

BASH
https://api.jcflow.com.co/v1/api

Response Format

The response format always includes success (boolean), message (string), and data (object|array).

JSON
{
  "success": true,
  "message": "Operación exitosa",
  "data": { }
}

Supported Document Types

CodeTipoDescription
1FEElectronic Sales Invoice
2NCElectronic Credit Note
3NDElectronic Debit Note
4DSElectronic Support Document

Authentication

All requests require authentication via API Key in the header.

Header Name

HTTP
X-Api-Key: sk_test_tu_api_key_aqui

Test Keys

API Keys with prefix sk_test_ operate in the sandbox environment.

Production Keys

API Keys with prefix sk_live_ operate in the real DIAN environment.

Code Examples
curl -X GET https://api.jcflow.com.co/v1/api/api-keys/test \
  -H "X-Api-Key: sk_test_tu_api_key_aqui"
💡 Generate API Key: Go to the API Keys section in your dashboard to generate a new key.
Try EndpointGET /api-keys/test

⚡ Rate Limiting

Each API Key has a per-minute request limit (default 100 req/min). Response headers inform the rate limit status:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed per window
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait (only on 429 responses)
⚠️ 429 Too Many Requests: If you exceed the limit, you will receive a 429 error. Implement retry with exponential backoff.
JAVASCRIPT
// Ejemplo: Retry con backoff exponencial
async function apiCall(url, options, retries = 3) {
  for (let i = 0; i < retries; i++) {
    const res = await fetch(url, options);
    if (res.status === 429) {
      const retryAfter = res.headers.get('Retry-After') || 5;
      await new Promise(r => setTimeout(r, retryAfter * 1000 * (i + 1)));
      continue;
    }
    return res.json();
  }
  throw new Error('Rate limit exceeded after retries');
}

🔒 Idempotency

Use the referencia_externa field to guarantee a document is never issued more than once. This field acts as an idempotency key protected by a Redis distributed lock.

JSON
{
  "id_tipo_documento": 1,
  "referencia_externa": "INV-2026-00042",
  "invoice_lines": [...]
}

Duplicate Responses

CodeError CodeScenario
409DUPLICATE_REFERENCEDocument already exists with that referencia_externa
409DUPLICATE_IN_PROGRESSAnother request with the same reference is being processed
409DUPLICATE_PAYLOADIdentical payload sent within the last 5 minutes
💡 Recommendation: Always send referencia_externa with a UUID or unique ID from your system. This protects against double-click, automatic retries, and network errors.