Inicio rápido
Signup → primera factura simulada en sandbox en menos de 10 minutos.
Sin .p12 real, sin registro DIAN, sin cobro.
Requisitos previos
Section titled “Requisitos previos”- Cuenta Emitia con una clave
sk_test_…(sandbox, sin costo) curl, Postman, Insomnia u otro cliente HTTP
-
Verifica tu autenticación
El primer paso siempre es confirmar que tu clave funciona.
GET /v1/accountdevuelve los datos de tu cuenta — úsalo para verificar la autenticación antes de seguir.Terminal window curl https://api.emitia.co/v1/account \-H "Authorization: Bearer sk_test_TU_CLAVE_AQUI"const res = await fetch('https://api.emitia.co/v1/account', {headers: { Authorization: 'Bearer sk_test_TU_CLAVE_AQUI' },});const account = await res.json();console.log(account);import httpxres = httpx.get("https://api.emitia.co/v1/account",headers={"Authorization": "Bearer sk_test_TU_CLAVE_AQUI"},)print(res.json())$ch = curl_init('https://api.emitia.co/v1/account');curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer sk_test_TU_CLAVE_AQUI',]);$body = curl_exec($ch);echo $body;Respuesta esperada
200 OK:{"id": "ten_01HX…","name": "Mi empresa SAS","dian_environment": "habilitacion","key_mode": "test"}Si recibes
401con"code": "invalid_api_key", la clave está mal copiada o fue revocada. Consulta la página de error. -
Crea un cliente (adquirente)
Terminal window curl -X POST https://api.emitia.co/v1/customers \-H "Authorization: Bearer sk_test_TU_CLAVE_AQUI" \-H "Content-Type: application/json" \-H "Emitia-Version: 2026-01-01" \-d '{"identification": {"type": "31","number": "900000001","check_digit": "1"},"legal_name": "Acme SAS","organization_type": "1","email": "facturacion@acme.co","address": "Cra 7 # 71-21","city_code": "11001","department_code": "11","country_code": "CO"}'// Emitia-Version: 2026-01-01const res = await fetch('https://api.emitia.co/v1/customers', {method: 'POST',headers: {Authorization: 'Bearer sk_test_TU_CLAVE_AQUI','Content-Type': 'application/json','Emitia-Version': '2026-01-01',},body: JSON.stringify({identification: { type: '31', number: '900000001', check_digit: '1' },legal_name: 'Acme SAS',organization_type: '1',email: 'facturacion@acme.co',address: 'Cra 7 # 71-21',city_code: '11001',department_code: '11',country_code: 'CO',}),});const customer = await res.json();// customer.id → "cust_01HX..."import httpxres = httpx.post("https://api.emitia.co/v1/customers",headers={"Authorization": "Bearer sk_test_TU_CLAVE_AQUI","Emitia-Version": "2026-01-01",},json={"identification": {"type": "31", "number": "900000001", "check_digit": "1"},"legal_name": "Acme SAS","organization_type": "1","email": "facturacion@acme.co","address": "Cra 7 # 71-21","city_code": "11001","department_code": "11","country_code": "CO",},)customer = res.json()# customer["id"] → "cust_01HX..."// Emitia-Version: 2026-01-01$data = json_encode(['identification' => ['type' => '31', 'number' => '900000001', 'check_digit' => '1'],'legal_name' => 'Acme SAS','organization_type' => '1','email' => 'facturacion@acme.co','address' => 'Cra 7 # 71-21','city_code' => '11001','department_code' => '11','country_code' => 'CO',]);$ch = curl_init('https://api.emitia.co/v1/customers');curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,CURLOPT_POST => true,CURLOPT_POSTFIELDS => $data,CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TU_CLAVE_AQUI','Content-Type: application/json','Emitia-Version: 2026-01-01',],]);$customer = json_decode(curl_exec($ch), true);// $customer['id'] → "cust_01HX..."Guarda el
iddel cliente (cust_01HX…): lo usarás en el siguiente paso. -
Emite la primera factura
El NIT
900000001-1es un NIT de prueba determinista: el sandbox siempre responde “aceptado”. Cada línea requiereline_extension_amount(el total de la línea antes de impuestos).Terminal window curl -X POST https://api.emitia.co/v1/invoices \-H "Authorization: Bearer sk_test_TU_CLAVE_AQUI" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-H "Emitia-Version: 2026-01-01" \-d '{"customer_id": "cust_01HX_REEMPLAZA_CON_TU_ID","currency": "COP","operation_type": "10","payment_means": { "code": "10", "type": "1" },"lines": [{"description": "Servicio de consultoría","quantity": "1.00","unit_code": "94","unit_price": "100000.00","line_extension_amount": "100000.00","taxes": [{ "code": "01", "rate": "19.00", "base": "100000.00", "value": "19000.00" }]}]}'import { randomUUID } from 'crypto';// Emitia-Version: 2026-01-01const res = await fetch('https://api.emitia.co/v1/invoices', {method: 'POST',headers: {Authorization: 'Bearer sk_test_TU_CLAVE_AQUI','Content-Type': 'application/json','Idempotency-Key': randomUUID(),'Emitia-Version': '2026-01-01',},body: JSON.stringify({customer_id: 'cust_01HX_REEMPLAZA_CON_TU_ID',currency: 'COP',operation_type: '10',payment_means: { code: '10', type: '1' },lines: [{description: 'Servicio de consultoría',quantity: '1.00',unit_code: '94',unit_price: '100000.00',line_extension_amount: '100000.00',taxes: [{ code: '01', rate: '19.00', base: '100000.00', value: '19000.00' }],},],}),});const invoice = await res.json();// invoice.id → "inv_01HX..."// invoice.status → "draft" (se encola; el worker asigna consecutivo/CUFE)import httpx, uuidres = httpx.post("https://api.emitia.co/v1/invoices",headers={"Authorization": "Bearer sk_test_TU_CLAVE_AQUI","Idempotency-Key": str(uuid.uuid4()),"Emitia-Version": "2026-01-01",},json={"customer_id": "cust_01HX_REEMPLAZA_CON_TU_ID","currency": "COP","operation_type": "10","payment_means": {"code": "10", "type": "1"},"lines": [{"description": "Servicio de consultoría","quantity": "1.00","unit_code": "94","unit_price": "100000.00","line_extension_amount": "100000.00","taxes": [{"code": "01", "rate": "19.00", "base": "100000.00", "value": "19000.00"}],}],},)invoice = res.json()# invoice["id"] → "inv_01HX..."$idempotencyKey = bin2hex(random_bytes(16));$data = json_encode(['customer_id' => 'cust_01HX_REEMPLAZA_CON_TU_ID','currency' => 'COP','operation_type' => '10','payment_means' => ['code' => '10', 'type' => '1'],'lines' => [['description' => 'Servicio de consultoría','quantity' => '1.00','unit_code' => '94','unit_price' => '100000.00','line_extension_amount' => '100000.00','taxes' => [['code' => '01', 'rate' => '19.00', 'base' => '100000.00', 'value' => '19000.00']],]],]);$ch = curl_init('https://api.emitia.co/v1/invoices');curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,CURLOPT_POST => true,CURLOPT_POSTFIELDS => $data,CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TU_CLAVE_AQUI','Content-Type: application/json','Idempotency-Key: ' . $idempotencyKey,'Emitia-Version: 2026-01-01',],]);$invoice = json_decode(curl_exec($ch), true);Respuesta esperada
202 Accepted(el procesamiento es asincrónico). La factura se crea endrafty se encola; el worker asigna el consecutivo y el CUFE, por lo quefull_numberllega vacío ycufeennullen esta respuesta:{"id": "inv_01HX…","object": "invoice","status": "draft","full_number": "","cufe": null,"created_at": "2026-01-15T10:30:00-05:00"} -
Espera el resultado via webhook
La factura pasa por la cola BullMQ → se firma → se envía a la DIAN (o al simulador en sandbox). El resultado llega como un evento webhook.
Configura tu endpoint en el dashboard o vía API:
Terminal window curl -X POST https://api.emitia.co/v1/webhook-endpoints \-H "Authorization: Bearer sk_test_TU_CLAVE_AQUI" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-H "Emitia-Version: 2026-01-01" \-d '{"url": "https://tuapp.co/hooks/emitia","subscribed_events": ["invoice.accepted_by_dian", "invoice.rejected_by_dian"]}'Cuando la factura sea aceptada recibirás:
{"id": "evt_01HX…","type": "invoice.accepted_by_dian","data": {"object": {"id": "inv_01HX…","status": "accepted_by_dian","cufe": "fe9c3a1b…","pdf_url": "https://files.emitia.co/…"}}}Aprende a verificar la firma HMAC del webhook en Conceptos: Webhooks.
¿Qué sigue?
Section titled “¿Qué sigue?”| Tarea | Guía |
|---|---|
| Mapear tu POS a Emitia | Guía de mapeo POS |
| Entender la idempotencia | Conceptos: Idempotencia |
| Verificar firmas de webhooks | Conceptos: Webhooks |
| Pasar a habilitación DIAN | Conceptos: Ambientes |
| Receta para tu stack | Recetas |
| Explorar todos los endpoints | Referencia API interactiva |