Factuarea API
Conceptos clave

Etiquetas y campos personalizados

Clasifica documentos con tags y adjunta custom_fields tipados. Filtra listados por tag. En qué se diferencian de metadata.

Dos campos transversales te permiten clasificar y enriquecer los documentos con tus propios datos de negocio: tags (etiquetas de clasificación libres por las que puedes filtrar los listados) y custom_fields (una lista ordenada de pares tipados {field, value}). Ambos se establecen en create/update y se devuelven en cada lectura.

CampoFormaLímitesFiltrableRecursos
tagsarray de slugs≤ 30, cada uno ≤ 40 caracteres (?tags=, ?tags[in]=)invoices, quotes, proformas, delivery_notes, purchase_invoices, recurring_invoices, products
custom_fieldsarray ordenado de {field, value}≤ 50 entradasNoinvoices, quotes, proformas, delivery_notes, purchase_invoices, recurring_invoices

Etiquetas

Un tag es un slug en minúscula que cumple [a-z0-9-] — solo letras, dígitos y guiones. Cada tag mide como máximo 40 caracteres, y un documento lleva como máximo 30 tags. Pásalos como un array JSON de strings al crear o actualizar:

curl -X POST https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
    "series_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02",
    "issued_on": "2026-05-15",
    "due_on": "2026-06-15",
    "tags": ["consultoria", "cliente-vip"],
    "lines": [
      { "description": "Monthly service", "quantity": 1, "unit_price": 99.00, "tax_rate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03" }
    ]
  }'

Los tags se devuelven como un array plano en cada lectura (vacío [] cuando no hay ninguno):

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b",
  "number": "F-2026-0042",
  "tags": ["consultoria", "cliente-vip"]
}

tags es un reemplazo completo al actualizar: enviar "tags": ["a"] sustituye todo el conjunto, no lo añade. Para agregar un tag, envía la lista completa incluidos los existentes. Para vaciarlos, envía [].

Filtrar por tag

Los endpoints de listado aceptan dos parámetros de query para filtrar por tag — elige uno:

ParámetroSemánticaEjemplo
tagsCoincidencia exacta con un único slug.?tags=cliente-vip
tags[in]Lista separada por comas, semántica OR — coincide con los documentos que lleven cualquiera de los slugs.?tags[in]=cliente-vip,moroso
# Todas las facturas etiquetadas con "cliente-vip"
curl -G https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "tags=cliente-vip"

# Facturas etiquetadas con "cliente-vip" O "moroso"
curl -G https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "tags[in]=cliente-vip,moroso"

El filtro por tag está disponible en invoices, quotes, proformas, delivery_notes, purchase_invoices y recurring_invoices. Se combina con los demás filtros y con la paginación por cursor.

Campos personalizados

custom_fields es un array ordenado de pares tipados {field, value}, para datos de negocio que quieras mostrar junto al documento (centro de coste, número de pedido, código de proyecto…). Hasta 50 entradas; cada field es un string no vacío de como máximo 60 caracteres y cada value es un string de como máximo 500 caracteres. El orden se conserva exactamente como lo envías.

curl -X POST https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
    "series_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02",
    "issued_on": "2026-05-15",
    "due_on": "2026-06-15",
    "custom_fields": [
      { "field": "centro_coste", "value": "CC-2026-001" },
      { "field": "numero_pedido", "value": "PO-2026-0042" }
    ],
    "lines": [
      { "description": "Monthly service", "quantity": 1, "unit_price": 99.00, "tax_rate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03" }
    ]
  }'

Igual que tags, el array completo es un reemplazo total al actualizar, y se devuelve en orden en cada lectura (vacío [] cuando no hay ninguno).

Campos personalizados frente a metadata

Tanto custom_fields como metadata llevan datos tuyos, pero sirven para propósitos distintos — no uses el que no toca.

Usa custom_fields para datos de negocio ordenados y tipados que el usuario ve en el documento. Usa metadata para un mapa desordenado clave→valor de datos de integración opacos (códigos de ERP, referencias de tu propia contabilidad) que nadie lee visualmente. Un documento puede llevar ambos.

custom_fieldsmetadata
FormaLista ordenada de {field, value}Mapa desordenado key → value
OrdenSe conservaNinguno
Límite≤ 50 entradas≤ 50 claves
Clavefield, 1–60 caracteresclave del mapa
Valorstring ≤ 500 caracteresstring ≤ 500 caracteres
IntenciónCampos de negocio que el usuario veDatos de integración opacos
RecursosLos seis recursos de documentoTodos los recursos

Los recursos maestros (clients, suppliers) no tienen custom_fields tipados — usa su metadata como almacén de campos personalizados sin tipar. Los products aceptan tags pero no custom_fields.

Ejemplos

import os, requests

base = 'https://api.factuarea.com/v1'
headers = {'Authorization': f"Bearer {os.environ['FACTUAREA_API_KEY']}"}

# Create an invoice with tags + custom_fields
resp = requests.post(f'{base}/invoices', headers=headers, json={
    'client_id': '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01',
    'series_id': '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02',
    'issued_on': '2026-05-15',
    'due_on': '2026-06-15',
    'tags': ['consultoria', 'cliente-vip'],
    'custom_fields': [
        {'field': 'centro_coste', 'value': 'CC-2026-001'},
        {'field': 'numero_pedido', 'value': 'PO-2026-0042'},
    ],
    'lines': [
        {'description': 'Monthly service', 'quantity': 1,
         'unit_price': 99.00, 'tax_rate_id': '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03'},
    ],
})
resp.raise_for_status()

# List invoices tagged "cliente-vip" OR "moroso"
rows = requests.get(f'{base}/invoices', headers=headers,
                    params={'tags[in]': 'cliente-vip,moroso'}).json()['data']
print(len(rows), 'matching invoices')
const base = 'https://api.factuarea.com/v1';
const headers = {
  Authorization: `Bearer ${process.env.FACTUAREA_API_KEY}`,
  'Content-Type': 'application/json',
};

// Create an invoice with tags + custom_fields
await fetch(`${base}/invoices`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    client_id: '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01',
    series_id: '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02',
    issued_on: '2026-05-15',
    due_on: '2026-06-15',
    tags: ['consultoria', 'cliente-vip'],
    custom_fields: [
      { field: 'centro_coste', value: 'CC-2026-001' },
      { field: 'numero_pedido', value: 'PO-2026-0042' },
    ],
    lines: [
      { description: 'Monthly service', quantity: 1,
        unit_price: 99.0, tax_rate_id: '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03' },
    ],
  }),
});

// List invoices tagged "cliente-vip" OR "moroso"
const url = new URL(`${base}/invoices`);
url.searchParams.set('tags[in]', 'cliente-vip,moroso');
const { data } = await fetch(url, { headers }).then((r) => r.json());
console.log(data.length, 'matching invoices');
# Create an invoice with tags + custom_fields
curl -s -X POST https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
    "series_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02",
    "issued_on": "2026-05-15",
    "due_on": "2026-06-15",
    "tags": ["consultoria", "cliente-vip"],
    "custom_fields": [
      { "field": "centro_coste", "value": "CC-2026-001" },
      { "field": "numero_pedido", "value": "PO-2026-0042" }
    ],
    "lines": [
      { "description": "Monthly service", "quantity": 1, "unit_price": 99.00, "tax_rate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03" }
    ]
  }' | jq '{id, tags, custom_fields}'

# List invoices tagged "cliente-vip" OR "moroso"
curl -s -G https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "tags[in]=cliente-vip,moroso" | jq '.data | length'

En esta página