Documentos en Codenica API

En la API pública, el nombre técnico de este objeto es documents. Un documento puede representar una factura, un pedido, un contrato, un acta u otro documento guardado en tu base de datos. Los ejemplos utilizan un registro de tipo invoice con datos de una factura enviados desde un sistema externo.

Antes de enviar la primera solicitud, crea la clave descrita en el artículo Codenica API - introducción. En las secciones siguientes encontrarás el flujo completo: comprobar el esquema y las listas, crear y actualizar registros, gestionar relaciones y archivos, usar operaciones por lotes y eliminar un registro.

  • leer listas de documentos con paginación, ordenación y filtros;
  • leer datos de facturas y otros tipos de documentos;
  • crear registros y aplicar actualizaciones parciales;
  • proteger los cambios con ETag y If-Match;
  • repetir solicitudes de forma segura mediante Idempotency-Key;
  • relacionar documentos entre sí y con otros objetos;
  • subir, descargar, adjuntar y eliminar archivos;
  • leer estadísticas, valores de campos y ejecutar operaciones agrupadas.

Los campos obligatorios y los valores disponibles pueden depender de la configuración de tu base de datos. Lee el esquema actual del tipo de documento que vas a utilizar antes de escribir datos.


Documentos - dirección de la API y tipo de despliegue

Envía las solicitudes a la dirección pública donde esté disponible tu instalación de Codenica. No utilices la dirección de la base de datos, la de un contenedor ni un puerto accesible únicamente desde el servidor. Las rutas de documentos comienzan por:

{BASE_URL}/api/v1/documents

En Codenica Cloud, utiliza el dominio público asignado a tu instalación:

export BASE_URL="https://tu-empresa.codenica.com"

En la instalación On-Premise predeterminada, la dirección registrada localmente por Codenica Discovery es:

export BASE_URL="http://codenica.local:5150"

Si el administrador ha publicado la instalación On-Premise mediante un dominio de la empresa, un reverse proxy, HTTPS u otro puerto externo, utiliza la dirección exacta que te haya proporcionado:

export BASE_URL="https://api.tu-empresa.example"

La base de datos correcta se selecciona a partir de la dirección del host. No intentes elegirla mediante tenantId, un campo adicional en la query string o un valor del body. No utilices localhost si la aplicación de integración se ejecuta en un ordenador distinto de la API. En producción, usa HTTPS cuando la instalación esté publicada con un certificado.


Documentos - permisos de la clave API

Crea la clave API en Codenica, en Settings - API - API Keys. Ponle un nombre que identifique la aplicación y el entorno y selecciona únicamente los permisos necesarios para trabajar con documentos.

El flujo completo de este artículo requiere:

  • documents:read - listar y leer documentos;
  • documents:write - crear y actualizar;
  • documents:delete - eliminar documentos;
  • documents:schema - leer campos y destinos de relaciones;
  • documents:stats - estadísticas y valores de campos;
  • documents:relationships:read y documents:relationships:write - leer y modificar relaciones;
  • documents:files:read y documents:files:write - gestionar archivos.

Para una integración de solo lectura normalmente bastan documents:read y documents:schema. Añade los permisos de estadísticas, relaciones y archivos solo cuando la integración los necesite.

Los campos técnicos pueden requerir documents:technical:read y la escritura de campos secretos requiere documents:secrets:write. Después de crear la clave, guarda el Client ID y el Client Secret en un almacén seguro. El secreto se muestra únicamente durante la creación o la rotación.


Documentos - encabezados de autenticación

La aplicación externa envía solicitudes de servidor a servidor usando dos encabezados:

export CLIENT_ID="cna_your_client_id"
export CLIENT_SECRET="cns_your_client_secret"

curl --request GET --url "$BASE_URL/api/v1/documents" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

No utilices en la integración el JWT Bearer de un administrador ni una sesión del panel. El JWT sirve para iniciar sesión en Codenica, mientras que la clave API conecta una aplicación externa con la base seleccionada. Usa HTTPS fuera de un entorno local de pruebas.

No guardes el secreto en un repositorio, una URL, los registros, el historial de comandos ni en código enviado al navegador. Los ejemplos utilizan valores ficticios.


Documentos - comprobar el contexto de la instalación

Lee el contexto antes de ejecutar las operaciones principales:

curl --request GET --url "$BASE_URL/api/v1/context" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Comprueba apiVersion, contractVersion, el identificador de la base de datos, tenant.resolvedDomain, caller.authentication con el valor api_key, los permisos necesarios y la presencia de documents en capabilities.resources. Lee también los límites de páginas, subidas y solicitudes.

Conserva meta.requestId. Si el contexto corresponde a otra instalación o falta un permiso, detén la sincronización y corrige la dirección o la clave. No intentes cambiar de base de datos en el body de la solicitud.


Documentos - esquema de campos y tipos

El esquema indica qué campos se pueden leer o escribir y qué valores acepta tu base de datos:

curl --request GET --url "$BASE_URL/api/v1/documents/schema" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Para itemType=invoice, comprueba primero los campos obligatorios:

Campo
Tipo
Significado
date
dateTime
fecha del documento
docNumber
string
número de factura o documento

El esquema también describe readable, writable, required, technical, secretWriteOnly, las opciones, la longitud máxima, la unicidad y las reglas de generación automática. El conjunto de campos no tiene por qué ser igual en todas las bases de datos.

Los campos key y keyType son secretos. No se devuelven en las respuestas normales y no se pueden utilizar para filtrar, ordenar, calcular estadísticas ni consultar valores. Compara el body con el esquema antes de enviarlo.


Documentos - endpoints disponibles

El siguiente mapa recoge las operaciones principales. Sustituye los valores entre llaves por los identificadores devueltos por la API.

  • GET /api/v1/documents - lista;
  • GET /api/v1/documents/schema - esquema de campos y relaciones;
  • GET /api/v1/documents/stats - estadísticas;
  • GET /api/v1/documents/values - valores de campos;
  • GET /api/v1/documents/{id} - documento individual;
  • POST /api/v1/documents - creación;
  • PATCH /api/v1/documents/{id} - actualización parcial;
  • DELETE /api/v1/documents/{id} - eliminación;
  • POST /api/v1/documents:batch - operaciones create, update y delete;
  • GET /api/v1/documents/{id}/relationships - lista de relaciones;
  • POST /api/v1/documents/{id}/relationships - añadir una relación;
  • POST /api/v1/documents/{id}/relationships:batch - cambiar varias relaciones;
  • DELETE /api/v1/documents/{id}/relationships/{targetDataSet}/{targetId} - eliminar una relación;
  • GET /api/v1/documents/{id}/files - lista de archivos;
  • POST /api/v1/documents/{id}/files - subida;
  • POST /api/v1/documents/{id}/files/{fileId} - adjuntar un archivo existente;
  • PUT /api/v1/documents/{id}/files/{fileId}/main - establecer el archivo principal;
  • DELETE /api/v1/documents/{id}/files/{fileId} - eliminar o desvincular un archivo;
  • GET /api/v1/documents/{id}/files/{fileId}/content - descargar el contenido.

Una respuesta 403 suele indicar que falta un permiso en la clave o que el usuario asociado no tiene la autorización necesaria.


Documentos - listados y paginación

Lee la lista página por página. Este ejemplo devuelve los diez primeros documentos invoice:

curl --request GET --url "$BASE_URL/api/v1/documents?itemType=invoice&page=1&pageSize=10&sort=date&direction=desc" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

La respuesta de una colección contiene items, page, pageSize, totalItems, totalPages y hasNextPage. Continúa mientras hasNextPage sea true. Si el orden es importante para la sincronización, establece siempre una ordenación explícita.

Lee el límite de pageSize en el contexto. No supongas que la primera página contiene todas las facturas ni que el orden predeterminado permanecerá igual.


Documentos - búsqueda y filtros

El ejemplo de prueba busca un documento por su identificador personalizado, tipo y estado:

curl --request GET --url "$BASE_URL/api/v1/documents?itemType=invoice&customId=PUBLIC-API-DOC-20260905101715-SOURCE&status=Draft&sort=customId&direction=asc&page=1&pageSize=10" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Según el esquema, puedes utilizar parámetros como itemType, ids, search, customId, docNumber, name, status, category, currency, createdAfter, createdBefore, updatedAfter y updatedBefore.

Para condiciones precisas, utiliza filter:

filter=status:eq:Draft
filter=docNumber:contains:2026
filter=category:in:Procurement,Sales
filter=description:notEmpty:

Los operadores incluyen eq, ne, in, contains, startsWith, endsWith, empty, notEmpty, gt, gte, lt y lte. Codifica según las reglas de las URL los valores que contengan espacios o caracteres especiales.


Documentos - seleccionar campos e incluir datos

El parámetro fields limita la respuesta a los campos que necesitas:

curl --request GET --url "$BASE_URL/api/v1/documents?itemType=invoice&fields=id,itemType,customId,docNumber,name,status,total" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Utiliza include para leer los archivos y las relaciones junto con el registro:

curl --request GET --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID?include=files,relationships" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

El acceso a los datos incluidos debe concederse por separado. La falta de documents:files:read o documents:relationships:read no se puede evitar mediante fields=*. Los campos técnicos y secretos solo se devuelven cuando los permisos y el esquema lo permiten.


Documentos - crear un registro

Utiliza POST /api/v1/documents para crear un documento. Indica el tipo en itemType y coloca los campos escribibles en attributes. Este ejemplo representa una factura enviada desde un sistema contable:

export IDEMPOTENCY_KEY="documents-create-20260905-0001"

curl --request POST --url "$BASE_URL/api/v1/documents" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data-raw '{
    "itemType": "invoice",
    "attributes": {
      "customId": "PUBLIC-API-DOC-20260905101715-SOURCE",
      "date": "2026-09-05T10:17:15Z",
      "docNumber": "FV/2026/0001",
      "name": "Invoice from ERP",
      "category": "Procurement",
      "type": "invoice",
      "status": "Draft",
      "currency": "PLN",
      "paymentMethod": "bank_transfer",
      "total": 1250.50,
      "description": "Document imported from the external accounting system."
    }
  }'

En el esquema invoice probado, date y docNumber eran obligatorios. Tu base de datos puede exigir campos adicionales o valores diferentes. No envíes campos de solo lectura ni un id salvo que el esquema lo permita expresamente.

Una respuesta correcta tiene el estado 201 Created. Guarda data.id, el ETag del encabezado HTTP y data.meta.etag. customId facilita encontrar después el documento en el sistema externo.


Documentos - repetir la creación de forma segura

Si se produce un timeout después de enviar una factura, todavía no sabes si el registro se guardó. Envía exactamente la misma solicitud con el mismo Idempotency-Key y un body idéntico. No crees una clave nueva solo porque no llegó la primera respuesta:

curl --request POST --url "$BASE_URL/api/v1/documents" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data-raw '{
    "itemType": "invoice",
    "attributes": {
      "customId": "PUBLIC-API-DOC-20260905101715-SOURCE",
      "date": "2026-09-05T10:17:15Z",
      "docNumber": "FV/2026/0001",
      "name": "Invoice from ERP",
      "category": "Procurement",
      "type": "invoice",
      "status": "Draft",
      "currency": "PLN",
      "paymentMethod": "bank_transfer",
      "total": 1250.50,
      "description": "Document imported from the external accounting system."
    }
  }'

La repetición idempotente devuelve el mismo documento en lugar de crear un duplicado. La misma clave no puede describir después otro body, endpoint u objetivo. Ese uso devuelve 422 idempotency_key_reused. Utiliza un valor nuevo para cada nueva operación.


Documentos - leer un registro

Después de crear o encontrar un documento, léelo mediante su UUID:

export DOCUMENT_ID="11111111-1111-1111-1111-111111111111"

curl --request GET --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID?include=files,relationships" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

La respuesta contiene id, itemType, los campos en attributes y los metadatos en meta. El ETag actual aparece en el encabezado HTTP y normalmente también en data.meta.etag y en la envoltura meta.etag.

Lee un ETag actualizado antes de cada cambio en el documento, una relación o un archivo. No utilices un valor guardado anteriormente si otra persona o integración pudo modificar el registro.


Documentos - actualización parcial con ETag

PATCH cambia únicamente los campos enviados en el body. Requiere el valor actual de If-Match y una nueva Idempotency-Key:

export CURRENT_ETAG='"etag-v1"'
export UPDATE_IDEMPOTENCY_KEY="documents-update-20260905-0001"

curl --request PATCH --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: $UPDATE_IDEMPOTENCY_KEY" \
  --data-raw '{
    "attributes": {
      "status": "Approved",
      "total": 1350.75,
      "description": "Invoice approved after verification in the accounting system."
    }
  }'

No es necesario enviar el documento completo. Los campos que no aparecen en el body permanecen sin cambios. Después de una operación correcta, guarda el nuevo ETag devuelto por la API.


Documentos - protección frente a cambios obsoletos

La API rechaza los cambios que no incluyen el ETag actual. Si omites If-Match, devuelve 428 if_match_required:

curl --request PATCH --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: documents-update-without-etag-0001" \
  --data-raw '{"attributes":{"status":"Approved"}}'

Si envías un ETag antiguo, recibirás 412 if_match_failed y el registro no cambiará. Lee de nuevo el documento, comprueba la nueva versión y decide entonces si debes volver a enviar tu cambio.

{
  "status": 412,
  "code": "if_match_failed",
  "detail": "The supplied ETag is not the current document version.",
  "requestId": "request-id-from-response"
}

La misma regla se aplica al eliminar documentos, cambiar relaciones y operar con archivos cuando la ruta modifica el registro.


Documentos - relaciones y destinos válidos

Un documento puede vincularse con otro objeto cuando el destino es visible para la clave y está permitido por el esquema. Antes de enviar una relación, comprueba relationshipTargets en la respuesta del esquema.

Envía targetId, targetDataSet, el targetItemType opcional y relationshipType cuando el destino seleccionado lo admita. Este ejemplo vincula directamente dos facturas:

curl --request POST --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/relationships" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-relationship-add-0001" \
  --data-raw '{
    "targetId": "22222222-2222-2222-2222-222222222222",
    "targetDataSet": "documents",
    "targetItemType": "invoice",
    "relationshipType": "related"
  }'

No envíes un targetItemType diferente del tipo real del destino. No crees una relación consigo mismo ni con un registro que la clave no pueda ver.


Documentos - leer y eliminar relaciones

Lee la lista de relaciones actuales por separado o junto con el documento:

curl --request GET --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/relationships?targetDataSet=documents&targetItemType=invoice&relationshipType=related&page=1&pageSize=50" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Para eliminar una relación, lee primero un ETag actualizado del documento y envía:

curl --request DELETE --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/relationships/documents/$TARGET_DOCUMENT_ID?relationshipType=related&targetItemType=invoice" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-relationship-delete-0001"

Una eliminación correcta devuelve 200 con data=true. Vuelve a leer la lista después de la operación y guarda el nuevo ETag del documento.


Documentos - cambiar varias relaciones a la vez

Utiliza relationships:batch para añadir y eliminar varias relaciones en una sola solicitud:

curl --request POST --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/relationships:batch" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-relationship-batch-0001" \
  --data-raw '{
    "add": [
      {
        "targetId": "33333333-3333-3333-3333-333333333333",
        "targetDataSet": "documents",
        "targetItemType": "invoice",
        "relationshipType": "related"
      }
    ],
    "remove": [
      {
        "targetId": "22222222-2222-2222-2222-222222222222",
        "targetDataSet": "documents",
        "targetItemType": "invoice",
        "relationshipType": "related"
      }
    ]
  }'

La respuesta indica los contadores added, removed y skipped. Utiliza un ETag actual aunque el lote contenga un solo cambio. Si el resultado es parcial, revisa cada elemento antes de enviar otra solicitud.


Documentos - listar y subir un archivo

Los archivos se gestionan por separado de los campos del documento. Empieza leyendo la lista actual:

curl --request GET --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/files?page=1&pageSize=50" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Envía el archivo como multipart/form-data. Este ejemplo crea un archivo de texto y lo establece como principal:

printf 'Invoice attachment created by the ERP integration.\n' > invoice-primary.txt
export FILE_UPLOAD_ETAG='"etag-v1"'

curl --request POST --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/files?makeMain=true&relationshipType=documentation" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $FILE_UPLOAD_ETAG" \
  --header "Idempotency-Key: documents-file-upload-0001" \
  --form "[email protected];type=text/plain"

La respuesta contiene id, fileName, contentType, size, relationshipType, isMain y downloadUrl. Esta URL es relativa a BASE_URL.


Documentos - descargar un archivo y cambiar el archivo principal

Descarga el contenido mediante el endpoint content. Guárdalo como datos binarios:

curl --request GET --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/files/$FILE_ID/content" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --output downloaded-invoice-file

Puedes subir un segundo archivo con makeMain=false. Para cambiar el archivo principal, lee el ETag actual del documento y llama a:

curl --request PUT --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/files/$FILE_ID/main" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-file-main-0001"

Lee la lista de archivos después del cambio. Solo un archivo debe tener isMain=true. Guarda el nuevo ETag tras la operación.


Documentos - adjuntar un archivo existente

Si un archivo ya está guardado con otro documento, puedes adjuntarlo a otro registro sin volver a subir su contenido:

export TARGET_DOCUMENT_ID="11111111-1111-1111-1111-111111111111"
export EXISTING_FILE_ID="44444444-4444-4444-4444-444444444444"

curl --request POST --url "$BASE_URL/api/v1/documents/$TARGET_DOCUMENT_ID/files/$EXISTING_FILE_ID?makeMain=true&relationshipType=manual" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-file-attach-0001"

Adjuntar crea una relación entre el documento y el archivo. Desvincularlo mediante DELETE /documents/{id}/files/{fileId} elimina la relación de ese documento, pero no borra un archivo que pertenezca a otro documento. Eliminar el archivo desde su documento propietario es una operación independiente.


Documentos - eliminar un archivo

Lee una lista reciente de archivos y el ETag del documento antes de eliminar un archivo. Si eliminas el archivo principal actual, el sistema puede seleccionar automáticamente otro archivo principal:

curl --request DELETE --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID/files/$FILE_ID" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-file-delete-0001"

Después de una respuesta 200, actualiza el ETag y vuelve a leer la lista. Eliminar el último archivo no elimina el documento, sino que deja una colección de archivos vacía. Si el archivo solo estaba adjunto al documento, elimina primero la relación y solo después considera eliminarlo en el lugar donde está almacenado.


Documentos - estadísticas y valores de campos

Las estadísticas muestran la distribución de los datos y el endpoint values devuelve valores útiles para crear filtros:

curl --request GET --url "$BASE_URL/api/v1/documents/stats?field=status&limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

curl --request GET --url "$BASE_URL/api/v1/documents/values?field=status&search=Draf&limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Ejemplo de respuesta de valores:

{
  "data": {
    "field": "status",
    "values": ["Draft", "Approved", "Paid"]
  },
  "meta": {
    "requestId": "request-id-from-response"
  }
}

Las estadísticas y los valores no modifican los datos. No los utilices para campos secretos o técnicos sin el permiso correspondiente.


Documentos - operaciones por lotes

El endpoint documents:batch permite crear, actualizar y eliminar varios documentos en una sola solicitud. Las operaciones update y delete requieren su propio ETag para cada elemento:

curl --request POST --url "$BASE_URL/api/v1/documents:batch" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: documents-batch-0001" \
  --data-raw '{
    "items": [
      {
        "operation": "create",
        "create": {
          "itemType": "invoice",
          "attributes": {
            "customId": "PUBLIC-API-DOC-20260905101715-TARGET-A",
            "date": "2026-09-05T10:18:00Z",
            "docNumber": "FV/2026/0002",
            "name": "Related invoice",
            "category": "Procurement",
            "type": "invoice",
            "status": "Draft",
            "currency": "PLN",
            "paymentMethod": "bank_transfer",
            "total": 510.00
          }
        }
      },
      {
        "operation": "update",
        "id": "11111111-1111-1111-1111-111111111111",
        "ifMatch": "\"etag-v1\"",
        "update": {
          "attributes": {
            "status": "Approved"
          }
        }
      },
      {
        "operation": "delete",
        "id": "22222222-2222-2222-2222-222222222222",
        "ifMatch": "\"etag-v3\""
      }
    ]
  }'

Si todo se completa correctamente, recibirás 200; si el resultado es parcial, 207. Un lote no es una transacción de todo o nada. Guarda los identificadores, ETags y estados de cada operación.


Documentos - eliminar un registro

La eliminación de un documento no se puede deshacer mediante la API. Lee el ETag actual y comprueba que el UUID y la dirección de la base sean correctos:

curl --request DELETE --url "$BASE_URL/api/v1/documents/$DOCUMENT_ID" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: documents-delete-0001"

Una respuesta correcta devuelve 200 y data=true. Una lectura posterior del documento devuelve 404 document_not_found. Si el registro tiene relaciones o archivos, guarda fuera del sistema los datos que necesites antes de eliminarlo.


Documentos - errores, límites y seguridad

Los errores utilizan el formato Problem Details. Los campos más importantes son status, code, detail y requestId. Basa la lógica de la aplicación en el campo estable code.

  • 400 - campos, tipo de documento o relación no válidos;
  • 401 - credenciales ausentes o no válidas;
  • 403 - permiso o autorización ausente;
  • 404 - el documento o el destino no existe o no es visible;
  • 409 - conflicto de datos;
  • 412 - ETag obsoleto;
  • 413 - el archivo supera el límite;
  • 428 - falta If-Match o Idempotency-Key;
  • 429 - se ha superado el límite de solicitudes;
  • 503 - el servicio no está disponible temporalmente.

Lee X-RateLimit-Limit y X-RateLimit-Remaining. Para 429, utiliza Retry-After si se devuelve y aumenta el tiempo de espera entre intentos. Oculta en los registros el Client Secret, los secretos de los documentos y el contenido de los archivos.


Documentos - flujo completo de integración

  1. Crea una clave en Settings - API - API Keys y concede solo los permisos que necesita la integración.
  2. Establece BASE_URL en la dirección pública de Codenica Cloud o en la dirección On-Premise proporcionada por el administrador.
  3. Envía GET /api/v1/context y confirma la base de datos, el emisor, los permisos y los límites correctos.
  4. Lee GET /api/v1/documents/schema y elige el tipo de documento, los campos obligatorios y los valores aceptados.
  5. Lee la lista paginada y filtrada o recupera un documento mediante su UUID.
  6. Crea una factura con un Idempotency-Key único, guarda su UUID y ETag y repite la solicitud idéntica después de un timeout.
  7. Actualiza el registro solo con el If-Match actual y guarda el nuevo ETag después de cada cambio.
  8. Añade, lee y elimina las relaciones permitidas por el esquema.
  9. Utiliza los endpoints específicos de archivos, conserva el ETag actual y distingue entre adjuntar y eliminar un archivo.
  10. Para volúmenes mayores, utiliza stats, values y documents:batch y revisa después el resultado de cada operación.
  11. Antes de eliminar, vuelve a leer el documento, confirma el ETag correcto y utiliza una clave de idempotencia nueva.

Este flujo permite trasladar la gestión de facturas y otros documentos a un sistema contable, una herramienta de gestión documental, un ERP o una aplicación de integración propia.