POST /api/documentos/documento/
POST /api/documentos/documento/
Crea el documento, o responde 409 si ese número ya existe.
El orden es estructura → duplicado → datos. La estructura va primero, como en toda la recepción. El duplicado va antes que los datos porque es la respuesta que necesita un reintento: el ERP que perdió la respuesta del primer intento y repite la petición al día siguiente ya no pasaría la fecha de emisión, y un 400 por la fecha le escondería que el documento existe.
El 409 lleva el cuerpo de error común (código documento_duplicado) y
la ruta del existente en Location: es donde HTTP la pone, y así el
cuerpo no se sale de detail + errores.
La búsqueda previa no cubre la carrera —dos peticiones iguales que la
pasan a la vez—: esa la resuelve la restricción de unicidad de la base,
y el IntegrityError se traduce al mismo 409.
operationId: documentos_documento_create
Autenticación
Sección titulada «Autenticación»Cualquiera de estas credenciales:
- LlaveApi — Llave de API de una integración. El valor completo es
Api-Key <prefijo>.<secreto>, tal como lo imprimemanage.py crear_llave_api. La llave alcanza exactamente los mismos emisores que la persona a cuyo nombre se creó.
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»Tipo de contenido: application/json · obligatorio.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
documento_tipo | integer | sí | |
emisor | integer | sí | |
numero_resolucion | string | sí | |
adquiriente | AdquirienteRequest | sí | Datos del receptor. No tiene endpoint propio: se piden en el documento. |
prefijo | string | sí | |
consecutivo | integer (int64) | sí | |
numero | string | no | Número del documento (cbc:ID). Si se omite, se arma como prefijo + consecutivo. |
fecha_emision | string (date) | sí | IssueDate del XML. Si se omite se toma la fecha de hoy, que es la única con la que se puede firmar (regla FAD09). |
moneda | integer | sí | |
forma_pago | integer | sí | |
medio_pago | integer | sí | |
total_descuentos | string (decimal) | no | Descuentos globales del documento (no los de línea). |
descuentos_motivo | string | no | cbc:AllowanceChargeReason del descuento global. |
total_cargos | string (decimal) | no | |
cargos_motivo | string | no | cbc:AllowanceChargeReason del cargo global. |
documento_referencia | string (uuid) | no | Admite null. |
concepto_correccion | string | no | ResponseCode del DiscrepancyResponse: por qué se corrige el documento referenciado. Los códigos válidos dependen del tipo de nota (ConceptoNotaCredito, ConceptoNotaDebito, ConceptoNotaAjuste). Vacío en lo que no es nota. |
fecha_vencimiento | string (date) | sí | DueDate del XML: hasta cuándo hay plazo para pagar. La DIAN la exige cuando la forma de pago es a crédito; en contado sobra. Admite null. |
orden_compra | string | no | Número de la orden de compra del adquiriente, si la hubo. |
orden_compra_fecha | string (date) | no | Admite null. |
orden_compra_tipo | string | no | cbc:OrderTypeCode: qué clase de orden es (contrato, pedido…), según la codificación que use el comprador. |
orden_compra_documento | string | no | cac:DocumentReference/cbc:ID: el soporte de la orden (contrato, acuerdo marco) cuando es distinto del número de la orden. |
observaciones | string | no | |
detalles | array<DocumentoDetalleRequest> | sí | |
pos | DocumentoPOSRequest | no | Va anidado en el documento, como el adquiriente. Alimenta dos de las tres extensiones obligatorias del P.O.S. (DEPD11 y DEPD21). La tercera, la del fabricante del software, sale de SoftwareDian y no se pide aquí: es constante para todos los tiquetes. La caja llega aquí y no por id de un maestro: el punto de venta conoce su placa, no nuestros identificadores internos, y así no hace falta darla de alta antes de vender. Los campos del comprador y el subtotal pueden omitirse; el constructor los toma del propio documento. No es que la DIAN los admita vacíos —los tres pares son de rechazo—, es que su valor ya está en el documento y pedirlo dos veces solo daría ocasión de que no coincidan. |
Ejemplo
Sección titulada «Ejemplo»curl -X POST "https://api.rededoc.uk/api/documentos/documento/" \ -H "Authorization: <llaveapi>" \ -H "Content-Type: application/json" \ -d '{ "documento_tipo": 1, "emisor": 1, "numero_resolucion": "texto", "adquiriente": { "razon_social": "texto", "primer_nombre": "texto", "segundo_nombre": "texto", "primer_apellido": "texto", "segundo_apellido": "texto", "tipo_identificacion": 1, "numero_identificacion": "texto", "tipo_organizacion": 1, "responsabilidades": [ 1 ], "pais": 1, "departamento": 1, "municipio": 1, "direccion": "texto", "codigo_postal": "texto", "telefono": "texto", "correo": "[email protected]" }, "prefijo": "texto", "consecutivo": 0, "numero": "texto", "fecha_emision": "2026-01-31", "moneda": 1, "forma_pago": 1, "medio_pago": 1, "total_descuentos": "0.00", "descuentos_motivo": "texto", "total_cargos": "0.00", "cargos_motivo": "texto", "documento_referencia": "00000000-0000-0000-0000-000000000000", "concepto_correccion": "texto", "fecha_vencimiento": "2026-01-31", "orden_compra": "texto", "orden_compra_fecha": "2026-01-31", "orden_compra_tipo": "texto", "orden_compra_documento": "texto", "observaciones": "texto", "detalles": [ { "numero_linea": 0, "descripcion": "texto", "codigo_producto": "texto", "cantidad": "0.00", "unidad_medida": 1, "valor_unitario": "0.00", "valor_total": "0.00", "descuento": "0.00", "descuento_motivo": "texto", "impuestos": [ { "tributo": 1, "base_gravable": "0.00", "tarifa": "0.00", "valor": "0.00" } ], "nota": "texto", "marca": "texto", "modelo": "texto", "centro_costo": "texto", "periodo_desde": "2026-01-31", "periodo_hasta": "2026-01-31", "periodo_descripcion": "texto", "periodo_descripcion_codigo": "texto" } ], "pos": { "caja_placa": "texto", "caja_ubicacion": "texto", "caja_tipo": "texto", "cajero": "texto", "codigo_venta": "texto", "subtotal": "0.00", "comprador_codigo": "texto", "comprador_nombres": "texto", "comprador_puntos": 0 } }'Respuestas
Sección titulada «Respuestas»| Código | Descripción |
|---|---|
201 | |
400 | Error |
401 | Error |
409 | |
429 | Error |
201 — cuerpo
Sección titulada «201 — cuerpo»| Campo | Tipo | Descripción |
|---|---|---|
id | string (uuid) | Solo lectura. |
documento_tipo | integer | |
emisor | integer | |
adquiriente | Adquiriente | Datos del receptor. No tiene endpoint propio: se piden en el documento. |
prefijo | string | |
consecutivo | integer (int64) | |
numero | string | Número del documento (cbc:ID). Si se omite, se arma como prefijo + consecutivo. |
fecha_emision | string (date) | IssueDate del XML. Si se omite se toma la fecha de hoy, que es la única con la que se puede firmar (regla FAD09). |
moneda | integer | |
forma_pago | integer | |
medio_pago | integer | |
total_descuentos | string (decimal) | Descuentos globales del documento (no los de línea). |
descuentos_motivo | string | cbc:AllowanceChargeReason del descuento global. |
total_cargos | string (decimal) | |
cargos_motivo | string | cbc:AllowanceChargeReason del cargo global. |
documento_referencia | string (uuid) | Admite null. |
concepto_correccion | string | ResponseCode del DiscrepancyResponse: por qué se corrige el documento referenciado. Los códigos válidos dependen del tipo de nota (ConceptoNotaCredito, ConceptoNotaDebito, ConceptoNotaAjuste). Vacío en lo que no es nota. |
fecha_vencimiento | string (date) | DueDate del XML: hasta cuándo hay plazo para pagar. La DIAN la exige cuando la forma de pago es a crédito; en contado sobra. Admite null. |
orden_compra | string | Número de la orden de compra del adquiriente, si la hubo. |
orden_compra_fecha | string (date) | Admite null. |
orden_compra_tipo | string | cbc:OrderTypeCode: qué clase de orden es (contrato, pedido…), según la codificación que use el comprador. |
orden_compra_documento | string | cac:DocumentReference/cbc:ID: el soporte de la orden (contrato, acuerdo marco) cuando es distinto del número de la orden. |
observaciones | string | |
detalles | array<DocumentoDetalle> | |
pos | DocumentoPOS | Va anidado en el documento, como el adquiriente. Alimenta dos de las tres extensiones obligatorias del P.O.S. (DEPD11 y DEPD21). La tercera, la del fabricante del software, sale de SoftwareDian y no se pide aquí: es constante para todos los tiquetes. La caja llega aquí y no por id de un maestro: el punto de venta conoce su placa, no nuestros identificadores internos, y así no hace falta darla de alta antes de vender. Los campos del comprador y el subtotal pueden omitirse; el constructor los toma del propio documento. No es que la DIAN los admita vacíos —los tres pares son de rechazo—, es que su valor ya está en el documento y pedirlo dos veces solo daría ocasión de que no coincidan. |
{ "id": "00000000-0000-0000-0000-000000000000", "documento_tipo": 1, "emisor": 1, "adquiriente": { "razon_social": "texto", "primer_nombre": "texto", "segundo_nombre": "texto", "primer_apellido": "texto", "segundo_apellido": "texto", "tipo_identificacion": 1, "numero_identificacion": "texto", "digito_verificacion": "texto", "tipo_organizacion": 1, "responsabilidades": [ 1 ], "pais": 1, "departamento": 1, "municipio": 1, "direccion": "texto", "codigo_postal": "texto", "telefono": "texto", }, "prefijo": "texto", "consecutivo": 0, "numero": "texto", "fecha_emision": "2026-01-31", "moneda": 1, "forma_pago": 1, "medio_pago": 1, "total_descuentos": "0.00", "descuentos_motivo": "texto", "total_cargos": "0.00", "cargos_motivo": "texto", "documento_referencia": "00000000-0000-0000-0000-000000000000", "concepto_correccion": "texto", "fecha_vencimiento": "2026-01-31", "orden_compra": "texto", "orden_compra_fecha": "2026-01-31", "orden_compra_tipo": "texto", "orden_compra_documento": "texto", "observaciones": "texto", "detalles": [ { "id": 1, "numero_linea": 0, "descripcion": "texto", "codigo_producto": "texto", "cantidad": "0.00", "unidad_medida": 1, "valor_unitario": "0.00", "valor_total": "0.00", "descuento": "0.00", "descuento_motivo": "texto", "impuestos": [ { "id": 1, "tributo": 1, "tributo_codigo": "texto", "base_gravable": "0.00", "tarifa": "0.00", "valor": "0.00" } ], "nota": "texto", "marca": "texto", "modelo": "texto", "centro_costo": "texto", "periodo_desde": "2026-01-31", "periodo_hasta": "2026-01-31", "periodo_descripcion": "texto", "periodo_descripcion_codigo": "texto" } ], "pos": { "caja_placa": "texto", "caja_ubicacion": "texto", "caja_tipo": "texto", "cajero": "texto", "codigo_venta": "texto", "subtotal": "0.00", "comprador_codigo": "texto", "comprador_nombres": "texto", "comprador_puntos": 0 }}400 — cuerpo
Sección titulada «400 — cuerpo»| Campo | Tipo | Descripción |
|---|---|---|
detail | string | Mensaje para mostrar a la persona. |
errores | array<object> | Nunca vacía. Cada error trae codigo, que es lo que el cliente mapea —los de DRF tal cual (required, invalid, does_not_exist, not_found…) y los propios en español (campo_desconocido, solicitud_invalida…)—, y mensaje, para la persona. Si el error es de un campo, su ruta va delante del mensaje: detalles[0].impuestos[0].tributo: Este campo es obligatorio. |
{ "detail": "texto", "errores": [ { "codigo": "texto", "mensaje": "texto" } ]}401 — cuerpo
Sección titulada «401 — cuerpo»| Campo | Tipo | Descripción |
|---|---|---|
detail | string | Mensaje para mostrar a la persona. |
errores | array<object> | Nunca vacía. Cada error trae codigo, que es lo que el cliente mapea —los de DRF tal cual (required, invalid, does_not_exist, not_found…) y los propios en español (campo_desconocido, solicitud_invalida…)—, y mensaje, para la persona. Si el error es de un campo, su ruta va delante del mensaje: detalles[0].impuestos[0].tributo: Este campo es obligatorio. |
{ "detail": "texto", "errores": [ { "codigo": "texto", "mensaje": "texto" } ]}409 — cuerpo
Sección titulada «409 — cuerpo»| Campo | Tipo | Descripción |
|---|---|---|
detail | string | Mensaje para mostrar a la persona. |
errores | array<object> | Nunca vacía. Cada error trae codigo, que es lo que el cliente mapea —los de DRF tal cual (required, invalid, does_not_exist, not_found…) y los propios en español (campo_desconocido, solicitud_invalida…)—, y mensaje, para la persona. Si el error es de un campo, su ruta va delante del mensaje: detalles[0].impuestos[0].tributo: Este campo es obligatorio. |
{ "detail": "texto", "errores": [ { "codigo": "texto", "mensaje": "texto" } ]}429 — cuerpo
Sección titulada «429 — cuerpo»| Campo | Tipo | Descripción |
|---|---|---|
detail | string | Mensaje para mostrar a la persona. |
errores | array<object> | Nunca vacía. Cada error trae codigo, que es lo que el cliente mapea —los de DRF tal cual (required, invalid, does_not_exist, not_found…) y los propios en español (campo_desconocido, solicitud_invalida…)—, y mensaje, para la persona. Si el error es de un campo, su ruta va delante del mensaje: detalles[0].impuestos[0].tributo: Este campo es obligatorio. |
{ "detail": "texto", "errores": [ { "codigo": "texto", "mensaje": "texto" } ]}RedEDoc es un servicio de Semántica Digital S.A.S.