Ir al contenido

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

Cualquiera de estas credenciales:

  • LlaveApi — Llave de API de una integración. El valor completo es Api-Key <prefijo>.<secreto>, tal como lo imprime manage.py crear_llave_api. La llave alcanza exactamente los mismos emisores que la persona a cuyo nombre se creó.

Tipo de contenido: application/json · obligatorio.

CampoTipoObligatorioDescripción
documento_tipointeger
emisorinteger
numero_resolucionstring
adquirienteAdquirienteRequestDatos del receptor. No tiene endpoint propio: se piden en el documento.
prefijostring
consecutivointeger (int64)
numerostringnoNúmero del documento (cbc:ID). Si se omite, se arma como prefijo + consecutivo.
fecha_emisionstring (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).
monedainteger
forma_pagointeger
medio_pagointeger
total_descuentosstring (decimal)noDescuentos globales del documento (no los de línea).
descuentos_motivostringnocbc:AllowanceChargeReason del descuento global.
total_cargosstring (decimal)no
cargos_motivostringnocbc:AllowanceChargeReason del cargo global.
documento_referenciastring (uuid)noAdmite null.
concepto_correccionstringnoResponseCode 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_vencimientostring (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_comprastringnoNúmero de la orden de compra del adquiriente, si la hubo.
orden_compra_fechastring (date)noAdmite null.
orden_compra_tipostringnocbc:OrderTypeCode: qué clase de orden es (contrato, pedido…), según la codificación que use el comprador.
orden_compra_documentostringnocac:DocumentReference/cbc:ID: el soporte de la orden (contrato, acuerdo marco) cuando es distinto del número de la orden.
observacionesstringno
detallesarray<DocumentoDetalleRequest>
posDocumentoPOSRequestnoVa 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.
Ventana de terminal
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
}
}'
CódigoDescripción
201
400Error
401Error
409
429Error
CampoTipoDescripción
idstring (uuid)Solo lectura.
documento_tipointeger
emisorinteger
adquirienteAdquirienteDatos del receptor. No tiene endpoint propio: se piden en el documento.
prefijostring
consecutivointeger (int64)
numerostringNúmero del documento (cbc:ID). Si se omite, se arma como prefijo + consecutivo.
fecha_emisionstring (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).
monedainteger
forma_pagointeger
medio_pagointeger
total_descuentosstring (decimal)Descuentos globales del documento (no los de línea).
descuentos_motivostringcbc:AllowanceChargeReason del descuento global.
total_cargosstring (decimal)
cargos_motivostringcbc:AllowanceChargeReason del cargo global.
documento_referenciastring (uuid)Admite null.
concepto_correccionstringResponseCode 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_vencimientostring (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_comprastringNúmero de la orden de compra del adquiriente, si la hubo.
orden_compra_fechastring (date)Admite null.
orden_compra_tipostringcbc:OrderTypeCode: qué clase de orden es (contrato, pedido…), según la codificación que use el comprador.
orden_compra_documentostringcac:DocumentReference/cbc:ID: el soporte de la orden (contrato, acuerdo marco) cuando es distinto del número de la orden.
observacionesstring
detallesarray<DocumentoDetalle>
posDocumentoPOSVa 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",
"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": [
{
"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
}
}
CampoTipoDescripción
detailstringMensaje para mostrar a la persona.
erroresarray<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"
}
]
}
CampoTipoDescripción
detailstringMensaje para mostrar a la persona.
erroresarray<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"
}
]
}
CampoTipoDescripción
detailstringMensaje para mostrar a la persona.
erroresarray<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"
}
]
}
CampoTipoDescripción
detailstringMensaje para mostrar a la persona.
erroresarray<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.