Contactos
Un contacto representa una persona física o empresa con la que mantienes una relación contable: clientes a los que facturas, proveedores de los que recibes gastos y empleados a los que pagas nóminas.
En FacturaDirecta un mismo contacto puede actuar simultáneamente como cliente, proveedor y empleado. No son tipos excluyentes: son facetas que se activan al asociar al contacto la cuenta contable correspondiente.
Facetas: cliente, proveedor, empleado
Las facetas se controlan a través del objeto content.main.accounts:
accounts.client→ habilita al contacto como cliente (cuenta 430* por defecto).accounts.provider→ habilita al contacto como proveedor (cuenta 400/410*).accounts.employee→ habilita al contacto como empleado (cuenta 465*).
Cada faceta principal tiene su contraparte de anticipos
(clientCredit, providerCredit, employeeCredit). Si indicas solo la cuenta
principal con el prefijo esperado, FacturaDirecta autocompleta la de anticipos
con el valor por defecto de la empresa.
Comportamiento por defecto al crear un contacto. Si no envías accounts,
el contacto se crea como cliente con las cuentas contables por defecto. Para
crear un proveedor o un empleado debes indicarlo explícitamente.
Para listar contactos por faceta, usa los filtros isClient, isProvider o
isEmployee en GET /contacts. Devuelven los contactos que tienen la cuenta
correspondiente asignada.
Cuando el contacto actúa como cliente, content.main.owner identifica al
usuario responsable de esa cartera. Se usa con roles personalizados para
limitar la visibilidad a clientes asignados. Si creas el contacto con
OAuth y no envías owner, la API asigna como responsable al usuario
autenticado; con apiKey se deja vacío salvo que lo envíes en el body.
Permisos por faceta
Con una aplicación conectada o un rol personalizado, los permisos de clientes, proveedores y empleados se evalúan por separado:
- Los listados y las consultas solo devuelven contactos con al menos una faceta que la credencial pueda leer.
- Crear, actualizar, etiquetar o borrar exige permiso de escritura sobre todas las facetas del contacto.
- Al actualizar también se comprueban las facetas anteriores. Quitar una cuenta de proveedor, por ejemplo, sigue requiriendo permiso para modificar proveedores.
Si falta un permiso, la respuesta es 403. Una aplicación conectada recibe
code: "connection_permission_insufficient" y manageUrl cuando el usuario
puede ampliar la conexión. Si la limitación procede del rol, el código es
user_role_insufficient. Consulta Errores y validaciones.
Campos personalizados
content.main.customFields es un mapa de valores indexado por el ID estable
cfi_<uuid v4> de cada campo personalizado. Las claves
deben corresponder a definiciones existentes. También se aceptan definiciones
borradas para conservar contactos históricos; un ID desconocido o con formato
incorrecto produce 400 Bad Request.
Enlace a la aplicación
Las respuestas que devuelven un contacto incluyen webUrl junto al resto de
los datos. En los listados, cada elemento de items lleva su propio enlace.
webUrl abre la ficha del elemento en la aplicación web de FacturaDirecta.
Puedes mostrarlo como enlace en tu integración sin construir rutas internas.
El navegador pedirá iniciar sesión con un usuario que tenga acceso a la
empresa. Es un campo opcional y no es un endpoint de la API: trátalo como una
URL para el usuario, no como una URL a la que enviar $ACCESS_TOKEN.
Operaciones
- Lista de contactos
- Crear contacto
- Obtener un contacto
- Actualizar contacto
- Borrar contacto
- Actualizar etiquetas de contacto
Lista de contactos
GET /{companyId}/contacts devuelve los contactos de la empresa indicada,
paginados.
Parámetros de consulta:
search— búsqueda libre por nombre, apellidos o nombre comercial.fiscalId— identificador fiscal exacto (sin separadores).vatEU— identificador IVA intracomunitario.externalId— referencia externa asignada al importar.phone— teléfono exacto.country— código país ISO 3166-1 Alpha-2 (ES,FR…).isClient,isProvider,isEmployee— facetas (ver sección superior).allTheseTags,anyOfTheseTags— filtros por etiquetas concretas.hasTags—truedevuelve solo contactos con al menos una etiqueta yfalse, solo contactos sin etiquetas.sortBy— campo de orden.related— recursos relacionados a expandir.
Ver Paginación para los parámetros comunes
(offset, limit, hasMore).
Ejemplo de respuesta JSON
{
"pagination": { "offset": 0, "limit": 50, "total": 124 },
"items": [
{
"content": {
"type": "contact",
"uuid": "con_2c4f8e21-7b3a-4d9c-9e1f-a8b7c6d5e4f3",
"main": {
"title": "Acme Diseño",
"name": "Acme Diseño S.L.",
"email": "facturacion@acme.es",
"phone": "+34 932 000 000",
"address": "Carrer Aribau 123",
"zipcode": "08036",
"city": "Barcelona",
"region": "Barcelona",
"country": "ES",
"fiscalId": "B12345674",
"fiscalIdCountry": "ES",
"accounts": {
"client": "4300001",
"clientCredit": "4380001"
},
"currency": "EUR"
}
},
"tags": ["agencia", "barcelona"],
"creationDate": "2025-11-14T10:22:31.000Z",
"modificationDate": "2026-04-02T08:15:00.000Z"
}
]
}Copy as cURL
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://app.facturadirecta.com/api/$COMPANY_ID/contacts?isClient=true&country=ES&limit=50"Crear contacto
POST /{companyId}/contacts crea un contacto en la empresa indicada.
Parámetros del body:
content.type— siempre"contact".content.main— campos del contacto.tags(opcional) — lista de etiquetas a asociar.
Notas:
- Si omites
accounts, el contacto se crea como cliente con las cuentas por defecto de la empresa. fiscalIdse valida cuandofiscalIdCountryesES(ocountryesESsi no se indicafiscalIdCountry).language(opcional) es el idioma en que se imprimen y se envían los documentos del contacto, como código ISO 639-1 (es,ca,en…). Las facturas, presupuestos y demás documentos nuevos lo toman al asignarles el contacto. Sin valor, cada documento sale en el idioma base de su plantilla.- La respuesta es el contacto creado completo, en el mismo formato que Obtener un contacto.
Límites del plan. Los planes limitan cuántos clientes y cuántos empleados puede tener la empresa a la vez:
| Plan | Clientes | Empleados |
|---|---|---|
| Gratis | 10 | 1 |
| Bronce | 100 | 2 |
| Plata | Sin límite | 5 |
| Oro | Sin límite | 20 |
| Diamante | Sin límite | Sin límite |
Los límites solo bloquean crear: los contactos que ya existen siguen
funcionando aunque la empresa baje de plan, y borrar uno libera hueco. Al
superarlos, la respuesta es 403 con el código plan_limit_exceeded (ver
Errores). Cuentan solo los contactos con la faceta
correspondiente: un proveedor no consume cupo de cliente ni de empleado.
Ejemplo de request JSON
{
"content": {
"type": "contact",
"main": {
"name": "Acme Diseño S.L.",
"email": "facturacion@acme.es",
"fiscalId": "B12345674",
"address": "Carrer Aribau 123",
"zipcode": "08036",
"city": "Barcelona",
"country": "ES"
}
},
"tags": ["agencia", "barcelona"]
}Copy as cURL
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
-d '{
"content": {
"type": "contact",
"main": {
"name": "Acme Diseño S.L.",
"email": "facturacion@acme.es",
"fiscalId": "B12345674",
"address": "Carrer Aribau 123",
"zipcode": "08036",
"city": "Barcelona",
"country": "ES"
}
},
"tags": ["agencia", "barcelona"]
}' \
"https://app.facturadirecta.com/api/$COMPANY_ID/contacts"Obtener un contacto
GET /{companyId}/contacts/{id} devuelve un contacto por su ID.
Parámetros:
related(opcional) — recursos relacionados a expandir, por ejemploinvoices,bills.
Ejemplo de respuesta JSON
{
"content": {
"type": "contact",
"uuid": "con_2c4f8e21-7b3a-4d9c-9e1f-a8b7c6d5e4f3",
"main": {
"title": "Acme Diseño",
"name": "Acme Diseño S.L.",
"email": "facturacion@acme.es",
"phone": "+34 932 000 000",
"address": "Carrer Aribau 123",
"zipcode": "08036",
"city": "Barcelona",
"region": "Barcelona",
"country": "ES",
"fiscalId": "B12345674",
"fiscalIdCountry": "ES",
"accounts": {
"client": "4300001",
"clientCredit": "4380001"
},
"currency": "EUR"
}
},
"tags": ["agencia", "barcelona"],
"creationDate": "2025-11-14T10:22:31.000Z",
"modificationDate": "2026-04-02T08:15:00.000Z",
"related": {}
}Copy as cURL
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://app.facturadirecta.com/api/$COMPANY_ID/contacts/con_2c4f8e21-7b3a-4d9c-9e1f-a8b7c6d5e4f3"Actualizar contacto
PUT /{companyId}/contacts/{id} sustituye el contenido completo del
contacto. No es un PATCH: lo que no envíes, se borra.
Parámetros del body: mismo formato que Crear contacto.
Para añadir una faceta a un contacto existente (por ejemplo, convertir un
cliente en cliente-y-proveedor) reenvía el contacto completo con las cuentas
adicionales en accounts.
Respuesta: el contacto actualizado completo, en el mismo formato que Obtener un contacto.
Ejemplo de request JSON
{
"content": {
"type": "contact",
"main": {
"name": "Acme Diseño S.L.",
"email": "facturacion@acme.es",
"phone": "+34 932 000 000",
"fiscalId": "B12345674",
"address": "Carrer Aribau 123",
"zipcode": "08036",
"city": "Barcelona",
"country": "ES",
"accounts": {
"client": "4300001",
"clientCredit": "4380001",
"provider": "4100001",
"providerCredit": "4070001"
}
}
}
}Copy as cURL
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -X PUT \
-d '{
"content": {
"type": "contact",
"main": {
"name": "Acme Diseño S.L.",
"email": "facturacion@acme.es",
"phone": "+34 932 000 000",
"fiscalId": "B12345674",
"address": "Carrer Aribau 123",
"zipcode": "08036",
"city": "Barcelona",
"country": "ES",
"accounts": {
"client": "4300001",
"clientCredit": "4380001",
"provider": "4100001",
"providerCredit": "4070001"
}
}
}
}' \
"https://app.facturadirecta.com/api/$COMPANY_ID/contacts/con_2c4f8e21-7b3a-4d9c-9e1f-a8b7c6d5e4f3"Borrar contacto
DELETE /{companyId}/contacts/{id} elimina un contacto de la empresa.
Restricciones. Si el contacto tiene documentos asociados (facturas,
gastos, nóminas), la API rechaza el borrado con 409 Conflict y un mensaje
indicando el motivo. En ese caso, reasigna sus documentos a otro contacto antes de
borrarlo.
Respuesta: { "result": true }.
Copy as cURL
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -X DELETE \
"https://app.facturadirecta.com/api/$COMPANY_ID/contacts/con_2c4f8e21-7b3a-4d9c-9e1f-a8b7c6d5e4f3"Actualizar etiquetas de contacto
PUT /{companyId}/contacts/{id}/tags reemplaza el conjunto de etiquetas de un
contacto sin tocar el resto del contenido. Útil cuando solo quieres reclasificar
sin reenviar la estructura completa del contacto.
Parámetros del body:
tags— lista completa de etiquetas (sustituye, no añade).
Ejemplo de request JSON
{
"tags": ["agencia", "premium", "barcelona"]
}Copy as cURL
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -X PUT \
-d '{"tags":["agencia","premium","barcelona"]}' \
"https://app.facturadirecta.com/api/$COMPANY_ID/contacts/con_2c4f8e21-7b3a-4d9c-9e1f-a8b7c6d5e4f3/tags"Identificador fiscal
fiscalId es obligatorio para emitir facturas a clientes españoles. Se valida
formato (NIF, CIF o NIE) y se almacena sin separadores ni espacios. Si no
indicas fiscalIdCountry, se asume el mismo país que la dirección fiscal del
contacto.
Para contactos extracomunitarios sin identificador fiscal, deja el campo vacío
e informa el nombre y el domicilio completos. Si TicketBAI no está activo, sus
facturas se emiten por defecto como facturas completas sin identificación del
destinatario (art. 6.1.d del RD 1619/2012), no como simplificadas. Con VeriFactu
se registran como F2. Para contactos intracomunitarios, usa el campo vatEU
(formato con prefijo de país: ESB12345674).
Versiones
GET /{companyId}/contacts/{id}/versions lista las versiones de el contacto: su alta, cada
modificación, su eliminación y su recuperación, con quién y cuándo, aunque se haya eliminado.
GET /{companyId}/contacts/{id}/versions/{versionId} devuelve la copia de una versión, en el
mismo formato que GET /{companyId}/contacts/{id}, y los cambios respecto a la versión anterior.
Sirven para ver qué se cambió y recuperar datos: ver
Versiones de documentos.
Errores comunes
400 ValidationError—fiscalIdcon formato inválido para el país indicado.403con códigoplan_limit_exceeded— se ha alcanzado el máximo de clientes o de empleados del plan.403con códigoconnection_permission_insufficientouser_role_insufficient— falta permiso sobre alguna faceta del contacto.409 Conflict— borrado de contacto con documentos asociados.409 Conflict—fiscalIdduplicado en la empresa.
Ver Errores y validaciones para el formato general de respuestas de error.
Endpoints
| Método | Path | operationId | Scopes | Descripción |
|---|---|---|---|---|
| GET | /{companyId}/contacts | getContacts | contacts:read | Lista de contactos |
| GET | /{companyId}/contacts/{id} | getContact | contacts:read | Obtener un contacto |
| GET | /{companyId}/contacts/{id}/versions | getContactVersions | contacts:read | Versiones de el contacto |
| GET | /{companyId}/contacts/{id}/versions/{versionId} | getContactVersion | contacts:read | Versión de el contacto |
| POST | /{companyId}/contacts | createContact | contacts:write | Crear contacto |
| PUT | /{companyId}/contacts/{id} | updateContact | contacts:write | Actualizar contacto |
| PUT | /{companyId}/contacts/{id}/tags | updateContactTags | contacts:write | Actualizar etiquetas de contacto |
| DELETE | /{companyId}/contacts/{id} | deleteContact | contacts:write | Borrar contacto |
Scopes
contacts:read— Lectura de contactos.contacts:write— Modificación de contactos.