PRO INTEGRA360 · DESARROLLADORES

API e integraciones.

Consulta la referencia técnica para conectar herramientas con el entorno de gestión de tu taller.

RESTJSONOpenAPI 3.0Referencia v1.0.20

Acceso y autenticación

Contacta con info@prointegra360.com para confirmar el acceso de tu taller. La documentación de la plataforma base requiere un client_id y un client_secret para obtener un token. Conserva estas credenciales en tu servidor, nunca en el código público de una web.

Servidor de la referencia técnica:

https://api.tallergp.com

Las operaciones indican su esquema de autenticación. El esquema general utiliza esta cabecera:

Authorization: Bearer ACCESS_TOKEN

Esta página permite consultar la documentación. No envía peticiones a la API ni solicita credenciales.

Clientes

GET/customersObtiene todos los clientes del taller con paginación.
Devuelve un listado paginado de clientes asociados al taller autenticado. Soporta paginación y ordenación mediante parámetros de consulta

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer"
}
per_pagequeryNoNúmero de elementos por página
{
  "type": "integer"
}
customer_numberqueryNoNúmero de cliente
{
  "type": "string"
}
emailqueryNoFiltrar por email (busqueda parcial).
{
  "type": "string"
}
phonequeryNoTeléfono del cliente
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · List of customers
{
  "description": "List of customers",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Respuesta paginada para la lista de clientes.",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Representa un cliente en un listado.",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Identificador único del cliente."
                },
                "customer_number": {
                  "type": "string",
                  "description": "Número de cliente."
                },
                "name": {
                  "type": "string",
                  "description": "Nombre del cliente."
                },
                "lastname": {
                  "type": "string",
                  "description": "Primer apellido del cliente."
                },
                "surname": {
                  "type": "string",
                  "description": "Segundo apellido del cliente."
                },
                "client_type": {
                  "type": "string",
                  "description": "Tipo de cliente (e.g., '1' para particular, '2' para empresa)."
                },
                "vat_number": {
                  "type": "string",
                  "description": "Número de Identificación Fiscal (NIF/CIF) del cliente."
                },
                "address": {
                  "type": "string",
                  "description": "Dirección del cliente."
                },
                "zip_code": {
                  "type": "string",
                  "description": "Código postal."
                },
                "location": {
                  "type": "string",
                  "description": "Localidad."
                },
                "province": {
                  "type": "string",
                  "description": "Provincia."
                },
                "country_num": {
                  "type": "string",
                  "description": "Código de país."
                },
                "phone": {
                  "type": "string",
                  "description": "Teléfono fijo."
                },
                "mobile": {
                  "type": "string",
                  "description": "Teléfono móvil."
                },
                "fax": {
                  "type": "string",
                  "description": "Fax."
                },
                "mail": {
                  "type": "string",
                  "format": "email",
                  "description": "Correo electrónico."
                },
                "web": {
                  "type": "string",
                  "format": "uri",
                  "description": "Página web."
                },
                "birthdate": {
                  "type": "string",
                  "description": "Fecha de nacimiento (DD/MM/YY o vacía)."
                },
                "blocked": {
                  "type": "string",
                  "description": "Indica si el cliente está bloqueado ('0' no bloqueado, '1' bloqueado)."
                },
                "account_ledger": {
                  "type": "string",
                  "description": "Cuenta contable."
                }
              },
              "example": {
                "id": "XXXXXXXXXXXXX",
                "customer_number": "0000000001",
                "name": "Cliente 0000000001",
                "lastname": "",
                "surname": "",
                "client_type": "1",
                "vat_number": "",
                "address": "",
                "zip_code": "006",
                "location": "MALAGA",
                "province": "",
                "country_num": "",
                "phone": "",
                "mobile": "",
                "fax": "",
                "mail": "",
                "web": "",
                "birthdate": "",
                "blocked": "0",
                "account_ledger": ""
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · Failed to generate customers
{
  "description": "Failed to generate customers",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
POST/customersCrea un nuevo cliente en el sistema
Registra un nuevo cliente asociado al taller del token de autenticación. ## Campos requeridos | Campo | Tipo | Descripción | |-------|------|-------------| | `name` | string | Nombre del cliente | | `customer_number` | string | Identificador externo | ## Campos opcionales principales | Campo | Tipo | Descripción | |-------|------|-------------| | `lastname` | string | Primer apellido | | `surname` | string | Segundo apellido | | `phone` | string | Teléfono fijo | | `mobile` | string | Teléfono móvil | | `mail` | string | Correo electrónico | | `vat_number` | string | NIF/CIF | | `address` | string | Dirección | | `zip_code` | string | Código postal | | `location` | string | Población | | `province` | string | Provincia | ## Campos opcionales comerciales | Campo | Tipo | Descripción | |-------|------|-------------| | `customer_number` | string | Número de cliente (manual) | | `alias` | string | Alias o nombre comercial | | `observations` | string | Observaciones | | `parts_discount` | float | Descuento en piezas (%) | | `labor_discount` | float | Descuento en mano de obra (%) | | `general_discount` | float | Descuento general (%) | | `blocked` | boolean | Cliente bloqueado | ## Campos auto-generados - `id` — Identificador único del cliente (UNIQUE_ID) - Asociación al taller del token de autenticación

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del cliente",
            "example": "Juan"
          },
          "lastname": {
            "type": "string",
            "description": "Primer apellido",
            "example": "Pérez"
          },
          "surname": {
            "type": "string",
            "description": "Segundo apellido",
            "example": "García"
          },
          "customer_number": {
            "type": "string",
            "description": "Número de cliente único",
            "example": "CLI001"
          },
          "vat_number": {
            "type": "string",
            "description": "NIF/CIF del cliente",
            "example": "12345678A"
          },
          "phone": {
            "type": "string",
            "description": "Teléfono fijo",
            "example": "961234567"
          },
          "mobile": {
            "type": "string",
            "description": "Teléfono móvil",
            "example": "612345678"
          },
          "mail": {
            "type": "string",
            "description": "Correo electrónico",
            "example": "juan@example.com"
          },
          "address": {
            "type": "string",
            "description": "Dirección postal",
            "example": "Calle Mayor 1"
          },
          "zip_code": {
            "type": "string",
            "description": "Código postal",
            "example": "46001"
          },
          "location": {
            "type": "string",
            "description": "Población",
            "example": "Valencia"
          },
          "province": {
            "type": "string",
            "description": "Provincia",
            "example": "Valencia"
          },
          "alias": {
            "type": "string",
            "description": "Alias o nombre comercial"
          },
          "observations": {
            "type": "string",
            "description": "Observaciones"
          },
          "parts_discount": {
            "type": "number",
            "description": "Descuento en piezas (%)",
            "example": 10
          },
          "labor_discount": {
            "type": "number",
            "description": "Descuento en mano de obra (%)",
            "example": 5
          },
          "general_discount": {
            "type": "number",
            "description": "Descuento general (%)",
            "example": 0
          },
          "blocked": {
            "type": "boolean",
            "description": "Cliente bloqueado",
            "example": false
          }
        },
        "required": [
          "name"
        ]
      },
      "example": {
        "name": "Juan",
        "customer_number": "CLI001",
        "lastname": "Pérez",
        "surname": "García",
        "phone": "961234567",
        "mobile": "612345678",
        "mail": "juan@example.com",
        "vat_number": "12345678A",
        "address": "Calle Mayor 1",
        "zip_code": "46001",
        "location": "Valencia",
        "province": "Valencia"
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Respuesta exitosa
{
  "description": "Respuesta exitosa"
}
GET/customers/{client_id}Obtener información del cliente.
Devuelve el detalle completo de un cliente del taller autenticado identificado por su client_id. Si el cliente no existe o no pertenece al taller, se devolverá un error 404

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
client_idpathSíIdentificador único del cliente.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Datos del cliente obtenidos con éxito.
{
  "description": "Datos del cliente obtenidos con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Representa el detalle completo de un cliente.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador único del cliente."
          },
          "customer_number": {
            "type": "string",
            "description": "Número de cliente."
          },
          "name": {
            "type": "string",
            "description": "Nombre del cliente."
          },
          "lastname": {
            "type": "string",
            "description": "Primer apellido del cliente."
          },
          "surname": {
            "type": "string",
            "description": "Segundo apellido del cliente."
          },
          "client_type": {
            "type": "string",
            "description": "Tipo de cliente."
          },
          "vat_number": {
            "type": "string",
            "description": "Número de Identificación Fiscal (NIF/CIF)."
          },
          "address": {
            "type": "string",
            "description": "Dirección del cliente."
          },
          "zip_code": {
            "type": "string",
            "description": "Código postal."
          },
          "location": {
            "type": "string",
            "description": "Localidad."
          },
          "province": {
            "type": "string",
            "description": "Provincia."
          },
          "country_num": {
            "type": "string",
            "description": "Código de país."
          },
          "phone": {
            "type": "string",
            "description": "Teléfono fijo."
          },
          "mobile": {
            "type": "string",
            "description": "Teléfono móvil."
          },
          "fax": {
            "type": "string",
            "description": "Fax."
          },
          "mail": {
            "type": "string",
            "format": "email",
            "description": "Correo electrónico."
          },
          "web": {
            "type": "string",
            "format": "uri",
            "description": "Página web."
          },
          "birthdate": {
            "type": "string",
            "description": "Fecha de nacimiento (DD/MM/YY o vacía)."
          },
          "blocked": {
            "type": "string",
            "description": "Indica si el cliente está bloqueado ('0' no bloqueado, '1' bloqueado)."
          },
          "account_ledger": {
            "type": "string",
            "description": "Cuenta contable."
          },
          "promos_disabled": {
            "type": "string",
            "description": "Promociones deshabilitadas ('0' habilitado, '1' deshabilitado)."
          },
          "repairs_enabled": {
            "type": "string",
            "description": "Reparaciones habilitadas ('0' deshabilitado, '1' habilitado)."
          },
          "appointments_enabled": {
            "type": "string",
            "description": "Citas habilitadas ('0' deshabilitado, '1' habilitado)."
          },
          "push_disabled": {
            "type": "string",
            "description": "Notificaciones push deshabilitadas ('0' habilitado, '1' deshabilitado)."
          },
          "payment_type": {
            "type": "string",
            "description": "Tipo de pago preferido por el cliente (si aplica)."
          },
          "applied_fee": {
            "type": "string",
            "description": "Tarifa aplicada."
          },
          "app_installed": {
            "type": "string",
            "description": "Estado de instalación de la app (e.g., 'both')."
          },
          "app_installed_date": {
            "type": "string",
            "description": "Fecha de instalación de la app (DD/MM/YY)."
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Representa un documento embebido en la información del cliente.",
              "properties": {
                "document_type": {
                  "type": "string",
                  "description": "Tipo de documento.",
                  "example": "1"
                },
                "file_name": {
                  "type": "string",
                  "description": "Nombre del archivo.",
                  "example": "ampliacion APP.pdf"
                },
                "file_size": {
                  "type": "string",
                  "description": "Tamaño del archivo en bytes.",
                  "example": "211011"
                },
                "description": {
                  "type": "string",
                  "description": "Descripción del documento.",
                  "example": "observaciones pdf"
                },
                "title": {
                  "type": "string",
                  "description": "Título del documento.",
                  "example": "descripcion pdf"
                },
                "date": {
                  "type": "string",
                  "description": "Fecha del documento (DD/MM/YY).",
                  "example": "13/06/25"
                },
                "url": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL del documento.",
                  "example": "https://d3lfz47touix8b.cloudfront.net/XXX/clientes/XXXX.pdf"
                }
              },
              "example": {
                "document_type": "1",
                "file_name": "ampliacion APP.pdf",
                "file_size": "211011",
                "description": "observaciones pdf",
                "title": "descripcion pdf",
                "date": "13/06/25",
                "url": "https://d3lfz47touix8b.cloudfront.net/1004/clientes/XXXXXXXXXXXXX.pdf"
              }
            },
            "description": "Lista de documentos asociados al cliente."
          },
          "contacts": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Representa un contacto asociado a un cliente.",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Nombre del contacto.",
                  "example": "CONTACTO 1"
                },
                "position": {
                  "type": "string",
                  "description": "Cargo del contacto.",
                  "example": "jefe"
                },
                "phone": {
                  "type": "string",
                  "description": "Teléfono del contacto.",
                  "example": "666888777"
                },
                "schedule": {
                  "type": "string",
                  "description": "Horario del contacto.",
                  "example": "19:00"
                },
                "email": {
                  "type": "string",
                  "format": "email",
                  "description": "Email del contacto.",
                  "example": "email@contacto.com"
                },
                "fax": {
                  "type": "string",
                  "description": "Fax del contacto.",
                  "example": "999666555"
                }
              },
              "example": {
                "name": "CONTACTO 1",
                "position": "jefe",
                "phone": "666888777",
                "schedule": "19:00",
                "email": "email@contacto.com",
                "fax": "999666555"
              }
            },
            "description": "Lista de contactos del cliente."
          }
        },
        "example": {
          "id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
          "customer_number": "0000001041",
          "name": "NOMBRE",
          "lastname": "APELLIDO1",
          "surname": "APELLIDO2",
          "client_type": "1",
          "vat_number": "12345678Z",
          "address": "Ramón Casas 30º",
          "zip_code": "02008",
          "location": "ALBACETE",
          "province": "ALBACETE",
          "country_num": "",
          "phone": "666666666",
          "mobile": "666555666",
          "fax": "",
          "mail": "mail@host.com",
          "web": "",
          "birthdate": "",
          "blocked": "0",
          "account_ledger": "222333223",
          "promos_disabled": "1",
          "repairs_enabled": "0",
          "appointments_enabled": "0",
          "push_disabled": "0",
          "payment_type": "",
          "applied_fee": "1",
          "app_installed": "both",
          "app_installed_date": "17/06/25",
          "documents": [
            {
              "document_type": "1",
              "file_name": "ampliacion APP.pdf",
              "file_size": "211011",
              "description": "observaciones pdf",
              "title": "descripcion pdf",
              "date": "13/06/25",
              "url": "https://d3lfz47touix8b.cloudfront.net/1004/clientes/XXXXXXXXXXXXX.pdf"
            }
          ],
          "contacts": [
            {
              "name": "CONTACTO 1",
              "position": "jefe",
              "phone": "666888777",
              "schedule": "19:00",
              "email": "email@contacto.com",
              "fax": "999666555"
            }
          ]
        }
      }
    }
  }
}
HTTP 400 · Error en los parámetros de la solicitud.
{
  "description": "Error en los parámetros de la solicitud.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Descripción del error."
          }
        }
      }
    }
  }
}
HTTP 404 · Cliente no encontrado.
{
  "description": "Cliente no encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "status": {
            "description": "codigo error",
            "type": "number"
          },
          "message": {
            "description": "Customer not found",
            "type": "string"
          }
        },
        "type": "object"
      }
    }
  }
}
PUT/customers/{client_id}Actualiza un cliente existente
Actualiza los datos de un cliente existente asociado al taller del token de autenticación. ## Validaciones - **Número de cliente único**: No puede existir otro cliente con el mismo número en el taller - **CIF/NIF único**: No puede existir otro cliente con el mismo CIF/NIF en el taller ## Campos actualizables principales | Campo | Tipo | Descripción | |-------|------|-------------| | `name` | string | Nombre del cliente | | `lastname` | string | Primer apellido | | `surname` | string | Segundo apellido | | `customer_number` | string | Número de cliente | | `vat_number` | string | NIF/CIF | ## Campos de contacto | Campo | Tipo | Descripción | |-------|------|-------------| | `phone` | string | Teléfono fijo | | `mobile` | string | Teléfono móvil | | `mail` | string | Correo electrónico | | `address` | string | Dirección | | `zip_code` | string | Código postal | | `location` | string | Población | | `province` | string | Provincia | ## Campos comerciales | Campo | Tipo | Descripción | |-------|------|-------------| | `alias` | string | Alias o nombre comercial | | `observations` | string | Observaciones | | `parts_discount` | float | Descuento en piezas (%) | | `labor_discount` | float | Descuento en mano de obra (%) | | `general_discount` | float | Descuento general (%) | | `blocked` | boolean | Cliente bloqueado | ## Notas - Solo se actualizan los campos enviados en el body - La comparación de número/CIF se hace normalizada (mayúsculas, sin espacios ni caracteres especiales)

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
client_idpathSí
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": false,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del cliente",
            "example": "Juan"
          },
          "lastname": {
            "type": "string",
            "description": "Primer apellido",
            "example": "Pérez"
          },
          "surname": {
            "type": "string",
            "description": "Segundo apellido",
            "example": "García"
          },
          "customer_number": {
            "type": "string",
            "description": "Número de cliente único",
            "example": "CLI001"
          },
          "vat_number": {
            "type": "string",
            "description": "NIF/CIF del cliente",
            "example": "12345678A"
          },
          "phone": {
            "type": "string",
            "description": "Teléfono fijo",
            "example": "961234567"
          },
          "mobile": {
            "type": "string",
            "description": "Teléfono móvil",
            "example": "612345678"
          },
          "mail": {
            "type": "string",
            "description": "Correo electrónico",
            "example": "juan@example.com"
          },
          "address": {
            "type": "string",
            "description": "Dirección postal",
            "example": "Calle Mayor 1"
          },
          "zip_code": {
            "type": "string",
            "description": "Código postal",
            "example": "46001"
          },
          "location": {
            "type": "string",
            "description": "Población",
            "example": "Valencia"
          },
          "province": {
            "type": "string",
            "description": "Provincia",
            "example": "Valencia"
          },
          "alias": {
            "type": "string",
            "description": "Alias o nombre comercial"
          },
          "observations": {
            "type": "string",
            "description": "Observaciones"
          },
          "parts_discount": {
            "type": "number",
            "description": "Descuento en piezas (%)",
            "example": 10
          },
          "labor_discount": {
            "type": "number",
            "description": "Descuento en mano de obra (%)",
            "example": 5
          },
          "general_discount": {
            "type": "number",
            "description": "Descuento general (%)",
            "example": 0
          },
          "blocked": {
            "type": "boolean",
            "description": "Cliente bloqueado",
            "example": false
          }
        },
        "required": [
          "name"
        ]
      },
      "example": {
        "name": "Juan Actualizado",
        "mobile": "622345678",
        "mail": "juan.nuevo@example.com",
        "observations": "Cliente preferente"
      }
    }
  }
}

Respuestas documentadas

HTTP 200 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 404 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
GET/customers/{client_id}/vehiclesObtener los vehículos de un cliente
Devuelve el listado paginado de vehículos asociados a un cliente del taller autenticado identificado por su client_id.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoElementos por página
{
  "type": "integer",
  "default": 10
}
client_idpathSíIdentificador único del cliente.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Datos obtenidos con éxito.
{
  "description": "Datos obtenidos con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Vehiculo en vista de lista.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "plate": {
                  "type": "string"
                },
                "vin": {
                  "type": "string"
                },
                "color": {
                  "type": "string",
                  "nullable": true
                },
                "kms": {
                  "type": "string",
                  "nullable": true
                },
                "branch": {
                  "type": "string",
                  "description": "Marca."
                },
                "model": {
                  "type": "string",
                  "nullable": true
                },
                "next_itv": {
                  "type": "string",
                  "nullable": true
                },
                "client_id": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Error en los parámetros de la solicitud.
{
  "description": "Error en los parámetros de la solicitud.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Descripción del error."
          }
        }
      }
    }
  }
}
HTTP 404 · Cliente no encontrado.
{
  "description": "Cliente no encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "status": {
            "description": "codigo error",
            "type": "number"
          },
          "message": {
            "description": "Customer not found",
            "type": "string"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/customers/{client_id}/vehicles/{vehicle_id}Obtener los vehículos de un cliente
Devuelve el detalle de un vehículo asociado a un cliente del taller autenticado identificado por su client_id y vehicle_id. Si el cliente o el vehículo no existen, o no pertenecen al taller autenticado, se devolverá un error 404.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
client_idpathSíIdentificador único del cliente.
{
  "type": "string"
}
vehicle_idpathSíIdentificador único del vehículo
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Datos del vehiculo obtenidos con éxito.
{
  "description": "Datos del vehiculo obtenidos con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle de vehiculo de un cliente.",
        "properties": {
          "id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "vin": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "kms": {
            "type": "string",
            "nullable": true
          },
          "branch": {
            "type": "string"
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "reg_date": {
            "type": "string",
            "nullable": true
          },
          "version": {
            "type": "string",
            "nullable": true
          },
          "model_year": {
            "type": "string",
            "nullable": true
          },
          "kw": {
            "type": "string",
            "nullable": true
          },
          "cv": {
            "type": "string",
            "nullable": true
          },
          "num_engine": {
            "type": "string",
            "nullable": true
          },
          "displacement": {
            "type": "string",
            "nullable": true
          },
          "next_itv": {
            "type": "string",
            "nullable": true
          },
          "next_services": {
            "type": "string"
          },
          "past_services": {
            "type": "string"
          },
          "documents": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 · Error en los parámetros de la solicitud.
{
  "description": "Error en los parámetros de la solicitud.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Descripción del error."
          }
        }
      }
    }
  }
}
HTTP 404 · Cliente no encontrado.
{
  "description": "Cliente no encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "status": {
            "description": "codigo error",
            "type": "number"
          },
          "message": {
            "description": "Customer not found",
            "type": "string"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/vehiclesListado de vehículos del taller
Devuelve un listado paginado de vehículos del taller autenticado. --- ### Parámetros de query | Parámetro | Tipo | Descripción | |----------|------|-------------| | `page` | integer | Número de página | | `per_page` | integer | Número de elementos por página | | `plate` | string | Matrícula del vehículo | | `vin` | string | Número de bastidor del vehículo (VIN) | --- ### Datos devueltos | Campo | Tipo | Descripción | |------|------|-------------| | `current_page` | integer | Página actual | | `per_page` | integer | Elementos por página | | `total` | integer | Total de vehículos | | `total_pages` | integer | Total de páginas | ### Listado de vehículos | Campo | Tipo | Descripción | |------|------|-------------| | `id` | string | Identificador único | | `plate` | string | Matrícula | | `vin` | string | Bastidor (VIN) | | `brand` | string | Marca | | `model` | string | Modelo | | `client_id` | string | ID del cliente asociado |

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer"
}
per_pagequeryNoNúmero de registros por página
{
  "type": "integer"
}
platequeryNoMatrícula del vehículo
{
  "type": "string"
}
vatqueryNoNúmero de bastidor del vehículo
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Respuesta exitosa
{
  "description": "Respuesta exitosa",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un vehiculo.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador unico del vehiculo."
          },
          "plate": {
            "type": "string",
            "description": "Matricula del vehiculo."
          },
          "vin": {
            "type": "string",
            "description": "Numero de bastidor (VIN)."
          },
          "color": {
            "type": "string",
            "nullable": true,
            "description": "Color del vehiculo."
          },
          "reg_date": {
            "type": "string",
            "nullable": true,
            "description": "Fecha de matriculacion (DD/MM/YYYY)."
          },
          "kms": {
            "type": "string",
            "nullable": true,
            "description": "Kilometraje actual."
          },
          "branch": {
            "type": "string",
            "description": "Marca del vehiculo."
          },
          "model": {
            "type": "string",
            "nullable": true,
            "description": "Modelo del vehiculo."
          },
          "version": {
            "type": "string",
            "nullable": true,
            "description": "Version del vehiculo."
          },
          "model_year": {
            "type": "string",
            "nullable": true,
            "description": "Ano del modelo."
          },
          "kw": {
            "type": "string",
            "nullable": true,
            "description": "Potencia en kilovatios."
          },
          "cv": {
            "type": "string",
            "nullable": true,
            "description": "Potencia en caballos de vapor."
          },
          "num_engine": {
            "type": "string",
            "nullable": true,
            "description": "Numero de motor."
          },
          "displacement": {
            "type": "string",
            "nullable": true,
            "description": "Cilindrada en cc."
          },
          "next_itv": {
            "type": "string",
            "nullable": true,
            "description": "Fecha de proxima ITV."
          },
          "next_services": {
            "type": "string",
            "description": "Proximas revisiones programadas."
          },
          "past_services": {
            "type": "string",
            "description": "Revisiones anteriores."
          },
          "documents": {
            "type": "string",
            "description": "Documentos asociados."
          },
          "client_id": {
            "type": "string",
            "description": "ID del cliente propietario."
          }
        },
        "required": [
          "id",
          "plate"
        ]
      }
    }
  }
}
POST/vehiclesCrea un nuevo vehículo asociado a un cliente
Registra un nuevo vehículo en el sistema, asociándolo a un cliente existente y al taller del token de autenticación. ## Campos requeridos | Campo | Tipo | Descripción | |-------|------|-------------| | `client_id` | string | Identificador único del cliente (UNIQUE_ID) | | `plate` | string | Matrícula del vehículo | ## Campos opcionales principales | Campo | Tipo | Descripción | |-------|------|-------------| | `vin` | string | Número de bastidor (VIN) | | `brand_id` | integer | ID de la marca | | `model_id` | integer | ID del modelo | | `version_id` | integer | ID de la versión | | `version_text` | string | Versión (texto libre) | | `color` | string | Color exterior | | `interior_color` | string | Color interior | | `kms` | string | Kilometraje actual | | `registration_date` | string | Fecha de matriculación (DD/MM/YYYY) | | `model_year` | integer | Año del modelo | ## Campos opcionales técnicos | Campo | Tipo | Descripción | |-------|------|-------------| | `fuel_type_id` | integer | ID del tipo de combustible | | `cv` | string | Potencia en CV | | `kw` | string | Potencia en kW | | `displacement` | string | Cilindrada | | `cylinders` | integer | Número de cilindros | | `engine_number` | string | Número de motor | | `engine_type` | string | Tipo de motor | | `oil_type` | string | Tipo de aceite | | `ktype` | string | Código KType (TecDoc) | | `environmental_label` | integer | Etiqueta medioambiental (0-4) | ## Campos opcionales de mantenimiento | Campo | Tipo | Descripción | |-------|------|-------------| | `next_itv_date` | string | Próxima fecha ITV (DD/MM/YYYY) | | `next_revision_date` | string | Próxima fecha revisión (DD/MM/YYYY) | | `next_revision_km` | integer | Próximos km para revisión | ## Campos opcionales adicionales | Campo | Tipo | Descripción | |-------|------|-------------| | `insurance_id` | integer | ID de la aseguradora | | `policy_number` | string | Número de póliza | | `is_fleet` | boolean | Vehículo de flota | | `observations` | string | Observaciones | ## Campos auto-generados - `id` — Identificador único del vehículo (UNIQUE_ID) - Asociación al taller del token de autenticación ## Ejemplo de petición ```json { "client_id": "7pser1d252xvpoob35lky6eo36peq9xm", "plate": "1234ABC", "vin": "WVWZZZ3CZWE123456", "brand_id": 342, "model_id": 1081890, "color": "Negro", "kms": "50000", "registration_date": "15/03/2022", "fuel_type_id": 2, "next_itv_date": "15/03/2026" }

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "description": "ID del cliente propietario",
            "example": "7pser1d252xvpoob35lky6eo36peq9xm"
          },
          "plate": {
            "type": "string",
            "description": "Matrícula del vehículo",
            "example": "1234ABC"
          },
          "vin": {
            "type": "string",
            "description": "Número de bastidor (VIN)",
            "example": "WVWZZZ3CZWE123456"
          },
          "brand_id": {
            "type": "integer",
            "description": "ID de la marca",
            "example": 342
          },
          "model_id": {
            "type": "integer",
            "description": "ID del modelo",
            "example": 1081890
          },
          "color": {
            "type": "string",
            "description": "Color del vehículo",
            "example": "Negro"
          },
          "kms": {
            "type": "string",
            "description": "Kilometraje actual",
            "example": "50000"
          },
          "registration_date": {
            "type": "string",
            "description": "Fecha de matriculación (DD/MM/YYYY)",
            "example": "15/03/2022"
          },
          "fuel_type_id": {
            "type": "integer",
            "description": "ID del tipo de combustible",
            "example": 2
          },
          "next_itv_date": {
            "type": "string",
            "description": "Próxima fecha ITV (DD/MM/YYYY)",
            "example": "15/03/2026"
          }
        },
        "required": [
          "plate"
        ]
      },
      "example": {
        "client_id": "7pser1d252xvpoob35lky6eo36peq9xm",
        "plate": "1234ABC",
        "vin": "WVWZZZ3CZWE123456",
        "brand_id": 342,
        "model_id": 1081890,
        "color": "Negro",
        "kms": "50000",
        "registration_date": "15/03/2022",
        "next_itv_date": "15/03/2026",
        "fuel_type_id": 2
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Respuesta exitosa
{
  "description": "Respuesta exitosa"
}
GET/vehicles/{vehicle_id}Get the details of a vehicle
Returns complete information about a vehicle by its unique identifier. ### Route parameters | Parameter | Type | Description | |-----------|------|-------------| | `vehicle_id` | string | Unique vehicle identifier (UNIQUE_ID) | ## Data returned ### Basic information | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique identifier | | `plate` | string | Registration | | `vin` | string | Frame (VIN) | | `brand` | string | Brand | | `model` | string | Model | | `client_id` | string | Associated Client ID | ### Technical information | Field | Type | Description | |-------|------|-------------| | `kms` | string | Mileage | | `registration_date` | string | Registration date | | `fuel_type` | string | Fuel type |

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
vehicle_idpathSí
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "vin": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 404 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
PUT/vehicles/{vehicle_id}Actualiza un vehículo existente
Actualiza los datos de un vehículo existente. ## Validaciones - **Matrícula única**: No puede existir otro vehículo con la misma matrícula en el taller - **Bastidor único**: No puede existir otro vehículo con el mismo bastidor en el taller - **Cliente válido**: Si se proporciona `client_id`, debe existir en el sistema ## Campos actualizables | Campo | Tipo | Descripción | |-------|------|-------------| | `client_id` | string | ID del cliente asociado | | `plate` | string | Matrícula del vehículo | | `vin` | string | Número de bastidor (VIN) | | `brand_id` | integer | ID de la marca | | `model_id` | integer | ID del modelo | | `color` | string | Color exterior | | `kms` | string | Kilometraje actual | | `registration_date` | string | Fecha de matriculación (DD/MM/YYYY) | | `fuel_type_id` | integer | ID del tipo de combustible | | `next_itv_date` | string | Próxima fecha ITV (DD/MM/YYYY) | ## Notas - Solo se actualizan los campos enviados en el body - La comparación de matrícula/bastidor se hace normalizada

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
vehicle_idpathSí
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": false,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "description": "ID del cliente propietario",
            "example": "7pser1d252xvpoob35lky6eo36peq9xm"
          },
          "plate": {
            "type": "string",
            "description": "Matrícula del vehículo",
            "example": "1234ABC"
          },
          "vin": {
            "type": "string",
            "description": "Número de bastidor (VIN)",
            "example": "WVWZZZ3CZWE123456"
          },
          "brand_id": {
            "type": "integer",
            "description": "ID de la marca",
            "example": 342
          },
          "model_id": {
            "type": "integer",
            "description": "ID del modelo",
            "example": 1081890
          },
          "color": {
            "type": "string",
            "description": "Color del vehículo",
            "example": "Negro"
          },
          "kms": {
            "type": "string",
            "description": "Kilometraje actual",
            "example": "50000"
          },
          "registration_date": {
            "type": "string",
            "description": "Fecha de matriculación (DD/MM/YYYY)",
            "example": "15/03/2022"
          },
          "fuel_type_id": {
            "type": "integer",
            "description": "ID del tipo de combustible",
            "example": 2
          },
          "next_itv_date": {
            "type": "string",
            "description": "Próxima fecha ITV (DD/MM/YYYY)",
            "example": "15/03/2026"
          }
        },
        "required": [
          "plate"
        ]
      },
      "example": {
        "plate": "5678XYZ",
        "color": "Blanco",
        "kms": "75000",
        "next_itv_date": "20/06/2027"
      }
    }
  }
}

Respuestas documentadas

HTTP 200 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 404 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
GET/dgt-lookup/{plate}Consulta oficial del vehiculo (DGT)
Obtiene la informacion oficial del vehiculo consultando la DGT. ⚠️ Esta operacion puede tener un coste por consulta.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
platepathSíMatricula del vehiculo (España).
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Informacion del vehiculo obtenida con exito.
{
  "description": "Informacion del vehiculo obtenida con exito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "matricula": {
            "type": "string",
            "description": "Matricula normalizada"
          },
          "bastidor": {
            "type": "string",
            "description": "Bastidor (VIN) del vehiculo"
          },
          "consultasDisponibles": {
            "type": "integer",
            "description": "Saldo de consultas del taller tras descontar"
          },
          "fechaConsulta": {
            "type": "string",
            "description": "Fecha del dato (DD/MM/YYYY)"
          },
          "datos": {
            "type": "object",
            "description": "Informacion tecnica oficial del vehiculo"
          }
        }
      }
    }
  }
}
HTTP 400 · Matricula no valida.
{
  "description": "Matricula no valida.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "codigo": {
            "type": "string"
          },
          "mensaje": {
            "type": "string"
          }
        }
      },
      "example": {
        "ok": false,
        "codigo": "MATRICULA_INVALIDA",
        "mensaje": "Matricula no valida"
      }
    }
  }
}
HTTP 401 · Token no valido o no autorizado.
{
  "description": "Token no valido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
HTTP 402 · El taller no tiene consultas disponibles.
{
  "description": "El taller no tiene consultas disponibles.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "codigo": {
            "type": "string"
          },
          "mensaje": {
            "type": "string"
          }
        }
      },
      "example": {
        "ok": false,
        "codigo": "SIN_CONSULTAS",
        "mensaje": "El taller no tiene consultas disponibles"
      }
    }
  }
}
HTTP 404 · No se ha encontrado el vehiculo.
{
  "description": "No se ha encontrado el vehiculo.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "codigo": {
            "type": "string"
          },
          "mensaje": {
            "type": "string"
          }
        }
      },
      "example": {
        "ok": false,
        "codigo": "VEHICULO_NO_ENCONTRADO",
        "mensaje": "No se han encontrado vehiculos para la matricula"
      }
    }
  }
}
HTTP 502 · Servicio no disponible.
{
  "description": "Servicio no disponible.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "codigo": {
            "type": "string"
          },
          "mensaje": {
            "type": "string"
          }
        }
      },
      "example": {
        "ok": false,
        "codigo": "ERROR_PROVEEDOR",
        "mensaje": "Servicio no disponible"
      }
    }
  }
}

Resguardos

GET/vehicle-intakesListado de resguardos
Obtiene un listado paginado de resguardos (entradas de vehículos).

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer"
}
per_pagequeryNoElementos por página
{
  "type": "integer"
}
from_datequeryNoFecha desde (yyyy-mm-dd).
{
  "type": "string"
}
to_datequeryNoFecha hasta (yyyy-mm-dd).
{
  "type": "string"
}
client_idqueryNoIdentificador único de cliente
{
  "type": "string"
}
vehicle_idqueryNoIdentificador único de vehículo
{
  "type": "string"
}
intake_numberqueryNoNúmero de resguardo (coincidencia exacta)
{
  "type": "string"
}
platequeryNoMatrícula del vehículo (coincidencia parcial)
{
  "type": "string"
}
status_codequeryNoEstado del resguardo: 1=Abierto, 2=Cerrado
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Respuesta paginada del listado de resguardos.",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Resumen de un resguardo (entrada de vehículo) en el listado.",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Identificador único del resguardo.",
                  "example": "es6b4l40ic7sfk3pqw0sfay6y39bt9w0"
                },
                "intake_number": {
                  "type": "string",
                  "description": "Número de resguardo.",
                  "example": "0000000025"
                },
                "entry_date": {
                  "type": "string",
                  "description": "Fecha de entrada (DD/MM/YYYY).",
                  "example": "20/02/2026"
                },
                "client_id": {
                  "type": "string",
                  "description": "Identificador único del cliente."
                },
                "vehicle_id": {
                  "type": "string",
                  "description": "Identificador único del vehículo."
                },
                "plate": {
                  "type": "string",
                  "description": "Matrícula del vehículo.",
                  "example": "2964-KBP"
                },
                "km": {
                  "type": "string",
                  "description": "Kilometraje del vehículo en el momento de la entrada.",
                  "example": "70000"
                },
                "status_code": {
                  "type": "integer",
                  "description": "Código de estado del resguardo: 1=Abierto, 2=Cerrado.",
                  "example": 1
                },
                "status_name": {
                  "type": "string",
                  "description": "Nombre legible del estado.",
                  "example": "Abierto"
                },
                "status_color": {
                  "type": "string",
                  "description": "Color hex asociado al estado.",
                  "example": "#3cb371"
                },
                "depositor_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nombre del depositante."
                },
                "estimated_date": {
                  "type": "string",
                  "nullable": true,
                  "description": "Fecha estimada de finalización (DD/MM/YYYY)."
                },
                "is_blocked": {
                  "type": "boolean",
                  "description": "Indica si el resguardo está bloqueado."
                },
                "is_archived": {
                  "type": "boolean",
                  "description": "Indica si el resguardo está archivado."
                }
              }
            }
          }
        }
      },
      "example": {
        "pagination": {
          "current_page": 1,
          "per_page": 10,
          "total_count": 25,
          "total_pages": 3
        },
        "data": [
          {
            "id": "es6b4l40ic7sfk3pqw0sfay6y39bt9w0",
            "intake_number": "0000000025",
            "entry_date": "20/02/2026",
            "client_id": "7ps4717hwaukddngvbom3f5yjf54q7q1",
            "vehicle_id": "9g38jrhu52oj5f5vp3ivmr1gxn2wqr1h",
            "plate": "2964-KBP",
            "km": "70000",
            "status_code": 1,
            "status_name": "Abierto",
            "status_color": "#3cb371",
            "depositor_name": "Juan deposita",
            "estimated_date": "24/02/2026",
            "is_blocked": false,
            "is_archived": false
          },
          {
            "id": "es6wye0z2sjxf1ph2uo3pyvp4qpl8q79",
            "intake_number": "0000000024",
            "entry_date": "10/06/2025",
            "client_id": "7ps4717hwaukddngvbom3f5yjf54q7q1",
            "vehicle_id": "9g38jrhu52oj5f5vp3ivmr1gxn2wqr1h",
            "plate": "2964-KBP",
            "km": "2222",
            "status_code": 1,
            "status_name": "Abierto",
            "status_color": "#3cb371",
            "depositor_name": null,
            "estimated_date": null,
            "is_blocked": false,
            "is_archived": false
          },
          {
            "id": "es6lvbkkkvm7t472nxj27bumk5ggl8p8",
            "intake_number": "0000000023",
            "entry_date": "10/06/2025",
            "client_id": "7ps4717hwaukddngvbom3f5yjf54q7q1",
            "vehicle_id": "9g38jrhu52oj5f5vp3ivmr1gxn2wqr1h",
            "plate": "2964-KBP",
            "km": "22222",
            "status_code": 2,
            "status_name": "Cerrado",
            "status_color": "#808080",
            "depositor_name": null,
            "estimated_date": null,
            "is_blocked": false,
            "is_archived": false
          }
        ]
      }
    }
  }
}
POST/vehicle-intakesCrear resguardo
Crea un resguardo de deposito. Son obligatorios `client_id` y `vehicle_id` (los identificadores que devuelven los listados de clientes y vehiculos); `insurer_id` es el identificador del listado de aseguradoras. El identificador y el numero de resguardo se generan automaticamente (el numero sigue la serie del taller) y el resguardo se crea en estado Abierto. Si no se envia `entry_date`, se usa la fecha actual. Las fechas van en formato DD/MM/YYYY. Devuelve el resguardo creado.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "client_id",
          "vehicle_id"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "Identificador del cliente (obligatorio)"
          },
          "vehicle_id": {
            "type": "string",
            "description": "Identificador del vehiculo (obligatorio)"
          },
          "insurer_id": {
            "type": "string",
            "description": "Identificador de la aseguradora"
          },
          "entry_date": {
            "type": "string",
            "description": "Fecha de entrada DD/MM/YYYY (por defecto, hoy)"
          },
          "estimated_date": {
            "type": "string",
            "description": "Fecha prevista DD/MM/YYYY"
          },
          "send_date": {
            "type": "string",
            "description": "Fecha de envio DD/MM/YYYY"
          },
          "km": {
            "type": "string",
            "description": "Kilometros del vehiculo"
          },
          "depositor_name": {
            "type": "string",
            "description": "Nombre del depositante"
          },
          "observations": {
            "type": "string",
            "description": "Observaciones"
          },
          "internal_observations": {
            "type": "string",
            "description": "Observaciones internas"
          },
          "acceptance_code": {
            "type": "integer",
            "description": "Codigo de aceptacion"
          },
          "siniester_number": {
            "type": "string",
            "description": "Numero de siniestro"
          },
          "insurance_amount": {
            "type": "number",
            "description": "Importe del seguro"
          },
          "has_parts_reception": {
            "type": "boolean",
            "description": "Recepcion de piezas"
          },
          "important_notice": {
            "type": "boolean",
            "description": "Aviso importante"
          },
          "fuel_level_code": {
            "type": "integer",
            "description": "Nivel de combustible: 0=lleno, 1=3/4, 2=1/2, 3=1/4, 4=reserva"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Resguardo creado con exito.
{
  "description": "Resguardo creado con exito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "intake_number": {
            "type": "string"
          },
          "entry_date": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "km": {
            "type": "string"
          },
          "status_code": {
            "type": "integer"
          },
          "status_name": {
            "type": "string"
          },
          "status_color": {
            "type": "string"
          },
          "depositor_name": {
            "type": "string"
          },
          "estimated_date": {
            "type": "string"
          },
          "is_blocked": {
            "type": "boolean"
          },
          "is_archived": {
            "type": "boolean"
          },
          "observations": {
            "type": "string"
          },
          "internal_observations": {
            "type": "string",
            "nullable": true
          },
          "acceptance_code": {
            "type": "integer",
            "nullable": true
          },
          "siniester_number": {
            "type": "string",
            "nullable": true
          },
          "insurance_amount": {
            "type": "number"
          },
          "next_itv_date": {
            "type": "string",
            "nullable": true
          },
          "send_date": {
            "type": "string",
            "nullable": true
          },
          "has_parts_reception": {
            "type": "boolean"
          },
          "important_notice": {
            "type": "boolean"
          },
          "employee_name": {
            "type": "string",
            "nullable": true
          },
          "fuel_level_code": {
            "type": "integer",
            "nullable": true
          },
          "fuel_level_name": {
            "type": "string",
            "nullable": true
          },
          "insurer_id": {
            "type": "string",
            "nullable": true
          },
          "bill_to_client_id": {
            "type": "string",
            "nullable": true
          },
          "billing_group_name": {
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}
HTTP 400 · Datos invalidos (p. ej. falta client_id o vehicle_id, o no existen para el taller).
{
  "description": "Datos invalidos (p. ej. falta client_id o vehicle_id, o no existen para el taller).",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "client_id is required",
          "vehicle_id is required"
        ]
      }
    }
  }
}
HTTP 401 · Token no valido o no autorizado.
{
  "description": "Token no valido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
GET/vehicle-intakes/{intake_id}Detalle de resguardo
Obtiene el detalle completo de un resguardo por su identificador único.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
intake_idpathSíIdentificador único del resguardo
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un resguardo (entrada de vehículo).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador único del resguardo."
          },
          "intake_number": {
            "type": "string",
            "description": "Número de resguardo."
          },
          "entry_date": {
            "type": "string",
            "description": "Fecha de entrada (DD/MM/YYYY)."
          },
          "client_id": {
            "type": "string",
            "description": "Identificador único del cliente."
          },
          "vehicle_id": {
            "type": "string",
            "description": "Identificador único del vehículo."
          },
          "plate": {
            "type": "string",
            "description": "Matrícula del vehículo."
          },
          "km": {
            "type": "string",
            "description": "Kilometraje del vehículo."
          },
          "status_code": {
            "type": "integer",
            "description": "Código de estado: 1=Abierto, 2=Cerrado."
          },
          "status_name": {
            "type": "string",
            "description": "Nombre legible del estado."
          },
          "status_color": {
            "type": "string",
            "description": "Color hex asociado al estado."
          },
          "depositor_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre del depositante."
          },
          "estimated_date": {
            "type": "string",
            "nullable": true,
            "description": "Fecha estimada de finalización (DD/MM/YYYY)."
          },
          "is_blocked": {
            "type": "boolean",
            "description": "Indica si el resguardo está bloqueado."
          },
          "is_archived": {
            "type": "boolean",
            "description": "Indica si el resguardo está archivado."
          },
          "observations": {
            "type": "string",
            "description": "Observaciones visibles del resguardo."
          },
          "internal_observations": {
            "type": "string",
            "description": "Observaciones internas (no visibles al cliente)."
          },
          "acceptance_code": {
            "type": "string",
            "nullable": true,
            "description": "Código de aceptación."
          },
          "siniester_number": {
            "type": "string",
            "nullable": true,
            "description": "Número de siniestro asociado."
          },
          "insurance_amount": {
            "type": "number",
            "description": "Importe del seguro.",
            "example": 0
          },
          "next_itv_date": {
            "type": "string",
            "nullable": true,
            "description": "Fecha de próxima ITV (DD/MM/YYYY)."
          },
          "send_date": {
            "type": "string",
            "nullable": true,
            "description": "Fecha de envío."
          },
          "has_parts_reception": {
            "type": "boolean",
            "description": "Indica si tiene recepción de piezas."
          },
          "important_notice": {
            "type": "boolean",
            "description": "Indica si tiene aviso importante."
          },
          "employee_name": {
            "type": "string",
            "description": "Nombre del empleado responsable."
          },
          "fuel_level_code": {
            "type": "integer",
            "description": "Código del nivel de combustible."
          },
          "fuel_level_name": {
            "type": "string",
            "description": "Descripción del nivel de combustible.",
            "example": "1/2 deposito"
          },
          "insurer_id": {
            "type": "string",
            "nullable": true,
            "description": "Identificador único de la aseguradora."
          },
          "bill_to_client_id": {
            "type": "string",
            "nullable": true,
            "description": "Identificador del cliente al que se factura."
          },
          "billing_group_name": {
            "type": "string",
            "description": "Nombre del grupo de facturación."
          }
        }
      },
      "example": {
        "id": "es6b4l40ic7sfk3pqw0sfay6y39bt9w0",
        "intake_number": "0000000025",
        "entry_date": "20/02/2026",
        "client_id": "7ps4717hwaukddngvbom3f5yjf54q7q1",
        "vehicle_id": "9g38jrhu52oj5f5vp3ivmr1gxn2wqr1h",
        "plate": "2964-KBP",
        "km": "70000",
        "status_code": 1,
        "status_name": "Abierto",
        "status_color": "#3cb371",
        "depositor_name": "Juan deposita",
        "estimated_date": "24/02/2026",
        "is_blocked": false,
        "is_archived": false,
        "observations": "Aleta izquierda, revisión itv",
        "internal_observations": "Debe una factura ",
        "acceptance_code": null,
        "siniester_number": null,
        "insurance_amount": 0,
        "next_itv_date": null,
        "send_date": null,
        "has_parts_reception": true,
        "important_notice": true,
        "employee_name": "RUBÉN",
        "fuel_level_code": 2,
        "fuel_level_name": "1/2 deposito",
        "insurer_id": null,
        "bill_to_client_id": null,
        "billing_group_name": "mecanica"
      }
    }
  }
}
PUT/vehicle-intakes/{intake_id}Actualizar resguardo
Actualiza los datos de un resguardo existente. Solo se modifican los campos enviados en el cuerpo. Con `status_code` se puede cerrar (2) o reabrir (1) el resguardo. Devuelve el resguardo actualizado.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
intake_idpathSíIdentificador unico del resguardo.
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "insurer_id": {
            "type": "string"
          },
          "entry_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "estimated_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "send_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "km": {
            "type": "string"
          },
          "depositor_name": {
            "type": "string"
          },
          "observations": {
            "type": "string"
          },
          "internal_observations": {
            "type": "string"
          },
          "acceptance_code": {
            "type": "integer"
          },
          "siniester_number": {
            "type": "string"
          },
          "insurance_amount": {
            "type": "number"
          },
          "has_parts_reception": {
            "type": "boolean"
          },
          "important_notice": {
            "type": "boolean"
          },
          "fuel_level_code": {
            "type": "integer",
            "description": "0=lleno, 1=3/4, 2=1/2, 3=1/4, 4=reserva"
          },
          "status_code": {
            "type": "integer",
            "description": "1=Abierto, 2=Cerrado"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Resguardo actualizado con exito.
{
  "description": "Resguardo actualizado con exito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "intake_number": {
            "type": "string"
          },
          "entry_date": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "km": {
            "type": "string"
          },
          "status_code": {
            "type": "integer"
          },
          "status_name": {
            "type": "string"
          },
          "status_color": {
            "type": "string"
          },
          "depositor_name": {
            "type": "string"
          },
          "estimated_date": {
            "type": "string"
          },
          "is_blocked": {
            "type": "boolean"
          },
          "is_archived": {
            "type": "boolean"
          },
          "observations": {
            "type": "string"
          },
          "internal_observations": {
            "type": "string",
            "nullable": true
          },
          "acceptance_code": {
            "type": "integer",
            "nullable": true
          },
          "siniester_number": {
            "type": "string",
            "nullable": true
          },
          "insurance_amount": {
            "type": "number"
          },
          "next_itv_date": {
            "type": "string",
            "nullable": true
          },
          "send_date": {
            "type": "string",
            "nullable": true
          },
          "has_parts_reception": {
            "type": "boolean"
          },
          "important_notice": {
            "type": "boolean"
          },
          "employee_name": {
            "type": "string",
            "nullable": true
          },
          "fuel_level_code": {
            "type": "integer",
            "nullable": true
          },
          "fuel_level_name": {
            "type": "string",
            "nullable": true
          },
          "insurer_id": {
            "type": "string",
            "nullable": true
          },
          "bill_to_client_id": {
            "type": "string",
            "nullable": true
          },
          "billing_group_name": {
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}
HTTP 400 · Datos invalidos o sin campos que actualizar.
{
  "description": "Datos invalidos o sin campos que actualizar.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "status_code must be 1 (open) or 2 (closed)"
        ]
      }
    }
  }
}
HTTP 401 · Token no valido o no autorizado.
{
  "description": "Token no valido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
HTTP 404 · Resguardo no encontrado.
{
  "description": "Resguardo no encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Vehicle intake not found"
        }
      }
    }
  }
}

Presupuestos

GET/budgetsListado de presupuestos
Obtiene un listado paginado de presupuestos

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoElementos por página
{
  "type": "integer",
  "default": 10
}
client_idqueryNoIdentificador único de cliente
{
  "type": "string"
}
vehicle_idqueryNoIdenfitificador único de vehículo
{
  "type": "string"
}
budget_numberqueryNoNúmero de presupuesto
{
  "type": "string"
}
from_datequeryNoFecha desde (yyyy-mm-dd).
{
  "type": "string"
}
to_datequeryNoFecha hasta (yyyy-mm-dd).
{
  "type": "string"
}
deletedqueryNoIncluir presupuestos eliminados (por defecto false).
{
  "type": "boolean",
  "default": false
}
platequeryNoMatrícula
{
  "type": "string"
}
vinqueryNoNª Bastidor
{
  "type": "string"
}
makequeryNoMarca de vehículo
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de presupuestos
{
  "description": "Listado de presupuestos",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Representa un elemento de la lista de presupuestos.",
              "properties": {
                "budget_id": {
                  "type": "string",
                  "description": "Identificador único del presupuesto.",
                  "example": "bgt_123xyz"
                },
                "budget_number": {
                  "type": "string",
                  "description": "Número del presupuesto.",
                  "example": "PRE-2024-001"
                },
                "date": {
                  "type": "string",
                  "description": "Fecha del presupuesto (formato DD/MM/YYYY).",
                  "example": "15/07/2024"
                },
                "client_name": {
                  "type": "string",
                  "description": "Nombre del cliente.",
                  "example": "Cliente Ejemplo S.L."
                },
                "vehicle_plate": {
                  "type": "string",
                  "description": "Matrícula del vehículo.",
                  "example": "1234-ABC"
                },
                "total_amount": {
                  "type": "string",
                  "description": "Importe total del presupuesto.",
                  "example": "1500,50"
                },
                "currency_symbol": {
                  "type": "string",
                  "description": "Símbolo de la moneda.",
                  "example": "€"
                },
                "status": {
                  "type": "string",
                  "description": "Estado del presupuesto (e.g., Pendiente, Aceptado, Rechazado).",
                  "example": "Pendiente"
                }
              },
              "required": [
                "budget_id",
                "budget_number",
                "date",
                "client_name",
                "total_amount",
                "status"
              ]
            }
          }
        }
      }
    }
  }
}
POST/budgetsCrear presupuesto
Crea la cabecera de un presupuesto. Solo es obligatorio `client_id` (el identificador que devuelve el listado de clientes); `vehicle_id` e `insurer_id` son opcionales. El identificador y el número se generan automáticamente (el número sigue la serie del taller), el IVA y la divisa se toman de la configuración del taller, y el presupuesto se crea En Elaboración con pagador cliente por defecto. Si no se envía `entry_date` se usa la fecha actual, y `valid_days` fija la validez en días desde la fecha de alta. Las líneas se añaden después con POST /budgets/{budget_id}/lines. Devuelve el presupuesto con la misma estructura que el detalle del GET.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "client_id"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "Identificador del cliente (obligatorio)"
          },
          "vehicle_id": {
            "type": "string",
            "description": "Identificador del vehiculo (opcional)"
          },
          "insurer_id": {
            "type": "string",
            "description": "Identificador de la aseguradora"
          },
          "entry_date": {
            "type": "string",
            "description": "Fecha de alta DD/MM/YYYY (por defecto, hoy)"
          },
          "valid_days": {
            "type": "integer",
            "description": "Dias de validez del presupuesto (calcula la fecha de validez desde la fecha de alta)"
          },
          "kilometers": {
            "type": "integer",
            "description": "Kilometros del vehiculo"
          },
          "observations": {
            "type": "string",
            "description": "Observaciones"
          },
          "incident_number": {
            "type": "string",
            "description": "Numero de siniestro"
          },
          "payer_type_id": {
            "type": "integer",
            "description": "Pagador: 1=cliente (por defecto), 2=aseguradora, 3=leasing, 4=otro cliente"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Presupuesto creado con éxito.
{
  "description": "Presupuesto creado con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Misma estructura que el detalle de GET /budgets/{budget_id}: cabecera, cliente, vehiculo, totales, lineas por tipo (parts, labors, others, paints, tyres), recursos y documentos.",
        "properties": {
          "budget_id": {
            "type": "string"
          },
          "budget_number": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "vat_percentage": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "vat_included": {
            "type": "string"
          },
          "status_id": {
            "type": "string"
          },
          "status_name": {
            "type": "string"
          },
          "client_full_name": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "total_with_vat": {
            "type": "number",
            "nullable": true
          },
          "total_without_vat": {
            "type": "number",
            "nullable": true
          },
          "client_number": {
            "type": "string"
          },
          "valid_days": {
            "type": "string",
            "nullable": true
          },
          "deleted": {
            "type": "boolean"
          },
          "vehicle_id": {
            "type": "string",
            "nullable": true
          },
          "plate": {
            "type": "string",
            "nullable": true
          },
          "vin": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "lines": {
            "type": "object"
          },
          "resources": {
            "type": "array"
          },
          "documents": {
            "type": "array"
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 · Datos inválidos (p. ej. falta client_id o no existe para el taller).
{
  "description": "Datos inválidos (p. ej. falta client_id o no existe para el taller).",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "client_id is required"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
GET/budgets/{budget_id}Detalle de una orden de un presupuesto
Obtiene todos los datos relacionados con un presupuesto

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
budget_idpathSíIdentificador único del presupuesto
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Detalle del presupuesto
{
  "description": "Detalle del presupuesto",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un presupuesto.",
        "properties": {
          "budget_id": {
            "type": "string",
            "description": "Identificador único del presupuesto.",
            "example": "XXXXX"
          },
          "budget_number": {
            "type": "string",
            "description": "Número del presupuesto.",
            "example": "PRE-2024-001"
          },
          "budget_date_formatted": {
            "type": "string",
            "description": "Fecha de creación del presupuesto (formato DD/MM/YYYY).",
            "example": "15/07/2024"
          },
          "valid_until_date_formatted": {
            "type": "string",
            "description": "Fecha de validez del presupuesto (formato DD/MM/YYYY).",
            "example": "14/08/2024"
          },
          "status_description": {
            "type": "string",
            "description": "Descripción del estado del presupuesto (e.g., Pendiente, Aceptado, Rechazado).",
            "example": "Pendiente"
          },
          "observations": {
            "type": "string",
            "description": "Observaciones o notas adicionales del presupuesto.",
            "example": "Presupuesto para revisión anual."
          },
          "subtotal_net_amount": {
            "type": "string",
            "description": "Subtotal neto antes de impuestos.",
            "example": "1200.00"
          },
          "total_discount_amount": {
            "type": "string",
            "description": "Importe total de descuentos aplicados.",
            "example": "50.00"
          },
          "total_tax_amount": {
            "type": "string",
            "description": "Importe total de los impuestos aplicados.",
            "example": "241.50"
          },
          "total_amount_vat_included": {
            "type": "string",
            "description": "Importe total del presupuesto con IVA incluido.",
            "example": "1391.50"
          },
          "currency_symbol": {
            "type": "string",
            "description": "Símbolo de la moneda.",
            "example": "€"
          },
          "vat_percentage_summary": {
            "type": "string",
            "description": "Resumen del porcentaje de IVA aplicado.",
            "example": "21%"
          },
          "client_id": {
            "type": "string",
            "description": "Identificador único del cliente."
          },
          "client_full_name": {
            "type": "string",
            "description": "Nombre completo del cliente."
          },
          "customer_number": {
            "type": "string",
            "description": "Número de cliente."
          },
          "client_tax_id": {
            "type": "string",
            "description": "NIF/CIF del cliente."
          },
          "client_address1": {
            "type": "string",
            "description": "Dirección principal del cliente."
          },
          "client_zip_code": {
            "type": "string",
            "description": "Código postal del cliente."
          },
          "client_city": {
            "type": "string",
            "description": "Ciudad del cliente."
          },
          "client_email": {
            "type": "string",
            "format": "email",
            "description": "Email del cliente."
          },
          "client_phone": {
            "type": "string",
            "description": "Teléfono del cliente."
          },
          "client_mobile_phone": {
            "type": "string",
            "description": "Teléfono móvil del cliente."
          },
          "vehicle_id": {
            "type": "string",
            "description": "Identificador único del vehículo."
          },
          "vehicle_plate_number": {
            "type": "string",
            "description": "Matrícula del vehículo."
          },
          "vehicle_vin": {
            "type": "string",
            "description": "Número de bastidor (VIN) del vehículo."
          },
          "vehicle_make_model_description": {
            "type": "string",
            "description": "Descripción de marca y modelo del vehículo."
          },
          "vehicle_kilometres": {
            "type": "string",
            "description": "Kilometraje del vehículo en el momento del presupuesto."
          },
          "budget_lines": {
            "type": "object",
            "description": "Agrupación de líneas de presupuesto por tipo.",
            "properties": {
              "parts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Representa una línea de un presupuesto.",
                  "properties": {
                    "line_id": {
                      "type": "string",
                      "description": "Identificador único de la línea."
                    },
                    "reference": {
                      "type": "string",
                      "example": "REF001",
                      "description": "Referencia del artículo/servicio."
                    },
                    "description": {
                      "type": "string",
                      "example": "Cambio de aceite y filtro",
                      "description": "Descripción detallada."
                    },
                    "quantity": {
                      "type": "string",
                      "example": "1",
                      "description": "Cantidad."
                    },
                    "unit_price_net": {
                      "type": "string",
                      "example": "50",
                      "description": "Precio unitario neto."
                    },
                    "discount_percentage": {
                      "type": "string",
                      "example": "0",
                      "description": "Porcentaje de descuento."
                    },
                    "tax_rate": {
                      "type": "string",
                      "example": "21",
                      "description": "Tipo de IVA aplicado."
                    },
                    "total_line_amount_net_with_discount": {
                      "type": "string",
                      "example": "50",
                      "description": "Importe total neto de la línea con descuento."
                    },
                    "line_type_description": {
                      "type": "string",
                      "example": "Mano de Obra",
                      "description": "Descripción del tipo de línea (Pieza, Mano de Obra, Otros)."
                    }
                  }
                },
                "description": "Líneas de repuestos."
              },
              "labors": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Representa una línea de un presupuesto.",
                  "properties": {
                    "line_id": {
                      "type": "string",
                      "description": "Identificador único de la línea."
                    },
                    "reference": {
                      "type": "string",
                      "example": "REF001",
                      "description": "Referencia del artículo/servicio."
                    },
                    "description": {
                      "type": "string",
                      "example": "Cambio de aceite y filtro",
                      "description": "Descripción detallada."
                    },
                    "quantity": {
                      "type": "string",
                      "example": "1",
                      "description": "Cantidad."
                    },
                    "unit_price_net": {
                      "type": "string",
                      "example": "50",
                      "description": "Precio unitario neto."
                    },
                    "discount_percentage": {
                      "type": "string",
                      "example": "0",
                      "description": "Porcentaje de descuento."
                    },
                    "tax_rate": {
                      "type": "string",
                      "example": "21",
                      "description": "Tipo de IVA aplicado."
                    },
                    "total_line_amount_net_with_discount": {
                      "type": "string",
                      "example": "50",
                      "description": "Importe total neto de la línea con descuento."
                    },
                    "line_type_description": {
                      "type": "string",
                      "example": "Mano de Obra",
                      "description": "Descripción del tipo de línea (Pieza, Mano de Obra, Otros)."
                    }
                  }
                },
                "description": "Líneas de mano de obra."
              },
              "others": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Representa una línea de un presupuesto.",
                  "properties": {
                    "line_id": {
                      "type": "string",
                      "description": "Identificador único de la línea."
                    },
                    "reference": {
                      "type": "string",
                      "example": "REF001",
                      "description": "Referencia del artículo/servicio."
                    },
                    "description": {
                      "type": "string",
                      "example": "Cambio de aceite y filtro",
                      "description": "Descripción detallada."
                    },
                    "quantity": {
                      "type": "string",
                      "example": "1",
                      "description": "Cantidad."
                    },
                    "unit_price_net": {
                      "type": "string",
                      "example": "50",
                      "description": "Precio unitario neto."
                    },
                    "discount_percentage": {
                      "type": "string",
                      "example": "0",
                      "description": "Porcentaje de descuento."
                    },
                    "tax_rate": {
                      "type": "string",
                      "example": "21",
                      "description": "Tipo de IVA aplicado."
                    },
                    "total_line_amount_net_with_discount": {
                      "type": "string",
                      "example": "50",
                      "description": "Importe total neto de la línea con descuento."
                    },
                    "line_type_description": {
                      "type": "string",
                      "example": "Mano de Obra",
                      "description": "Descripción del tipo de línea (Pieza, Mano de Obra, Otros)."
                    }
                  }
                },
                "description": "Otras líneas."
              }
            }
          },
          "created_by_user_name": {
            "type": "string",
            "description": "Nombre del usuario que creó el presupuesto."
          },
          "created_at_datetime_formatted": {
            "type": "string",
            "description": "Fecha y hora de creación del presupuesto (formato legible).",
            "example": "15/07/2024 10:30"
          },
          "updated_at_datetime_formatted": {
            "type": "string",
            "description": "Fecha y hora de la última modificación (formato legible).",
            "example": "15/07/2024 11:00"
          }
        }
      }
    }
  }
}
PUT/budgets/{budget_id}Actualizar presupuesto
Actualiza la cabecera de un presupuesto existente. Solo se modifican los campos enviados. `status_code` admite 0 (En Elaboración), 1 (Entregado), 2 (Rechazado), 6 (En negociación) y 99 (Caducado); aceptar o facturar se gestiona desde la aplicación. Si el presupuesto está aceptado, firmado, en la papelera o bloqueado devuelve 409 (mismas reglas que las líneas). Devuelve el presupuesto actualizado.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
budget_idpathSíIdentificador único del presupuesto.
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "insurer_id": {
            "type": "string"
          },
          "entry_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "valid_days": {
            "type": "integer"
          },
          "kilometers": {
            "type": "integer"
          },
          "observations": {
            "type": "string"
          },
          "incident_number": {
            "type": "string"
          },
          "payer_type_id": {
            "type": "integer",
            "description": "1=cliente, 2=aseguradora, 3=leasing, 4=otro cliente"
          },
          "status_code": {
            "type": "integer",
            "description": "Estado: 0=En Elaboracion, 1=Entregado, 2=Rechazado, 6=En negociacion, 99=Caducado. Aceptar y Facturar se gestionan desde la aplicacion"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Presupuesto actualizado con éxito.
{
  "description": "Presupuesto actualizado con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Misma estructura que el detalle de GET /budgets/{budget_id}: cabecera, cliente, vehiculo, totales, lineas por tipo (parts, labors, others, paints, tyres), recursos y documentos.",
        "properties": {
          "budget_id": {
            "type": "string"
          },
          "budget_number": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "vat_percentage": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "vat_included": {
            "type": "string"
          },
          "status_id": {
            "type": "string"
          },
          "status_name": {
            "type": "string"
          },
          "client_full_name": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "total_with_vat": {
            "type": "number",
            "nullable": true
          },
          "total_without_vat": {
            "type": "number",
            "nullable": true
          },
          "client_number": {
            "type": "string"
          },
          "valid_days": {
            "type": "string",
            "nullable": true
          },
          "deleted": {
            "type": "boolean"
          },
          "vehicle_id": {
            "type": "string",
            "nullable": true
          },
          "plate": {
            "type": "string",
            "nullable": true
          },
          "vin": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "lines": {
            "type": "object"
          },
          "resources": {
            "type": "array"
          },
          "documents": {
            "type": "array"
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 · Datos inválidos o sin campos que actualizar.
{
  "description": "Datos inválidos o sin campos que actualizar.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "status_code must be one of 0 (draft), 1 (delivered), 2 (rejected), 6 (negotiating) or 99 (expired)"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
HTTP 404 · Presupuesto no encontrado.
{
  "description": "Presupuesto no encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Budget not found"
        }
      }
    }
  }
}
HTTP 409 · El presupuesto no es modificable (aceptado, firmado, en papelera o bloqueado).
{
  "description": "El presupuesto no es modificable (aceptado, firmado, en papelera o bloqueado).",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "reason": {
            "type": "string",
            "description": "accepted | signed | recycled | blocked"
          }
        }
      },
      "example": {
        "status": 409,
        "message": "El presupuesto no se puede modificar",
        "reason": "accepted"
      }
    }
  }
}
POST/budgets/{budget_id}/linesCrear linea de presupuesto
Crea una nueva linea dentro de un presupuesto existente. Los campos obligatorios son `line_type` y `description`. Los totales del presupuesto se recalculan automaticamente. **Restricciones:** No se puede modificar un presupuesto que este aceptado, firmado o en la papelera de reciclaje (error 409).

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
budget_idpathSíIdentificador unico del presupuesto
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "Datos de la nueva linea de presupuesto. Los campos `line_type` y `description` son obligatorios.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "line_type",
          "description"
        ],
        "properties": {
          "line_type": {
            "type": "integer",
            "description": "Tipo de linea: 1=piezas, 2=mano de obra, 3=pintura, 4=subcontrata, 5=otros",
            "enum": [
              1,
              2,
              3,
              4,
              5
            ]
          },
          "description": {
            "type": "string",
            "description": "Descripcion de la linea"
          },
          "reference": {
            "type": "string",
            "description": "Referencia del articulo o servicio"
          },
          "quantity": {
            "type": "number",
            "description": "Cantidad (default: 1)",
            "default": 1
          },
          "unit_price": {
            "type": "number",
            "description": "Precio unitario (default: 0)",
            "default": 0
          },
          "discount_percentage": {
            "type": "number",
            "description": "Porcentaje de descuento (default: 0)",
            "default": 0
          },
          "tax_rate": {
            "type": "number",
            "description": "Porcentaje de IVA. Si no se indica, hereda el del presupuesto"
          }
        }
      },
      "example": {
        "line_type": 1,
        "description": "Filtro de aceite",
        "reference": "FO-1234",
        "quantity": 2,
        "unit_price": 12.5,
        "discount_percentage": 10,
        "tax_rate": 21
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Linea creada correctamente
{
  "description": "Linea creada correctamente",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "line_id": {
            "type": "string",
            "description": "Identificador unico de la linea"
          },
          "description": {
            "type": "string",
            "description": "Descripcion de la linea"
          },
          "reference": {
            "type": "string",
            "description": "Referencia del articulo o servicio"
          },
          "quantity": {
            "type": "number",
            "description": "Cantidad"
          },
          "unit_price": {
            "type": "number",
            "description": "Precio unitario"
          },
          "discount_percentage": {
            "type": "number",
            "description": "Porcentaje de descuento"
          },
          "tax_rate": {
            "type": "number",
            "description": "Porcentaje de IVA"
          },
          "line_type": {
            "type": "integer",
            "description": "Tipo de linea (1-5)"
          },
          "total_with_discount": {
            "type": "number",
            "description": "Total de la linea con descuento aplicado"
          }
        }
      }
    }
  }
}
HTTP 400 · Error de validacion: faltan campos requeridos o valores invalidos
{
  "description": "Error de validacion: faltan campos requeridos o valores invalidos",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autenticado o token invalido
{
  "description": "No autenticado o token invalido",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Presupuesto no encontrado
{
  "description": "Presupuesto no encontrado",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 409 · El presupuesto no se puede modificar (aceptado, firmado o en papelera)
{
  "description": "El presupuesto no se puede modificar (aceptado, firmado o en papelera)",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Codigo HTTP"
          },
          "message": {
            "type": "string",
            "description": "Mensaje de error descriptivo"
          },
          "reason": {
            "type": "string",
            "description": "Razon del bloqueo: accepted, signed o recycled",
            "enum": [
              "accepted",
              "signed",
              "recycled"
            ]
          }
        }
      }
    }
  }
}
PUT/budgets/{budget_id}/lines/{line_id}Actualizar linea de presupuesto
Actualiza los campos de una linea de presupuesto existente. Solo se modifican los campos enviados en el body. El campo `line_type` no se puede cambiar. Los totales del presupuesto se recalculan automaticamente. **Restricciones:** No se puede modificar un presupuesto que este aceptado, firmado o en la papelera de reciclaje (error 409).

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
budget_idpathSíIdentificador unico del presupuesto
{
  "type": "string"
}
line_idpathSíIdentificador unico de la linea de presupuesto
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "Campos a actualizar en la linea. Solo se modifican los campos incluidos. No se permite cambiar `line_type`.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Descripcion de la linea"
          },
          "reference": {
            "type": "string",
            "description": "Referencia del articulo o servicio"
          },
          "quantity": {
            "type": "number",
            "description": "Cantidad"
          },
          "unit_price": {
            "type": "number",
            "description": "Precio unitario"
          },
          "discount_percentage": {
            "type": "number",
            "description": "Porcentaje de descuento"
          },
          "tax_rate": {
            "type": "number",
            "description": "Porcentaje de IVA"
          }
        }
      },
      "example": {
        "description": "Filtro de aceite premium",
        "reference": "FO-5678",
        "quantity": 3,
        "unit_price": 15,
        "discount_percentage": 5,
        "tax_rate": 21
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Linea actualizada correctamente
{
  "description": "Linea actualizada correctamente",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "line_id": {
            "type": "string",
            "description": "Identificador unico de la linea"
          },
          "description": {
            "type": "string",
            "description": "Descripcion de la linea"
          },
          "reference": {
            "type": "string",
            "description": "Referencia del articulo o servicio"
          },
          "quantity": {
            "type": "number",
            "description": "Cantidad"
          },
          "unit_price": {
            "type": "number",
            "description": "Precio unitario"
          },
          "discount_percentage": {
            "type": "number",
            "description": "Porcentaje de descuento"
          },
          "tax_rate": {
            "type": "number",
            "description": "Porcentaje de IVA"
          },
          "line_type": {
            "type": "integer",
            "description": "Tipo de linea (1-5)"
          },
          "total_with_discount": {
            "type": "number",
            "description": "Total de la linea con descuento aplicado"
          }
        }
      }
    }
  }
}
HTTP 400 · Error de validacion: no se proporcionaron campos validos para actualizar
{
  "description": "Error de validacion: no se proporcionaron campos validos para actualizar",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autenticado o token invalido
{
  "description": "No autenticado o token invalido",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Presupuesto o linea no encontrados
{
  "description": "Presupuesto o linea no encontrados",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 409 · El presupuesto no se puede modificar (aceptado, firmado o en papelera)
{
  "description": "El presupuesto no se puede modificar (aceptado, firmado o en papelera)",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Codigo HTTP"
          },
          "message": {
            "type": "string",
            "description": "Mensaje de error descriptivo"
          },
          "reason": {
            "type": "string",
            "description": "Razon del bloqueo: accepted, signed o recycled",
            "enum": [
              "accepted",
              "signed",
              "recycled"
            ]
          }
        }
      }
    }
  }
}
DELETE/budgets/{budget_id}/lines/{line_id}Eliminar linea de presupuesto
Elimina permanentemente una linea de un presupuesto. Los totales del presupuesto se recalculan automaticamente. **Restricciones:** No se puede modificar un presupuesto que este aceptado, firmado o en la papelera de reciclaje (error 409).

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
budget_idpathSíIdentificador unico del presupuesto
{
  "type": "string"
}
line_idpathSíIdentificador unico de la linea de presupuesto
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Linea eliminada correctamente
{
  "description": "Linea eliminada correctamente",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 · Faltan parametros requeridos (budget_id, line_id)
{
  "description": "Faltan parametros requeridos (budget_id, line_id)",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 401 · No autenticado o token invalido
{
  "description": "No autenticado o token invalido",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Presupuesto o linea no encontrados
{
  "description": "Presupuesto o linea no encontrados",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 409 · El presupuesto no se puede modificar (aceptado, firmado o en papelera)
{
  "description": "El presupuesto no se puede modificar (aceptado, firmado o en papelera)",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Codigo HTTP"
          },
          "message": {
            "type": "string",
            "description": "Mensaje de error descriptivo"
          },
          "reason": {
            "type": "string",
            "description": "Razon del bloqueo: accepted, signed o recycled",
            "enum": [
              "accepted",
              "signed",
              "recycled"
            ]
          }
        }
      }
    }
  }
}

Proveedores

GET/suppliersObtiene un listado de proveedores
Devuelve una lista paginada de proveedores registrados en el sistema.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página para la paginación.
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoNúmero de proveedores por página.
{
  "type": "integer",
  "default": 10
}
supplier_numberqueryNoNúmero de proveedor
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de proveedores obtenido con éxito.
{
  "description": "Listado de proveedores obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Proveedor.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "supplier_number": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "vat_number": {
                  "type": "string",
                  "nullable": true
                },
                "payment_method": {
                  "type": "string"
                },
                "payment_terms": {
                  "type": "string"
                },
                "address": {
                  "type": "string",
                  "nullable": true
                },
                "zip_code": {
                  "type": "string",
                  "nullable": true
                },
                "city": {
                  "type": "string",
                  "nullable": true
                },
                "province": {
                  "type": "string",
                  "nullable": true
                },
                "parts_discount": {
                  "type": "number",
                  "nullable": true
                },
                "labor_discount": {
                  "type": "number",
                  "nullable": true
                },
                "phone_1": {
                  "type": "string",
                  "nullable": true
                },
                "phone_2": {
                  "type": "string",
                  "nullable": true
                },
                "fax": {
                  "type": "string",
                  "nullable": true
                },
                "email": {
                  "type": "string",
                  "nullable": true
                },
                "website": {
                  "type": "string",
                  "nullable": true
                },
                "account_ledger": {
                  "type": "string",
                  "nullable": true
                },
                "special_vat": {
                  "type": "number",
                  "nullable": true
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
POST/suppliersCrear proveedor
Crea un proveedor. El unico campo obligatorio es `name`. El identificador y el numero de proveedor se generan automaticamente (el numero sigue la serie del taller). Devuelve el proveedor creado.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del proveedor (obligatorio)"
          },
          "vat_number": {
            "type": "string",
            "description": "CIF/NIF"
          },
          "address": {
            "type": "string",
            "description": "Direccion"
          },
          "zip_code": {
            "type": "string",
            "description": "Codigo postal"
          },
          "city": {
            "type": "string",
            "description": "Poblacion"
          },
          "province": {
            "type": "string",
            "description": "Provincia"
          },
          "parts_discount": {
            "type": "integer",
            "description": "Descuento en piezas (%)"
          },
          "labor_discount": {
            "type": "integer",
            "description": "Descuento en mano de obra (%)"
          },
          "phone_1": {
            "type": "string",
            "description": "Telefono 1"
          },
          "phone_2": {
            "type": "string",
            "description": "Telefono 2"
          },
          "fax": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "website": {
            "type": "string",
            "description": "Pagina web"
          },
          "account_ledger": {
            "type": "string",
            "description": "Cuenta contable"
          },
          "special_vat": {
            "type": "integer",
            "description": "IVA especial"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Proveedor creado con exito.
{
  "description": "Proveedor creado con exito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "supplier_number": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "vat_number": {
            "type": "string"
          },
          "payment_method": {
            "type": "string",
            "nullable": true
          },
          "payment_terms": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string"
          },
          "zip_code": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "province": {
            "type": "string"
          },
          "parts_discount": {
            "type": "integer"
          },
          "labor_discount": {
            "type": "integer"
          },
          "phone_1": {
            "type": "string"
          },
          "phone_2": {
            "type": "string"
          },
          "fax": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "account_ledger": {
            "type": "string"
          },
          "special_vat": {
            "type": "integer"
          },
          "contacts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Datos invalidos (p. ej. falta name).
{
  "description": "Datos invalidos (p. ej. falta name).",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "name is required"
        ]
      }
    }
  }
}
HTTP 401 · Token no valido o no autorizado.
{
  "description": "Token no valido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
GET/suppliers/{supplier_id}Obtiene el detalle de un proveedor
Devuelve los detalles de un proveedor específico.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
supplier_idpathSíID del proveedor a obtener.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de proveedores obtenido con éxito.
{
  "description": "Listado de proveedores obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle de proveedor (mismos campos que lista).",
        "properties": {
          "id": {
            "type": "string"
          },
          "supplier_number": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "vat_number": {
            "type": "string",
            "nullable": true
          },
          "payment_method": {
            "type": "string"
          },
          "payment_terms": {
            "type": "string"
          },
          "address": {
            "type": "string",
            "nullable": true
          },
          "zip_code": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "province": {
            "type": "string",
            "nullable": true
          },
          "parts_discount": {
            "type": "number",
            "nullable": true
          },
          "labor_discount": {
            "type": "number",
            "nullable": true
          },
          "phone_1": {
            "type": "string",
            "nullable": true
          },
          "phone_2": {
            "type": "string",
            "nullable": true
          },
          "fax": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "account_ledger": {
            "type": "string",
            "nullable": true
          },
          "special_vat": {
            "type": "number",
            "nullable": true
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
PUT/suppliers/{supplier_id}Actualizar proveedor
Actualiza los datos de un proveedor existente. Solo se modifican los campos enviados en el cuerpo. Devuelve el proveedor actualizado.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
supplier_idpathSíIdentificador unico del proveedor.
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "vat_number": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "zip_code": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "province": {
            "type": "string"
          },
          "parts_discount": {
            "type": "integer"
          },
          "labor_discount": {
            "type": "integer"
          },
          "phone_1": {
            "type": "string"
          },
          "phone_2": {
            "type": "string"
          },
          "fax": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "account_ledger": {
            "type": "string"
          },
          "special_vat": {
            "type": "integer"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Proveedor actualizado con exito.
{
  "description": "Proveedor actualizado con exito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "supplier_number": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "vat_number": {
            "type": "string"
          },
          "payment_method": {
            "type": "string",
            "nullable": true
          },
          "payment_terms": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string"
          },
          "zip_code": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "province": {
            "type": "string"
          },
          "parts_discount": {
            "type": "integer"
          },
          "labor_discount": {
            "type": "integer"
          },
          "phone_1": {
            "type": "string"
          },
          "phone_2": {
            "type": "string"
          },
          "fax": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "account_ledger": {
            "type": "string"
          },
          "special_vat": {
            "type": "integer"
          },
          "contacts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Datos invalidos o sin campos que actualizar.
{
  "description": "Datos invalidos o sin campos que actualizar.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "No valid fields provided for update"
        ]
      }
    }
  }
}
HTTP 401 · Token no valido o no autorizado.
{
  "description": "Token no valido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
HTTP 404 · Proveedor no encontrado.
{
  "description": "Proveedor no encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Supplier not found"
        }
      }
    }
  }
}

Empleados

GET/employeesObtiene un listado de empleados
Devuelve una lista paginada de empleados registrados en el sistema.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página para la paginación.
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoNúmero de proveedores por página.
{
  "type": "integer",
  "default": 10
}

Respuestas documentadas

HTTP 200 · Listado de empleados obtenido con éxito.
{
  "description": "Listado de empleados obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Resumen de un empleado en la lista.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador unico del empleado."
          },
          "employee_number": {
            "type": "string",
            "description": "Numero de empleado."
          },
          "name": {
            "type": "string",
            "description": "Nombre del empleado."
          },
          "surname1": {
            "type": "string",
            "description": "Primer apellido del empleado."
          },
          "surname2": {
            "type": "string",
            "nullable": true,
            "description": "Segundo apellido del empleado."
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/employees/{employee_id}Obtiene el detalle de un empleado
Devuelve los detalles de un empleado específico.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
employee_idpathSíID del empleado a obtener.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Detalles del empleado obtenidos con éxito.
{
  "description": "Detalles del empleado obtenidos con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un empleado.",
        "properties": {
          "id": {
            "type": "string"
          },
          "employee_number": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "surname1": {
            "type": "string"
          },
          "surname2": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "mobile": {
            "type": "string",
            "nullable": true
          },
          "nif": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string",
            "nullable": true
          },
          "postal_code": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "province": {
            "type": "string",
            "nullable": true
          },
          "date_joined": {
            "type": "string",
            "nullable": true
          },
          "date_left": {
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/employees/time-entriesConsultar fichajes
Consulta los fichajes presenciales de los empleados del taller. **Sin parametros** devuelve los fichajes de todos los empleados del día actual. Se pueden combinar libremente `employee_id`, `from` y `to`. **Fechas.** Se admite fecha sola (`2026-08-01`) o fecha y hora. `from` sin hora se toma desde las 00:00:00; `to` sin hora se toma hasta las 00:00:00 del día siguiente, es decir, es un **límite superior exclusivo**. El bloque `period` de la respuesta indica el período que se ha aplicado realmente. **Turnos nocturnos.** El criterio incluye los fichajes que se solapan con el periodo, de modo que un turno que empieza a las 22:00 y termina a las 06:00 del día siguiente aparece al consultar cualquiera de los dos días. **Fichajes abiertos.** Un fichaje sin cerrar entra en el resultado siempre que haya empezado antes del fin del período consultado, sin límite por antigüedad. Conviene tenerlo en cuenta: un fichaje que nunca se cerró seguirá apareciendo en todas las consultas posteriores a su inicio. El rango máximo por consulta es de 366 días.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
employee_idqueryNoIdentificador único del empleado. Si se omite, se devuelven los fichajes de todos los empleados del taller.
{
  "type": "string"
}
fromqueryNoInicio del período. Fecha (`2026-08-01`) o fecha y hora. Si se omite, el día actual.
{
  "type": "string"
}
toqueryNoFin del período, límite exclusivo. Una fecha sin hora se toma como las 00:00 del día siguiente.
{
  "type": "string"
}
pagequeryNoNúmero de página. Por defecto 1.
{
  "type": "integer"
}
per_pagequeryNoResultados por página, entre 1 y 100. Por defecto 10.
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 · Fichajes del período consultado.
{
  "description": "Fichajes del período consultado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "type": "object",
            "properties": {
              "current_page": {
                "type": "integer"
              },
              "per_page": {
                "type": "integer"
              },
              "total_count": {
                "type": "integer"
              },
              "total_pages": {
                "type": "integer"
              }
            }
          },
          "period": {
            "type": "object",
            "description": "Período realmente aplicado a la consulta",
            "properties": {
              "from": {
                "type": "string"
              },
              "to": {
                "type": "string",
                "description": "Límite superior exclusivo"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "description": "Identificador del fichaje"
                },
                "employee_id": {
                  "type": "string",
                  "description": "Identificador único del empleado"
                },
                "employee_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nombre y apellidos del empleado"
                },
                "start_at": {
                  "type": "string",
                  "description": "Fecha y hora de entrada, hora local del taller, sin desfase horario"
                },
                "end_at": {
                  "type": "string",
                  "nullable": true,
                  "description": "Fecha y hora de salida. Nulo indica que el fichaje sigue abierto"
                },
                "start_type": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "description": {
                      "type": "string"
                    }
                  }
                },
                "end_type": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "description": {
                      "type": "string"
                    }
                  }
                },
                "observations": {
                  "type": "string",
                  "nullable": true
                },
                "warnings": {
                  "type": "array",
                  "description": "Solo en alta y modificación, si el fichaje se solapa con otro del mismo empleado",
                  "items": {
                    "type": "object",
                    "properties": {
                      "code": {
                        "type": "string"
                      },
                      "message": {
                        "type": "string"
                      },
                      "time_entry_ids": {
                        "type": "array",
                        "items": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Parámetros inválidos: formato de fecha incorrecto, to anterior a from o rango mayor de 366 días.
{
  "description": "Parámetros inválidos: formato de fecha incorrecto, to anterior a from o rango mayor de 366 días.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "The requested date range cannot exceed 366 days"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": true,
        "message": "Invalid or expired API Key.",
        "code": "unauthorized"
      }
    }
  }
}
POST/employees/time-entriesAñadir fichaje
Crea un fichaje presencial. Son obligatorios `employee_id`, `start_at` y `start_type_id`. **Fichaje abierto.** Si se omite `end_at`, el fichaje queda abierto, de modo que un dispositivo externo puede registrar primero la entrada y completar la salida después con el endpoint de modificación. **Fechas.** Se interpretan como hora local del taller: `2026-08-20T08:00:00`. Se admite un indicador de zona horaria (`Z` o `+02:00`), pero **se descarta**: se guarda la fecha y hora tal cual, sin convertir de huso. **Solapes.** Si el fichaje se solapa con otro del mismo empleado se crea igualmente, pero la respuesta incluye un bloque `warnings` con los fichajes afectados.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "employee_id",
          "start_at",
          "start_type_id"
        ],
        "properties": {
          "employee_id": {
            "type": "string",
            "description": "Identificador único del empleado (obligatorio)"
          },
          "start_at": {
            "type": "string",
            "description": "Fecha y hora de entrada en hora local del taller. Formato YYYY-MM-DDTHH:MM:SS. Se admite un offset de zona horaria, pero se descarta: se toma la fecha y hora tal cual (obligatorio)"
          },
          "start_type_id": {
            "type": "integer",
            "description": "Tipo de fichaje de entrada, debe ser de sentido entry (obligatorio)"
          },
          "end_at": {
            "type": "string",
            "nullable": true,
            "description": "Fecha y hora de salida. Si se omite, el fichaje queda abierto"
          },
          "end_type_id": {
            "type": "integer",
            "nullable": true,
            "description": "Tipo de fichaje de salida, debe ser de sentido exit"
          },
          "observations": {
            "type": "string",
            "nullable": true,
            "description": "Observaciones, hasta 1500 caracteres"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Fichaje creado con éxito.
{
  "description": "Fichaje creado con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Identificador del fichaje"
          },
          "employee_id": {
            "type": "string",
            "description": "Identificador único del empleado"
          },
          "employee_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre y apellidos del empleado"
          },
          "start_at": {
            "type": "string",
            "description": "Fecha y hora de entrada, hora local del taller, sin desfase horario"
          },
          "end_at": {
            "type": "string",
            "nullable": true,
            "description": "Fecha y hora de salida. Nulo indica que el fichaje sigue abierto"
          },
          "start_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "end_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "observations": {
            "type": "string",
            "nullable": true
          },
          "warnings": {
            "type": "array",
            "description": "Solo en alta y modificación, si el fichaje se solapa con otro del mismo empleado",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "time_entry_ids": {
                  "type": "array",
                  "items": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Datos inválidos: faltan campos obligatorios, el empleado o el tipo no existen, el tipo no es del sentido correcto, o las fechas no son coherentes.
{
  "description": "Datos inválidos: faltan campos obligatorios, el empleado o el tipo no existen, el tipo no es del sentido correcto, o las fechas no son coherentes.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "end_at cannot be earlier than start_at"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": true,
        "message": "Invalid or expired API Key.",
        "code": "unauthorized"
      }
    }
  }
}
GET/employees/time-entries/{id}Consultar un fichaje
Devuelve un fichaje concreto por su identificador, con la misma estructura que el listado. Un fichaje de otro taller o borrado devuelve 404.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
idpathSíIdentificador del fichaje.
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 · Fichaje encontrado.
{
  "description": "Fichaje encontrado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Identificador del fichaje"
          },
          "employee_id": {
            "type": "string",
            "description": "Identificador único del empleado"
          },
          "employee_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre y apellidos del empleado"
          },
          "start_at": {
            "type": "string",
            "description": "Fecha y hora de entrada, hora local del taller, sin desfase horario"
          },
          "end_at": {
            "type": "string",
            "nullable": true,
            "description": "Fecha y hora de salida. Nulo indica que el fichaje sigue abierto"
          },
          "start_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "end_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "observations": {
            "type": "string",
            "nullable": true
          },
          "warnings": {
            "type": "array",
            "description": "Solo en alta y modificación, si el fichaje se solapa con otro del mismo empleado",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "time_entry_ids": {
                  "type": "array",
                  "items": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": true,
        "message": "Invalid or expired API Key.",
        "code": "unauthorized"
      }
    }
  }
}
HTTP 404 · Fichaje no encontrado en este taller.
{
  "description": "Fichaje no encontrado en este taller.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Time entry not found with ID: 352699"
        }
      }
    }
  }
}
PUT/employees/time-entries/{id}Modificar o corregir fichaje
Corrige un fichaje existente. **Solo hay que enviar los campos que se quieran modificar**; los ausentes no se tocan. El caso más habitual es el empleado que olvidó fichar la salida: ```json {"end_at": "2026-08-20T14:07:00", "end_type_id": 98331} ``` **Reabrir un fichaje.** Enviar `end_at` con valor `null` limpia la hora de salida y también el tipo de salida, dejando el fichaje abierto de nuevo. Sirve para deshacer un cierre equivocado. La coherencia se comprueba sobre el resultado final, no solo sobre lo enviado: si se envía únicamente `end_at`, se compara con la hora de entrada que ya tiene el fichaje. El empleado de un fichaje no se puede cambiar. Devuelve el fichaje completo después de aplicar la modificación.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
idpathSíIdentificador del fichaje que se quiere corregir.
{
  "type": "integer"
}

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Modificación parcial: solo se tocan los campos presentes. Un null explícito en end_at reabre el fichaje y limpia también el tipo de salida.",
        "properties": {
          "start_at": {
            "type": "string",
            "description": "Nueva fecha y hora de entrada"
          },
          "start_type_id": {
            "type": "integer",
            "description": "Nuevo tipo de entrada"
          },
          "end_at": {
            "type": "string",
            "nullable": true,
            "description": "Nueva fecha y hora de salida. Enviar null reabre el fichaje"
          },
          "end_type_id": {
            "type": "integer",
            "nullable": true,
            "description": "Nuevo tipo de salida"
          },
          "observations": {
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Fichaje corregido con éxito.
{
  "description": "Fichaje corregido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Identificador del fichaje"
          },
          "employee_id": {
            "type": "string",
            "description": "Identificador único del empleado"
          },
          "employee_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre y apellidos del empleado"
          },
          "start_at": {
            "type": "string",
            "description": "Fecha y hora de entrada, hora local del taller, sin desfase horario"
          },
          "end_at": {
            "type": "string",
            "nullable": true,
            "description": "Fecha y hora de salida. Nulo indica que el fichaje sigue abierto"
          },
          "start_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "end_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "observations": {
            "type": "string",
            "nullable": true
          },
          "warnings": {
            "type": "array",
            "description": "Solo en alta y modificación, si el fichaje se solapa con otro del mismo empleado",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "time_entry_ids": {
                  "type": "array",
                  "items": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Datos inválidos o sin campos que actualizar.
{
  "description": "Datos inválidos o sin campos que actualizar.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "No valid fields provided for update"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": true,
        "message": "Invalid or expired API Key.",
        "code": "unauthorized"
      }
    }
  }
}
HTTP 404 · Fichaje no encontrado en este taller.
{
  "description": "Fichaje no encontrado en este taller.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Time entry not found with ID: 352699"
        }
      }
    }
  }
}

Ordenes

GET/repair-ordersListado de órdenes de reparación
Obtiene un listado paginado de órdenes de reparación

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer"
}
per_pagequeryNoElementos por página
{
  "type": "integer"
}
client_idqueryNoIdentificador único de cliente
{
  "type": "string"
}
vehicle_idqueryNoIdenfitificador único de vehículo
{
  "type": "string"
}
order_numberqueryNoNúmero de orden de reparación
{
  "type": "string"
}
from_datequeryNoFecha desde (yyyy-mm-dd).
{
  "type": "string"
}
to_datequeryNoFecha hasta (yyyy-mm-dd).
{
  "type": "string"
}
deletedqueryNoIncluir órdenes eliminadas (por defecto false).
{
  "type": "boolean"
}
closedqueryNoFiltrar por estado: true para cerradas, false para abiertas.
{
  "type": "boolean"
}
platequeryNoMatrícula
{
  "type": "string"
}
vinqueryNoNº Bastidor
{
  "type": "string"
}
makequeryNoMarca vehículo
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de órdenes de reparación
{
  "description": "Listado de órdenes de reparación",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Orden de reparacion en vista de lista.",
              "properties": {
                "entry_id": {
                  "type": "string"
                },
                "order_number": {
                  "type": "string",
                  "nullable": true
                },
                "entry_date": {
                  "type": "string",
                  "nullable": true,
                  "description": "DD/MM/YYYY"
                },
                "client_id": {
                  "type": "string",
                  "nullable": true
                },
                "plate": {
                  "type": "string",
                  "nullable": true
                },
                "vin": {
                  "type": "string",
                  "nullable": true
                },
                "vehicle_id": {
                  "type": "string",
                  "nullable": true
                },
                "total_amount_vat_included": {
                  "type": "number"
                },
                "currency": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "nullable": true
                },
                "deleted": {
                  "type": "boolean"
                },
                "is_closed": {
                  "type": "boolean"
                },
                "service_status_id": {
                  "type": "string",
                  "nullable": true
                },
                "service_status_name": {
                  "type": "string",
                  "nullable": true
                },
                "pdf": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
POST/repair-ordersCrear orden de reparación
Crea una orden de reparación. Son obligatorios `client_id` y `vehicle_id` (los identificadores que devuelven los listados de clientes y vehículos); `insurance_company_id` es el identificador del listado de aseguradoras. El identificador y el número de orden se generan automáticamente (el número sigue la serie del taller), el IVA y la divisa se toman de la configuración del taller, y la orden se crea abierta con pagador cliente por defecto. Si no se envía `entry_date`, se usa la fecha actual. Las fechas van en formato DD/MM/YYYY. Los campos de estado (`is_closed`, `service_status_id`, `percentage_completed`, `exit_date`) solo se aceptan en la modificación. Devuelve la orden creada con la misma estructura que el detalle del GET.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "client_id",
          "vehicle_id"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "Identificador del cliente (obligatorio)"
          },
          "vehicle_id": {
            "type": "string",
            "description": "Identificador del vehiculo (obligatorio)"
          },
          "insurance_company_id": {
            "type": "string",
            "description": "Identificador de la aseguradora"
          },
          "entry_date": {
            "type": "string",
            "description": "Fecha de entrada DD/MM/YYYY (por defecto, hoy)"
          },
          "delivery_date": {
            "type": "string",
            "description": "Fecha de entrega prevista DD/MM/YYYY"
          },
          "kilometres": {
            "type": "string",
            "description": "Kilometros del vehiculo"
          },
          "breakdown_description": {
            "type": "string",
            "description": "Descripcion de la averia"
          },
          "observations": {
            "type": "string",
            "description": "Observaciones"
          },
          "incident_number": {
            "type": "string",
            "description": "Numero de siniestro"
          },
          "insurance_deductible_amount": {
            "type": "number",
            "description": "Franquicia del seguro"
          },
          "payer_type_id": {
            "type": "integer",
            "description": "Pagador: 1=cliente (por defecto), 2=aseguradora, 3=leasing, 4=otro cliente"
          },
          "fuel_level_id": {
            "type": "integer",
            "description": "Nivel de combustible: 0=lleno, 1=3/4, 2=1/2, 3=1/4, 4=reserva"
          },
          "collect_replaced_parts": {
            "type": "boolean",
            "description": "Recoger piezas sustituidas"
          },
          "notify_unforeseen_budget": {
            "type": "boolean",
            "description": "Avisar si surge presupuesto imprevisto"
          },
          "next_revision_date": {
            "type": "string",
            "description": "Proxima revision: fecha DD/MM/YYYY"
          },
          "next_revision_km": {
            "type": "integer",
            "description": "Proxima revision: kilometros"
          },
          "next_revision_description": {
            "type": "string",
            "description": "Proxima revision: descripcion"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Orden de reparación creada con éxito.
{
  "description": "Orden de reparación creada con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Misma estructura que el detalle de GET /repair-orders/{entry_id}: datos de la orden, cliente, vehiculo, importes y lineas (parts, labor, paint, other, wheels), documentos y recursos.",
        "properties": {
          "entry_id": {
            "type": "string"
          },
          "order_number": {
            "type": "string"
          },
          "breakdown_description": {
            "type": "string"
          },
          "observations": {
            "type": "string"
          },
          "kilometres": {
            "type": "string"
          },
          "is_closed": {
            "type": "string"
          },
          "percentage_completed": {
            "type": "string",
            "nullable": true
          },
          "service_status_id": {
            "type": "string",
            "nullable": true
          },
          "vat_percentage_summary": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "entry_date_formatted": {
            "type": "string"
          },
          "delivery_date_formatted": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "client_full_name": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "vin": {
            "type": "string"
          },
          "payer_type_id": {
            "type": "string"
          },
          "fuel_level_id": {
            "type": "string"
          },
          "fuel_level_name": {
            "type": "string"
          },
          "insurance_company_id": {
            "type": "string",
            "nullable": true
          },
          "next_revision_km_entry_level": {
            "type": "string",
            "nullable": true
          },
          "parts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "labor": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "paint": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "other": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "wheels": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 · Datos inválidos (p. ej. falta client_id o vehicle_id, o no existen para el taller).
{
  "description": "Datos inválidos (p. ej. falta client_id o vehicle_id, o no existen para el taller).",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "client_id is required",
          "vehicle_id is required"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
GET/repair-orders/{entry_id}Detalle de una orden de reparación de taller
Obtiene todos los datos relacionados con una orden específica de taller.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
entry_idpathSíIdentificador único de la entrada de taller
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Detalle de la entrada de taller
{
  "description": "Detalle de la entrada de taller",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de una orden de reparacion.",
        "properties": {
          "entry_id": {
            "type": "string"
          },
          "order_number": {
            "type": "string"
          },
          "is_valued": {
            "type": "string"
          },
          "breakdown_description": {
            "type": "string",
            "nullable": true
          },
          "observations": {
            "type": "string",
            "nullable": true
          },
          "incident_number": {
            "type": "string",
            "nullable": true
          },
          "kilometres": {
            "type": "string",
            "nullable": true
          },
          "is_closed": {
            "type": "string"
          },
          "is_vat_integrated_in_prices": {
            "type": "string"
          },
          "is_not_billable": {
            "type": "string"
          },
          "is_blocked_flag": {
            "type": "string"
          },
          "percentage_completed": {
            "type": "string",
            "nullable": true
          },
          "order_global_discount_percentage": {
            "type": "string"
          },
          "vat_percentage_summary": {
            "type": "string"
          },
          "total_amount_net_from_entry": {
            "type": "number"
          },
          "total_amount_vat_incl_from_entry": {
            "type": "number"
          },
          "entry_date_formatted": {
            "type": "string"
          },
          "entry_datetime_formatted": {
            "type": "string"
          },
          "exit_datetime_formatted": {
            "type": "string",
            "nullable": true
          },
          "delivery_date_formatted": {
            "type": "string",
            "nullable": true
          },
          "delivery_datetime_formatted": {
            "type": "string",
            "nullable": true
          },
          "created_at_datetime_formatted": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "currency_decimals": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "client_full_name": {
            "type": "string"
          },
          "billing_client_id": {
            "type": "string",
            "nullable": true
          },
          "vehicle_id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "vin": {
            "type": "string"
          },
          "service_status_id": {
            "type": "string",
            "nullable": true
          },
          "service_status_name": {
            "type": "string",
            "nullable": true
          },
          "budget_id": {
            "type": "string",
            "nullable": true
          },
          "budget_number": {
            "type": "string",
            "nullable": true
          },
          "associated_invoice_id": {
            "type": "string"
          },
          "associated_invoice_number": {
            "type": "string"
          },
          "parts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "labor": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "paint": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "other": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "wheels": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "package_parents": {
            "type": "string"
          },
          "resources": {
            "type": "object"
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
PUT/repair-orders/{entry_id}Actualizar orden de reparación
Actualiza una orden de reparación existente. Solo se modifican los campos enviados en el cuerpo. Con `is_closed` se cierra (la fecha de cierre se pone automáticamente) o se reabre la orden; `service_status_id` cambia el estado de servicio y `percentage_completed` el porcentaje completado. Devuelve la orden actualizada.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
entry_idpathSíIdentificador único de la orden de reparación.
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "insurance_company_id": {
            "type": "string"
          },
          "entry_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "delivery_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "exit_date": {
            "type": "string",
            "description": "Fecha de salida DD/MM/YYYY"
          },
          "kilometres": {
            "type": "string"
          },
          "breakdown_description": {
            "type": "string"
          },
          "observations": {
            "type": "string"
          },
          "incident_number": {
            "type": "string"
          },
          "insurance_deductible_amount": {
            "type": "number"
          },
          "payer_type_id": {
            "type": "integer",
            "description": "1=cliente, 2=aseguradora, 3=leasing, 4=otro cliente"
          },
          "fuel_level_id": {
            "type": "integer",
            "description": "0=lleno, 1=3/4, 2=1/2, 3=1/4, 4=reserva"
          },
          "collect_replaced_parts": {
            "type": "boolean"
          },
          "notify_unforeseen_budget": {
            "type": "boolean"
          },
          "next_revision_date": {
            "type": "string",
            "description": "DD/MM/YYYY"
          },
          "next_revision_km": {
            "type": "integer"
          },
          "next_revision_description": {
            "type": "string"
          },
          "is_closed": {
            "type": "boolean",
            "description": "true cierra la orden (la fecha de cierre se pone automaticamente), false la reabre"
          },
          "service_status_id": {
            "type": "integer",
            "description": "Estado de servicio (catalogo de estados)"
          },
          "percentage_completed": {
            "type": "integer",
            "description": "Porcentaje completado (0-100)"
          }
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Orden de reparación actualizada con éxito.
{
  "description": "Orden de reparación actualizada con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Misma estructura que el detalle de GET /repair-orders/{entry_id}: datos de la orden, cliente, vehiculo, importes y lineas (parts, labor, paint, other, wheels), documentos y recursos.",
        "properties": {
          "entry_id": {
            "type": "string"
          },
          "order_number": {
            "type": "string"
          },
          "breakdown_description": {
            "type": "string"
          },
          "observations": {
            "type": "string"
          },
          "kilometres": {
            "type": "string"
          },
          "is_closed": {
            "type": "string"
          },
          "percentage_completed": {
            "type": "string",
            "nullable": true
          },
          "service_status_id": {
            "type": "string",
            "nullable": true
          },
          "vat_percentage_summary": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "entry_date_formatted": {
            "type": "string"
          },
          "delivery_date_formatted": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "client_full_name": {
            "type": "string"
          },
          "vehicle_id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "vin": {
            "type": "string"
          },
          "payer_type_id": {
            "type": "string"
          },
          "fuel_level_id": {
            "type": "string"
          },
          "fuel_level_name": {
            "type": "string"
          },
          "insurance_company_id": {
            "type": "string",
            "nullable": true
          },
          "next_revision_km_entry_level": {
            "type": "string",
            "nullable": true
          },
          "parts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "labor": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "paint": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "other": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "wheels": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 400 · Datos inválidos o sin campos que actualizar.
{
  "description": "Datos inválidos o sin campos que actualizar.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "percentage_completed must be between 0 and 100"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": "Token no valido o no autorizado"
      }
    }
  }
}
HTTP 404 · Orden de reparación no encontrada.
{
  "description": "Orden de reparación no encontrada.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Repair order not found"
        }
      }
    }
  }
}

Facturas

GET/invoicesListado de facturas
Obtiene un listado paginado de facturas registradas en el sistema. **Requiere autenticación con token Bearer.**

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoElementos por página
{
  "type": "integer",
  "default": 10
}
client_idqueryNoIdentificador único de cliente
{
  "type": "string"
}
vehicle_idqueryNoIdenfitificador único de vehículo
{
  "type": "string"
}
invoice_numberqueryNoNúmero de factura
{
  "type": "string"
}
from_datequeryNoFecha desde (yyyy-mm-dd).
{
  "type": "string"
}
to_datequeryNoFecha hasta (yyyy-mm-dd).
{
  "type": "string"
}
deletedqueryNoIncluir facturas eliminadas (por defecto false).
{
  "type": "boolean",
  "default": false
}
platequeryNoMatrícula
{
  "type": "string"
}
vinqueryNoNº Bastidor
{
  "type": "string"
}
makequeryNoMarca vehículo
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de facturas con paginación
{
  "description": "Listado de facturas con paginación",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Factura en vista de lista.",
              "properties": {
                "invoice_id": {
                  "type": "string"
                },
                "invoice_number": {
                  "type": "string"
                },
                "date": {
                  "type": "string",
                  "description": "DD/MM/YYYY"
                },
                "payer_info": {
                  "type": "object",
                  "properties": {
                    "payer": {
                      "type": "integer"
                    },
                    "payer_id": {
                      "type": "string"
                    }
                  }
                },
                "client_id": {
                  "type": "string"
                },
                "vehicle_id": {
                  "type": "string"
                },
                "plate": {
                  "type": "string"
                },
                "vin": {
                  "type": "string"
                },
                "client_name": {
                  "type": "string"
                },
                "total_amount_with_vat": {
                  "type": "number"
                },
                "total_amount_without_vat": {
                  "type": "number"
                },
                "status_name": {
                  "type": "string"
                },
                "currency": {
                  "type": "string"
                },
                "accounted": {
                  "type": "boolean"
                },
                "blocked": {
                  "type": "boolean"
                },
                "deleted": {
                  "type": "boolean"
                },
                "pdf": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado (token inválido o ausente)
{
  "description": "No autorizado (token inválido o ausente)",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/invoices/{invoice_id}Detalle de una factura
Obtiene el detalle completo de una factura específica, incluyendo las líneas de factura por tipo (repuestos, mano de obra, etc). ### Parámetro requerido: - `invoice_id`: ID único de la factura. **Requiere autenticación con token Bearer.**

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
invoice_idpathSíIdentificador único de la factura.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Detalle completo de la factura incluyendo sus líneas.
{
  "description": "Detalle completo de la factura incluyendo sus líneas.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de una factura con lineas, recursos y documentos.",
        "properties": {
          "invoice_id": {
            "type": "string"
          },
          "invoice_number": {
            "type": "string"
          },
          "date": {
            "type": "string"
          },
          "payer_info": {
            "type": "object"
          },
          "client_id": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "total_amount_with_vat": {
            "type": "number"
          },
          "total_amount_without_vat": {
            "type": "number"
          },
          "pending_amount": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "status_name": {
            "type": "string"
          },
          "accounted": {
            "type": "boolean"
          },
          "blocked": {
            "type": "boolean"
          },
          "deleted": {
            "type": "string"
          },
          "billing_client_unique_id": {
            "type": "string",
            "nullable": true
          },
          "vehicle_id": {
            "type": "string"
          },
          "plate": {
            "type": "string"
          },
          "vin": {
            "type": "string"
          },
          "vehicle_description": {
            "type": "string"
          },
          "subtotal_net_amount": {
            "type": "string"
          },
          "total_tax_amount": {
            "type": "string"
          },
          "tax_rate_summary": {
            "type": "string"
          },
          "payment_terms_name": {
            "type": "string",
            "nullable": true
          },
          "payment_method_name": {
            "type": "string"
          },
          "observations": {
            "type": "string",
            "nullable": true
          },
          "series_name": {
            "type": "string"
          },
          "created_by_user": {
            "type": "string"
          },
          "created_at_formatted": {
            "type": "string"
          },
          "total_parts_amount_with_discount": {
            "type": "number"
          },
          "total_labor_amount_with_discount": {
            "type": "number"
          },
          "total_others_amount_with_discount": {
            "type": "number"
          },
          "total_paint_amount_with_discount": {
            "type": "number"
          },
          "total_tyres_amount_with_discount": {
            "type": "number"
          },
          "global_discount_amount": {
            "type": "number"
          },
          "global_discount_percentage": {
            "type": "string"
          },
          "status_code": {
            "type": "string"
          },
          "status_name_detail": {
            "type": "string"
          },
          "status_color": {
            "type": "string"
          },
          "lines": {
            "type": "object",
            "properties": {
              "parts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Linea de factura.",
                  "properties": {
                    "reference": {
                      "type": "string",
                      "nullable": true
                    },
                    "description": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "string"
                    },
                    "unit_price": {
                      "type": "string"
                    },
                    "discount_percentage": {
                      "type": "string"
                    },
                    "tax_rate": {
                      "type": "string"
                    },
                    "total_with_discount": {
                      "type": "string"
                    },
                    "line_type_code": {
                      "type": "string"
                    },
                    "employee_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "employee_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "work_date": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_disbursement": {
                      "type": "boolean"
                    },
                    "visible": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "labors": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Linea de factura.",
                  "properties": {
                    "reference": {
                      "type": "string",
                      "nullable": true
                    },
                    "description": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "string"
                    },
                    "unit_price": {
                      "type": "string"
                    },
                    "discount_percentage": {
                      "type": "string"
                    },
                    "tax_rate": {
                      "type": "string"
                    },
                    "total_with_discount": {
                      "type": "string"
                    },
                    "line_type_code": {
                      "type": "string"
                    },
                    "employee_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "employee_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "work_date": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_disbursement": {
                      "type": "boolean"
                    },
                    "visible": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "others": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Linea de factura.",
                  "properties": {
                    "reference": {
                      "type": "string",
                      "nullable": true
                    },
                    "description": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "string"
                    },
                    "unit_price": {
                      "type": "string"
                    },
                    "discount_percentage": {
                      "type": "string"
                    },
                    "tax_rate": {
                      "type": "string"
                    },
                    "total_with_discount": {
                      "type": "string"
                    },
                    "line_type_code": {
                      "type": "string"
                    },
                    "employee_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "employee_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "work_date": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_disbursement": {
                      "type": "boolean"
                    },
                    "visible": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "paints": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Linea de factura.",
                  "properties": {
                    "reference": {
                      "type": "string",
                      "nullable": true
                    },
                    "description": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "string"
                    },
                    "unit_price": {
                      "type": "string"
                    },
                    "discount_percentage": {
                      "type": "string"
                    },
                    "tax_rate": {
                      "type": "string"
                    },
                    "total_with_discount": {
                      "type": "string"
                    },
                    "line_type_code": {
                      "type": "string"
                    },
                    "employee_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "employee_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "work_date": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_disbursement": {
                      "type": "boolean"
                    },
                    "visible": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "tyres": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Linea de factura.",
                  "properties": {
                    "reference": {
                      "type": "string",
                      "nullable": true
                    },
                    "description": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "string"
                    },
                    "unit_price": {
                      "type": "string"
                    },
                    "discount_percentage": {
                      "type": "string"
                    },
                    "tax_rate": {
                      "type": "string"
                    },
                    "total_with_discount": {
                      "type": "string"
                    },
                    "line_type_code": {
                      "type": "string"
                    },
                    "employee_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "employee_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "work_date": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_disbursement": {
                      "type": "boolean"
                    },
                    "visible": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "resources": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "pdf": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado (token inválido o ausente)
{
  "description": "No autorizado (token inválido o ausente)",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Factura no encontrada.
{
  "description": "Factura no encontrada.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}

Materiales

GET/materialsObtiene un listado de materiales
Devuelve una lista paginada de materiales almacenados en el sistema.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página para la paginación.
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoNúmero de materiales por página.
{
  "type": "integer",
  "default": 10
}
material_refqueryNoReferencial del material
{
  "type": "string",
  "default": ""
}

Respuestas documentadas

HTTP 200 · Listado de materiales obtenido con éxito.
{
  "description": "Listado de materiales obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Material en vista de lista.",
              "properties": {
                "material_id": {
                  "type": "string"
                },
                "reference": {
                  "type": "string",
                  "nullable": true
                },
                "serial_number": {
                  "type": "string",
                  "nullable": true
                },
                "name": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "cost": {
                  "type": "number"
                },
                "pvp": {
                  "type": "number"
                },
                "alert_threshold": {
                  "type": "number",
                  "nullable": true
                },
                "discount1": {
                  "type": "number"
                },
                "discount2": {
                  "type": "number"
                },
                "margin": {
                  "type": "number"
                },
                "tax_rate": {
                  "type": "number"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
POST/materialsCrear material
Da de alta un nuevo material. Los campos obligatorios son `reference` y `description`. La `reference` se guarda en mayusculas (sin espacios al inicio/fin) y debe ser unica por taller; si ya existe se devuelve un error 400. Si se informa `quantity` (stock inicial), ademas de crear el material se genera automaticamente un movimiento de entrada en el almacen.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "Datos del nuevo material. Los campos `reference` y `description` son obligatorios. Si se informa `quantity`, se registra como stock inicial.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "reference",
          "description"
        ],
        "properties": {
          "reference": {
            "type": "string",
            "description": "Referencia o codigo del material. Se almacena en mayusculas y sin espacios al inicio/fin. Debe ser unica por taller."
          },
          "description": {
            "type": "string",
            "description": "Nombre o descripcion del material (se acepta tambien el alias name)."
          },
          "serial_number": {
            "type": "string",
            "description": "Numero de serie del material"
          },
          "quantity": {
            "type": "integer",
            "description": "Stock inicial. Si se informa (>0) se genera automaticamente un movimiento de entrada en el almacen.",
            "default": 0
          },
          "cost": {
            "type": "number",
            "format": "float",
            "description": "Coste unitario"
          },
          "pvp": {
            "type": "number",
            "format": "float",
            "description": "Precio de venta al publico"
          },
          "alert_threshold": {
            "type": "integer",
            "description": "Umbral de alerta de stock minimo"
          },
          "discount1": {
            "type": "number",
            "format": "float",
            "description": "Primer porcentaje de descuento"
          },
          "discount2": {
            "type": "number",
            "format": "float",
            "description": "Segundo porcentaje de descuento"
          },
          "margin": {
            "type": "number",
            "format": "float",
            "description": "Margen de beneficio (porcentaje)"
          },
          "tax_rate": {
            "type": "number",
            "format": "float",
            "description": "Porcentaje de IVA"
          }
        }
      },
      "example": {
        "reference": "FILT-1234",
        "description": "Filtro de aceite",
        "cost": 3.9,
        "pvp": 10.72,
        "tax_rate": 21,
        "quantity": 5
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Material creado correctamente. Devuelve el material con su stock y movimientos.
{
  "description": "Material creado correctamente. Devuelve el material con su stock y movimientos.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un material con movimientos y fotos.",
        "properties": {
          "material_id": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "serial_number": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "cost": {
            "type": "number"
          },
          "pvp": {
            "type": "number"
          },
          "alert_threshold": {
            "type": "number",
            "nullable": true
          },
          "discount1": {
            "type": "number"
          },
          "discount2": {
            "type": "number"
          },
          "margin": {
            "type": "number"
          },
          "tax_rate": {
            "type": "number"
          },
          "stock_movements": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Movimiento de stock de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "movement_date": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "entry_id": {
                  "type": "string",
                  "nullable": true
                },
                "sales_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "invoice_id": {
                  "type": "string",
                  "nullable": true
                },
                "ticket_id": {
                  "type": "string",
                  "nullable": true
                },
                "purchase_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "description": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Foto de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "unique_code": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "document_type_id": {
                  "type": "string",
                  "nullable": true
                },
                "file_name": {
                  "type": "string"
                },
                "width": {
                  "type": "integer",
                  "nullable": true
                },
                "height": {
                  "type": "integer",
                  "nullable": true
                },
                "url": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Error de validacion (faltan campos obligatorios) o referencia duplicada.
{
  "description": "Error de validacion (faltan campos obligatorios) o referencia duplicada.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autenticado o token invalido
{
  "description": "No autenticado o token invalido",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/materials/{material_id}Obtiene el detalle de un material
Devuelve la información detallada de un material, incluyendo movimientos de stock y fotos.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
material_idpathSíIdentificador único del material.
{
  "type": "string",
  "example": "q9p0zwzfc8csui2xngah3ma1x456yenr"
}

Respuestas documentadas

HTTP 200 · Detalle del material obtenido con éxito.
{
  "description": "Detalle del material obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un material con movimientos y fotos.",
        "properties": {
          "material_id": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "serial_number": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "cost": {
            "type": "number"
          },
          "pvp": {
            "type": "number"
          },
          "alert_threshold": {
            "type": "number",
            "nullable": true
          },
          "discount1": {
            "type": "number"
          },
          "discount2": {
            "type": "number"
          },
          "margin": {
            "type": "number"
          },
          "tax_rate": {
            "type": "number"
          },
          "stock_movements": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Movimiento de stock de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "movement_date": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "entry_id": {
                  "type": "string",
                  "nullable": true
                },
                "sales_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "invoice_id": {
                  "type": "string",
                  "nullable": true
                },
                "ticket_id": {
                  "type": "string",
                  "nullable": true
                },
                "purchase_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "description": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Foto de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "unique_code": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "document_type_id": {
                  "type": "string",
                  "nullable": true
                },
                "file_name": {
                  "type": "string"
                },
                "width": {
                  "type": "integer",
                  "nullable": true
                },
                "height": {
                  "type": "integer",
                  "nullable": true
                },
                "url": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · No se encontró el material con el identificador especificado.
{
  "description": "No se encontró el material con el identificador especificado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
PUT/materials/{material_id}Modificar material
Actualiza los datos de un material existente. El material se localiza por `material_id` o por su referencia (en el segmento de la ruta). La `reference` no se puede modificar; si se usa para localizar, solo actua como criterio de busqueda. Si se incluye `quantity`, se calcula la diferencia con el stock actual, se actualiza el stock y se genera el movimiento de almacen correspondiente (entrada o salida).

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
material_idpathSíIdentificador del material (material_id). Tambien se acepta la referencia del material como valor del segmento.
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "Campos a actualizar del material. Solo se modifican los campos incluidos. La referencia no se puede modificar. Si se incluye `quantity`, ajusta el stock generando el movimiento de la diferencia.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Nombre o descripcion del material (alias: name)"
          },
          "serial_number": {
            "type": "string",
            "description": "Numero de serie del material"
          },
          "quantity": {
            "type": "integer",
            "description": "Nuevo stock deseado. Se calcula la diferencia con el stock actual y se genera el movimiento correspondiente."
          },
          "cost": {
            "type": "number",
            "format": "float",
            "description": "Coste unitario"
          },
          "pvp": {
            "type": "number",
            "format": "float",
            "description": "Precio de venta al publico"
          },
          "alert_threshold": {
            "type": "integer",
            "description": "Umbral de alerta de stock minimo"
          },
          "discount1": {
            "type": "number",
            "format": "float",
            "description": "Primer porcentaje de descuento"
          },
          "discount2": {
            "type": "number",
            "format": "float",
            "description": "Segundo porcentaje de descuento"
          },
          "margin": {
            "type": "number",
            "format": "float",
            "description": "Margen de beneficio (porcentaje)"
          },
          "tax_rate": {
            "type": "number",
            "format": "float",
            "description": "Porcentaje de IVA"
          }
        }
      },
      "example": {
        "pvp": 12.5,
        "quantity": 7
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Material actualizado correctamente. Devuelve el material con su stock y movimientos.
{
  "description": "Material actualizado correctamente. Devuelve el material con su stock y movimientos.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un material con movimientos y fotos.",
        "properties": {
          "material_id": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "serial_number": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "cost": {
            "type": "number"
          },
          "pvp": {
            "type": "number"
          },
          "alert_threshold": {
            "type": "number",
            "nullable": true
          },
          "discount1": {
            "type": "number"
          },
          "discount2": {
            "type": "number"
          },
          "margin": {
            "type": "number"
          },
          "tax_rate": {
            "type": "number"
          },
          "stock_movements": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Movimiento de stock de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "movement_date": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "entry_id": {
                  "type": "string",
                  "nullable": true
                },
                "sales_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "invoice_id": {
                  "type": "string",
                  "nullable": true
                },
                "ticket_id": {
                  "type": "string",
                  "nullable": true
                },
                "purchase_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "description": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Foto de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "unique_code": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "document_type_id": {
                  "type": "string",
                  "nullable": true
                },
                "file_name": {
                  "type": "string"
                },
                "width": {
                  "type": "integer",
                  "nullable": true
                },
                "height": {
                  "type": "integer",
                  "nullable": true
                },
                "url": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Error de validacion: no se proporcionaron campos validos para actualizar.
{
  "description": "Error de validacion: no se proporcionaron campos validos para actualizar.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autenticado o token invalido
{
  "description": "No autenticado o token invalido",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Material no encontrado
{
  "description": "Material no encontrado",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
GET/materials/{material_id}/movementsListado de movimientos de stock de un material
Devuelve una lista paginada de los movimientos de stock asociados a un material.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página para la paginación.
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoNúmero de movimientos por página.
{
  "type": "integer",
  "default": 10
}
material_idpathSíIdentificador único del material.
{
  "type": "string",
  "example": "q9p0zwzfc8csui2xngah3ma1x456yenr"
}

Respuestas documentadas

HTTP 200 · Listado de movimientos de stock obtenido con éxito.
{
  "description": "Listado de movimientos de stock obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Movimiento de stock de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "movement_date": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "entry_id": {
                  "type": "string",
                  "nullable": true
                },
                "sales_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "invoice_id": {
                  "type": "string",
                  "nullable": true
                },
                "ticket_id": {
                  "type": "string",
                  "nullable": true
                },
                "purchase_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "description": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
POST/materials/{material_id}/movementsAnadir movimiento de stock
Registra un movimiento de stock sobre un material existente. El material se localiza por `material_id` o por su referencia. Se envia el `quantity` como **stock resultante deseado**: se calcula la diferencia con el stock actual, se genera el movimiento de almacen por dicha diferencia y se actualiza el stock acumulado del material.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
material_idpathSíIdentificador del material (material_id). Tambien se acepta la referencia del material como valor del segmento.
{
  "type": "string"
}

Cuerpo de la petición

{
  "required": true,
  "description": "Stock resultante deseado para el material. Se genera el movimiento de almacen por la diferencia respecto al stock actual.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "quantity"
        ],
        "properties": {
          "quantity": {
            "type": "integer",
            "description": "Stock resultante deseado. Se calcula la diferencia con el stock actual y se genera un movimiento de almacen por dicha diferencia."
          },
          "reference": {
            "type": "string",
            "description": "Referencia del material, como localizador alternativo si no se usa el material_id en la ruta."
          }
        }
      },
      "example": {
        "quantity": 12
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Movimiento registrado correctamente. Devuelve el material con su stock actualizado y movimientos.
{
  "description": "Movimiento registrado correctamente. Devuelve el material con su stock actualizado y movimientos.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Detalle completo de un material con movimientos y fotos.",
        "properties": {
          "material_id": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "serial_number": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "cost": {
            "type": "number"
          },
          "pvp": {
            "type": "number"
          },
          "alert_threshold": {
            "type": "number",
            "nullable": true
          },
          "discount1": {
            "type": "number"
          },
          "discount2": {
            "type": "number"
          },
          "margin": {
            "type": "number"
          },
          "tax_rate": {
            "type": "number"
          },
          "stock_movements": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Movimiento de stock de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "movement_date": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "entry_id": {
                  "type": "string",
                  "nullable": true
                },
                "sales_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "invoice_id": {
                  "type": "string",
                  "nullable": true
                },
                "ticket_id": {
                  "type": "string",
                  "nullable": true
                },
                "purchase_delivery_note_id": {
                  "type": "string",
                  "nullable": true
                },
                "description": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Foto de un material.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "unique_code": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "document_type_id": {
                  "type": "string",
                  "nullable": true
                },
                "file_name": {
                  "type": "string"
                },
                "width": {
                  "type": "integer",
                  "nullable": true
                },
                "height": {
                  "type": "integer",
                  "nullable": true
                },
                "url": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Error de validacion: el stock resultante (quantity) es obligatorio y debe ser un entero no negativo.
{
  "description": "Error de validacion: el stock resultante (quantity) es obligatorio y debe ser un entero no negativo.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
HTTP 401 · No autenticado o token invalido
{
  "description": "No autenticado o token invalido",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Material no encontrado
{
  "description": "Material no encontrado",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}

Citas

GET/appointmentsObtiene un listado de citas
Devuelve una lista paginada de citas programadas del taller. **Búsqueda por matrícula y por teléfono.** Los filtros `plate` y `phone` buscan sobre los datos escritos en la propia cita, no sobre la ficha del cliente, porque una cita puede existir sin que el cliente esté dado de alta. Con cualquiera de los dos, las fechas dejan de hacer falta y se devuelven como máximo las 100 citas más recientes. **Tipo de cita.** Cada cita incluye `appointment_type_id` y `appointment_type_name`, nulos si no tiene tipo asignado. Las citas se devuelven ordenadas por fecha, de la más reciente a la más antigua.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página para la paginación.
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoNúmero de citas por página.
{
  "type": "integer",
  "default": 10
}
client_idqueryNoIdentificador único de cliente
{
  "type": "string"
}
vehicle_idqueryNoIdenfitificador único de vehículo
{
  "type": "string"
}
from_datequeryNoFecha desde (yyyy-mm-dd).
{
  "type": "string"
}
to_datequeryNoFecha hasta (yyyy-mm-dd).
{
  "type": "string"
}
platequeryNoMatrícula escrita en la cita. Se ignoran mayúsculas, espacios y guiones: `1234-ABC`, `1234 abc` y `1234ABC` son la misma búsqueda.
{
  "type": "string"
}
phonequeryNoTeléfono escrito en la cita. Se comparan solo los dígitos y se busca por el final, con un mínimo de 6: `600123456` encuentra `+34 600 12 34 56`. Ojo, no al revés: buscar con prefijo no encuentra los guardados sin él.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de citas obtenido con éxito.
{
  "description": "Listado de citas obtenido con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Representa una cita en el sistema.",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Identificador único de la cita."
                },
                "client_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identificador único del cliente asociado (si existe)."
                },
                "vehicle_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identificador único del vehículo asociado (si existe)."
                },
                "date": {
                  "type": "string",
                  "description": "Fecha y hora de la cita, en formato DD/MM/YYYY HH:mm.",
                  "example": "25/06/2025 13:30"
                },
                "name": {
                  "type": "string",
                  "description": "Nombre del cliente o de la persona para la cita.",
                  "example": "APELLIDO1 APELLIDO2, NOMBRE"
                },
                "phone": {
                  "type": "string",
                  "nullable": true,
                  "description": "Teléfono de contacto tal como se guardó en la cita.",
                  "example": "666666666"
                },
                "description": {
                  "type": "string",
                  "description": "Descripción o motivo de la cita.",
                  "example": "RECARGA GAS AIRE"
                },
                "plate": {
                  "type": "string",
                  "nullable": true,
                  "description": "Matrícula tal como se guardó en la cita.",
                  "example": "0000AAA"
                },
                "appointment_type_id": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Tipo de cita. Nulo si la cita no tiene tipo asignado.",
                  "example": 7
                },
                "appointment_type_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Descripción del tipo de cita. Nulo si la cita no tiene tipo asignado.",
                  "example": "Revisión"
                }
              },
              "example": {
                "id": "e6kwknqg7q9wasnxqianq9w3fehzy8j2",
                "client_id": "7pser1d252xvpoob35lky6eo36peq9xm",
                "vehicle_id": "9g3rzt5qoezoyvnq4vfa3n39h0tcvhz5",
                "date": "25/06/2025 13:30",
                "name": "APELLIDO1 APELLIDO2, NOMBRE",
                "phone": "666666666",
                "description": "RECARGA GAS AIRE",
                "plate": "0000AAA",
                "appointment_type_id": 7,
                "appointment_type_name": "Revisión"
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · Parámetros inválidos. Códigos: `phone_too_short`, `phone_too_long`, `plate_too_long`.
{
  "description": "Parámetros inválidos. Códigos: `phone_too_short`, `phone_too_long`, `plate_too_long`.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Error de validación o de regla de negocio. El campo error es un código estable: conviene programar contra él y no contra el texto de message, que puede cambiar.",
        "properties": {
          "status": {
            "type": "integer",
            "example": 400
          },
          "error": {
            "type": "string",
            "description": "Código del error.",
            "example": "appointment_type_not_found"
          },
          "message": {
            "type": "string",
            "description": "Mensaje legible.",
            "example": "El tipo de cita 7 no existe en este taller"
          },
          "errors": {
            "type": "array",
            "description": "Solo cuando hay varios mensajes de validación.",
            "items": {
              "type": "string"
            }
          },
          "user_ids": {
            "type": "array",
            "description": "Solo en user_not_found: identificadores rechazados.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "error": "phone_too_short",
        "message": "phone must contain at least 6 digits",
        "errors": [
          "phone must contain at least 6 digits"
        ]
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
POST/appointmentsCrea una nueva cita
Registra una nueva cita en el sistema. **Tipo de cita.** `appointment_type_id` es opcional. Si se envía, debe existir en el taller autenticado; si no existe, la cita **no se crea** y se devuelve el código `appointment_type_not_found`. Los valores válidos se obtienen en GET /appointment-types. **Duración.** `duration` va en horas y es opcional. Si no se envía y el tipo de cita tiene duración configurada, la cita la hereda; si se envía, manda lo que venga en la petición. **Fechas.** Se admite `DD/MM/YYYY HH:mm` y también ISO 8601 (`2026-10-03T10:30:00`).

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "Datos de la cita a crear.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Datos para crear una nueva cita. La fecha se admite en formato DD/MM/YYYY HH:mm o ISO 8601 (YYYY-MM-DDTHH:MM:SS).",
        "properties": {
          "client_id": {
            "type": "string",
            "description": "Identificador único del cliente asociado (opcional).",
            "example": "7pser1d252xvpoob35lky6eo36peq9xm"
          },
          "vehicle_id": {
            "type": "string",
            "description": "Identificador único del vehículo asociado (opcional).",
            "example": "9g3rzt5qoezoyvnq4vfa3n39h0tcvhz5"
          },
          "date": {
            "type": "string",
            "description": "Fecha y hora de la cita. DD/MM/YYYY HH:mm o ISO 8601.",
            "example": "2026-10-03T10:30:00"
          },
          "name": {
            "type": "string",
            "description": "Nombre del cliente o de la persona para la cita.",
            "example": "Laura Gómez"
          },
          "phone": {
            "type": "string",
            "description": "Teléfono de contacto.",
            "example": "600123456"
          },
          "description": {
            "type": "string",
            "description": "Descripción o motivo de la cita.",
            "example": "Revisión anual"
          },
          "plate": {
            "type": "string",
            "description": "Matrícula del vehículo.",
            "example": "1234ABC"
          },
          "appointment_type_id": {
            "type": "integer",
            "description": "Tipo de cita (opcional). Debe existir en el taller autenticado; los valores válidos se obtienen en GET /appointment-types. Si no existe, la cita no se crea.",
            "example": 7
          },
          "duration": {
            "type": "number",
            "format": "float",
            "description": "Duración de la cita en horas (opcional). Si no se envía y el tipo de cita tiene duración configurada, la cita la hereda.",
            "example": 1.5
          },
          "add_note": {
            "type": "boolean",
            "description": "Indica si se debe añadir una nota adicional (opcional).",
            "example": true
          },
          "add_schedule": {
            "type": "boolean",
            "description": "Si es true, crea además una entrada en la agenda del taller asociada a la cita. Por defecto false.",
            "example": true
          },
          "employee_id": {
            "type": "string",
            "description": "Identificador único del empleado asignado al bloque de agenda (opcional). Solo aplica si add_schedule=true. Si el empleado no existe en el taller, la entrada se crea sin asignación.",
            "example": "lm2dvv24vvfo6k08wxpnikehrhs3tkww"
          },
          "estimated_hours": {
            "type": "number",
            "format": "float",
            "description": "Duración estimada del bloque de agenda en horas (por defecto 1). Solo aplica si add_schedule=true.",
            "example": 2
          }
        },
        "required": [
          "date",
          "name",
          "phone",
          "description",
          "plate"
        ],
        "example": {
          "date": "2026-10-03T10:30:00",
          "name": "Laura Gómez",
          "phone": "600123456",
          "plate": "1234ABC",
          "description": "Revisión anual",
          "appointment_type_id": 7
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Cita creada con éxito.
{
  "description": "Cita creada con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Representa una cita en el sistema.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador único de la cita."
          },
          "client_id": {
            "type": "string",
            "nullable": true,
            "description": "Identificador único del cliente asociado (si existe)."
          },
          "vehicle_id": {
            "type": "string",
            "nullable": true,
            "description": "Identificador único del vehículo asociado (si existe)."
          },
          "date": {
            "type": "string",
            "description": "Fecha y hora de la cita, en formato DD/MM/YYYY HH:mm.",
            "example": "25/06/2025 13:30"
          },
          "name": {
            "type": "string",
            "description": "Nombre del cliente o de la persona para la cita.",
            "example": "APELLIDO1 APELLIDO2, NOMBRE"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "description": "Teléfono de contacto tal como se guardó en la cita.",
            "example": "666666666"
          },
          "description": {
            "type": "string",
            "description": "Descripción o motivo de la cita.",
            "example": "RECARGA GAS AIRE"
          },
          "plate": {
            "type": "string",
            "nullable": true,
            "description": "Matrícula tal como se guardó en la cita.",
            "example": "0000AAA"
          },
          "appointment_type_id": {
            "type": "integer",
            "nullable": true,
            "description": "Tipo de cita. Nulo si la cita no tiene tipo asignado.",
            "example": 7
          },
          "appointment_type_name": {
            "type": "string",
            "nullable": true,
            "description": "Descripción del tipo de cita. Nulo si la cita no tiene tipo asignado.",
            "example": "Revisión"
          }
        },
        "example": {
          "id": "e6kwknqg7q9wasnxqianq9w3fehzy8j2",
          "client_id": "7pser1d252xvpoob35lky6eo36peq9xm",
          "vehicle_id": "9g3rzt5qoezoyvnq4vfa3n39h0tcvhz5",
          "date": "25/06/2025 13:30",
          "name": "APELLIDO1 APELLIDO2, NOMBRE",
          "phone": "666666666",
          "description": "RECARGA GAS AIRE",
          "plate": "0000AAA",
          "appointment_type_id": 7,
          "appointment_type_name": "Revisión"
        }
      }
    }
  }
}
HTTP 400 · Solicitud incorrecta. Verifique los datos enviados.
{
  "description": "Solicitud incorrecta. Verifique los datos enviados.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Error de validación o de regla de negocio. El campo error es un código estable: conviene programar contra él y no contra el texto de message, que puede cambiar.",
        "properties": {
          "status": {
            "type": "integer",
            "example": 400
          },
          "error": {
            "type": "string",
            "description": "Código del error.",
            "example": "appointment_type_not_found"
          },
          "message": {
            "type": "string",
            "description": "Mensaje legible.",
            "example": "El tipo de cita 7 no existe en este taller"
          },
          "errors": {
            "type": "array",
            "description": "Solo cuando hay varios mensajes de validación.",
            "items": {
              "type": "string"
            }
          },
          "user_ids": {
            "type": "array",
            "description": "Solo en user_not_found: identificadores rechazados.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "error": "appointment_type_not_found",
        "message": "El tipo de cita 7 no existe en este taller"
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/appointments/timesObtiene los tiempos disponibles para una fecha
Devuelve una lista de horarios disponibles para agendar una cita en la fecha especificada.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
datequerySíFecha para la cual se consultan los tiempos disponibles (formato YYYY-MM-DD).
{
  "type": "string",
  "format": "date",
  "example": "2025-06-18"
}

Respuestas documentadas

HTTP 200 · Tiempos disponibles obtenidos con éxito.
{
  "description": "Tiempos disponibles obtenidos con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "boolean",
            "example": true
          },
          "msg": {
            "type": "string",
            "example": "Tiempos disponibles para 2025-06-18"
          },
          "response": {
            "type": "object",
            "description": "Detalle de los tiempos disponibles para una fecha.",
            "properties": {
              "date": {
                "type": "string",
                "format": "date",
                "description": "La fecha para la cual se muestran los tiempos.",
                "example": "2025-06-18"
              },
              "description": {
                "type": "string",
                "description": "Descripción general.",
                "example": "Horas disponibles"
              },
              "title": {
                "type": "string",
                "description": "Título para la sección de tiempos.",
                "example": "Horas"
              },
              "is_holiday": {
                "type": "boolean",
                "description": "Indica si la fecha es un día festivo.",
                "example": false
              },
              "times": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "time",
                  "example": "08:30"
                },
                "description": "Lista de horarios disponibles en formato HH:mm."
              }
            }
          }
        },
        "example": {
          "status": true,
          "msg": "Tiempos disponibles para 2025-06-18",
          "response": {
            "date": "2025-06-18",
            "description": "Horas disponibles",
            "title": "Horas",
            "is_holiday": false,
            "times": [
              "08:30",
              "09:30",
              "10:30",
              "11:30",
              "12:30",
              "13:30",
              "14:30",
              "15:30",
              "16:30",
              "17:30",
              "18:30"
            ]
          }
        }
      }
    }
  }
}
HTTP 400 · Fecha inválida o formato incorrecto.
{
  "description": "Fecha inválida o formato incorrecto.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 401 · No autorizado.
{
  "description": "No autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
DELETE/appointments/{appointment_id}Elimina una cita
Elimina una cita específica del sistema utilizando su ID.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
appointment_idpathSíIdentificador único de la cita a eliminar.
{
  "type": "string"
}

Respuestas documentadas

HTTP 204 · Cita eliminada con éxito. No se devuelve contenido.
{
  "description": "Cita eliminada con éxito. No se devuelve contenido."
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Cita no encontrada.
{
  "description": "Cita no encontrada.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}

Notificaciones

POST/notificationsCrear una notificación
Crea una nueva notificación en el sistema. **Destinatarios.** El campo `users` es opcional: si se omite, la notificación se crea sin destinatarios, igual que antes. Cada usuario debe pertenecer al taller, no estar borrado y tener activada la recepción de notificaciones; los identificadores se obtienen en GET /users. **Todo o nada.** Si alguno de los usuarios no es válido no se crea nada, ni la notificación ni los destinatarios, y se devuelve el código `user_not_found` con la lista de los rechazados. Los identificadores repetidos se guardan una sola vez y el máximo por petición es 200. **Respuesta.** Devuelve la notificación creada. Antes devolvía únicamente un mensaje de confirmación.

Autenticación

[
  {
    "Bearer": []
  }
]

Cuerpo de la petición

{
  "required": true,
  "description": "Datos de la notificación a crear.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Datos necesarios para crear una nueva notificación.",
        "properties": {
          "title": {
            "type": "string",
            "description": "Título de la notificación.",
            "example": "Recordatorio de cita"
          },
          "message": {
            "type": "string",
            "description": "Contenido de la notificación.",
            "example": "No olvides tu cita para la revisión del vehículo."
          },
          "users": {
            "type": "array",
            "description": "Usuarios del taller que recibirán la notificación (opcional). Si se omite o llega vacía, la notificación se crea sin destinatarios. Los identificadores se obtienen en GET /users. Se admite también una lista de cadenas.",
            "maxItems": 200,
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string",
                  "description": "Identificador único del usuario.",
                  "example": "p8rp9nb06ue851ay4wfpr5mjnc25wnd3"
                }
              }
            }
          }
        },
        "required": [
          "title",
          "message"
        ],
        "example": {
          "title": "Recordatorio de cita",
          "message": "No olvides tu cita para la revisión del vehículo.",
          "users": [
            {
              "user_id": "p8rp9nb06ue851ay4wfpr5mjnc25wnd3"
            }
          ]
        }
      }
    }
  }
}

Respuestas documentadas

HTTP 201 · Notificación creada con éxito.
{
  "description": "Notificación creada con éxito.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Notificación del taller con sus destinatarios.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador único de la notificación.",
            "example": "g2q1plyimmje0ozzbg4f9aug8at6efr6"
          },
          "title": {
            "type": "string",
            "example": "Recordatorio de cita"
          },
          "message": {
            "type": "string",
            "example": "No olvides tu cita para la revisión del vehículo."
          },
          "created_at": {
            "type": "string",
            "description": "Fecha de alta, en formato DD/MM/YYYY HH:mm. La hora es siempre 00:00: la aplicación guarda solo la fecha.",
            "example": "24/09/2026 00:00"
          },
          "users": {
            "type": "array",
            "description": "Destinatarios. Lista vacía si la notificación no tiene ninguno.",
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string",
                  "example": "p8rp9nb06ue851ay4wfpr5mjnc25wnd3"
                },
                "seen": {
                  "type": "boolean",
                  "description": "Si el usuario ya la ha leído.",
                  "example": false
                }
              }
            }
          }
        },
        "example": {
          "id": "g2q1plyimmje0ozzbg4f9aug8at6efr6",
          "title": "Recordatorio de cita",
          "message": "No olvides tu cita para la revisión del vehículo.",
          "created_at": "24/09/2026 00:00",
          "users": [
            {
              "user_id": "p8rp9nb06ue851ay4wfpr5mjnc25wnd3",
              "seen": false
            }
          ]
        }
      }
    }
  }
}
HTTP 400 · Solicitud incorrecta. Verifique los datos enviados.
{
  "description": "Solicitud incorrecta. Verifique los datos enviados.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Error de validación o de regla de negocio. El campo error es un código estable: conviene programar contra él y no contra el texto de message, que puede cambiar.",
        "properties": {
          "status": {
            "type": "integer",
            "example": 400
          },
          "error": {
            "type": "string",
            "description": "Código del error.",
            "example": "appointment_type_not_found"
          },
          "message": {
            "type": "string",
            "description": "Mensaje legible.",
            "example": "El tipo de cita 7 no existe en este taller"
          },
          "errors": {
            "type": "array",
            "description": "Solo cuando hay varios mensajes de validación.",
            "items": {
              "type": "string"
            }
          },
          "user_ids": {
            "type": "array",
            "description": "Solo en user_not_found: identificadores rechazados.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "error": "user_not_found",
        "message": "Estos usuarios no existen en este taller o no pueden recibir notificaciones: p8r4tyuj0yy0m11ehx1ndridpq1i6qk8",
        "user_ids": [
          "p8r4tyuj0yy0m11ehx1ndridpq1i6qk8"
        ]
      }
    }
  }
}
HTTP 401 · No autorizado. El token de acceso es inválido o no fue proporcionado.
{
  "description": "No autorizado. El token de acceso es inválido o no fue proporcionado.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/notifications/{id}Consultar una notificación
Devuelve una notificación con su lista de destinatarios y si cada uno la ha leído (`seen`). Una notificación de otro taller devuelve 404.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
idpathSíIdentificador único de la notificación.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Notificación encontrada.
{
  "description": "Notificación encontrada.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Notificación del taller con sus destinatarios.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador único de la notificación.",
            "example": "g2q1plyimmje0ozzbg4f9aug8at6efr6"
          },
          "title": {
            "type": "string",
            "example": "Recordatorio de cita"
          },
          "message": {
            "type": "string",
            "example": "No olvides tu cita para la revisión del vehículo."
          },
          "created_at": {
            "type": "string",
            "description": "Fecha de alta, en formato DD/MM/YYYY HH:mm. La hora es siempre 00:00: la aplicación guarda solo la fecha.",
            "example": "24/09/2026 00:00"
          },
          "users": {
            "type": "array",
            "description": "Destinatarios. Lista vacía si la notificación no tiene ninguno.",
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string",
                  "example": "p8rp9nb06ue851ay4wfpr5mjnc25wnd3"
                },
                "seen": {
                  "type": "boolean",
                  "description": "Si el usuario ya la ha leído.",
                  "example": false
                }
              }
            }
          }
        },
        "example": {
          "id": "g2q1plyimmje0ozzbg4f9aug8at6efr6",
          "title": "Recordatorio de cita",
          "message": "No olvides tu cita para la revisión del vehículo.",
          "created_at": "24/09/2026 00:00",
          "users": [
            {
              "user_id": "p8rp9nb06ue851ay4wfpr5mjnc25wnd3",
              "seen": false
            }
          ]
        }
      }
    }
  }
}
HTTP 401 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Notificación no encontrada en este taller.
{
  "description": "Notificación no encontrada en este taller.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "error": {
            "type": "integer"
          },
          "messages": {
            "type": "object"
          }
        }
      },
      "example": {
        "status": 404,
        "error": 404,
        "messages": {
          "error": "Notification not found with ID: g2q1..."
        }
      }
    }
  }
}

Aseguradoras

GET/insurersObtiene un listado de aseguradoras
Devuelve una lista paginada de aseguradoras registradas por el taller asociado al **token**

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página
{
  "type": "integer",
  "default": 1
}
per_pagequeryNoElementos por página
{
  "type": "integer",
  "default": 10
}
insurer_numberqueryNoNúmero de la aseguradora
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Listado de aseguradoras
{
  "description": "Listado de aseguradoras",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "pagination": {
            "properties": {
              "current_page": {
                "type": "integer",
                "example": 1,
                "description": "Número de página actual"
              },
              "per_page": {
                "type": "integer",
                "example": 10,
                "description": "Elementos por página"
              },
              "total_count": {
                "type": "integer",
                "example": 31,
                "description": "Nº total de elementos sin paginar"
              },
              "total_pages": {
                "type": "integer",
                "example": 4,
                "description": "Nº total de páginas teniendo en cuenta el numero de elementos"
              }
            }
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Aseguradora.",
              "properties": {
                "id": {
                  "type": "string"
                },
                "insurer_number": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "email": {
                  "type": "string",
                  "nullable": true
                },
                "address": {
                  "type": "string",
                  "nullable": true
                },
                "zip_code": {
                  "type": "string",
                  "nullable": true
                },
                "city": {
                  "type": "string",
                  "nullable": true
                },
                "province": {
                  "type": "string",
                  "nullable": true
                },
                "cif": {
                  "type": "string",
                  "nullable": true
                },
                "phone": {
                  "type": "string",
                  "nullable": true
                },
                "website": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 · No autorizado (token inválido o ausente)
{
  "description": "No autorizado (token inválido o ausente)",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}

Usuarios

GET/usersConsultar usuarios
Usuarios del taller. Su utilidad principal es conocer los identificadores que admite el campo `users` al crear una notificación. **Solo pueden ser destinatarios los usuarios con `receives_notifications` a `true`.** Enviar cualquier otro en `users` devuelve un error `user_not_found`.

Autenticación

[
  {
    "Bearer": []
  }
]

Respuestas documentadas

HTTP 200 · Usuarios del taller.
{
  "description": "Usuarios del taller.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Identificador único del usuario. Es el valor que se envía en el campo users al crear una notificación."
                },
                "login": {
                  "type": "string",
                  "description": "Nombre de acceso."
                },
                "name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nombre descriptivo. Puede ser nulo: no todos los usuarios lo tienen."
                },
                "receives_notifications": {
                  "type": "boolean",
                  "description": "Si el usuario tiene activada la recepción de notificaciones. Solo estos pueden ser destinatarios."
                },
                "employee_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identificador del empleado vinculado, si lo hay."
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}

Albaranes de Compra

GET/purchase-delivery-notesObtiene albaranes de compra con paginación.
Retorna un listado paginado de albaranes de compra. Soporta paginación con page y per_page.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página.
{
  "type": "integer"
}
per_pagequeryNoNúmero de elementos por página.
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 · Listado paginado de albaranes de compra.
{
  "description": "Listado paginado de albaranes de compra."
}
HTTP 401 · No autorizado. Token inválido o ausente.
{
  "description": "No autorizado. Token inválido o ausente.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/purchase-delivery-notes/{id}Obtiene un albarán de compra por ID.
Retorna los detalles de un albarán de compra específico.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
idpathSíIdentificador del albarán de compra.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Detalle del albarán de compra.
{
  "description": "Detalle del albarán de compra."
}
HTTP 401 · No autorizado. Token inválido o ausente.
{
  "description": "No autorizado. Token inválido o ausente.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Albarán de compra no encontrado.
{
  "description": "Albarán de compra no encontrado."
}

Marcas y modelos

GET/brandsListado de Marcas
Obtiene la lista de todas las marcas de vehículos disponibles. ## Parámetros de consulta opcionales | Parámetro | Tipo | Descripción | |-----------|------|-------------| | `search` | string | Filtrar por nombre de la marca | | `page` | integer | Número de página (default: 1) | | `per_page` | integer | Resultados por página (default: 50, max: 200) | ## Ejemplo de respuesta ```json { "pagination": { "current_page": 1, "per_page": 50, "total_count": 89, "total_pages": 2 }, "data": [ { "id": 342, "name": "VOLKSWAGEN" }, { "id": 265, "name": "SEAT" }, { "id": 245, "name": "RENAULT" } ] } ```

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
searchqueryNoNombre de marca
{
  "type": "string"
}
pagequeryNoNúmero de página
{
  "type": "integer"
}
per_pagequeryNoNúmero de elementos por página
{
  "type": "integer"
}

Cuerpo de la petición

{
  "required": true,
  "description": "",
  "content": {
    "application/json": {
      "schema": {},
      "example": {
        "client_id": "7pser1d252xvpoob35lky6eo36peq9xm",
        "plate": "1234ABC",
        "vin": "WVWZZZ3CZWE123456",
        "brand_id": 342,
        "model_id": 1081890,
        "color": "Negro",
        "kms": "50000",
        "registration_date": "15/03/2022",
        "next_itv_date": "15/03/2026",
        "fuel_type_id": 2
      }
    }
  }
}

Respuestas documentadas

HTTP 200 · Successful response
{
  "description": "Successful response"
}
GET/brands/{brand_id}/modelsLista los modelos de una marca específica
Obtiene todos los modelos de vehículos disponibles para una marca específica. ## Parámetros de ruta | Parámetro | Tipo | Requerido | Descripción | |-----------|------|-----------|-------------| | `brand_id` | integer | Sí | ID de la marca | ## Parámetros de consulta opcionales | Parámetro | Tipo | Descripción | |-----------|------|-------------| | `search` | string | Filtrar por nombre del modelo | | `page` | integer | Número de página (default: 1) | | `per_page` | integer | Resultados por página (default: 50, max: 200) | ## Ejemplo de respuesta ```json { "pagination": { "current_page": 1, "per_page": 50, "total_count": 125, "total_pages": 3 }, "data": [ { "id": 1081890, "brand_id": 342, "name": "GOLF", "vehicle_type_id": 1 } ] }

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
brand_idpathSí
{
  "type": "integer"
}
searchqueryNoNombre modelo
{
  "type": "string"
}
pagequeryNoNúmero de página
{
  "type": "integer"
}
per_pagequeryNoNúmero de elementos por página
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 · Respuesta exitosa
{
  "description": "Respuesta exitosa"
}

Facturas de Compra

GET/purchase-invoicesObtiene facturas de compra con paginación.
Retorna un listado paginado de facturas de compra. Soporta paginación con page y per_page.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página.
{
  "type": "integer"
}
per_pagequeryNoNúmero de elementos por página.
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 · Listado paginado de facturas de compra.
{
  "description": "Listado paginado de facturas de compra."
}
HTTP 401 · No autorizado. Token inválido o ausente.
{
  "description": "No autorizado. Token inválido o ausente.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
GET/purchase-invoices/{id}Obtiene una factura de compra por ID.
Retorna los detalles de una factura de compra específica.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
idpathSíIdentificador de la factura de compra.
{
  "type": "string"
}

Respuestas documentadas

HTTP 200 · Detalle de la factura de compra.
{
  "description": "Detalle de la factura de compra."
}
HTTP 401 · No autorizado. Token inválido o ausente.
{
  "description": "No autorizado. Token inválido o ausente.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}
HTTP 404 · Factura de compra no encontrada.
{
  "description": "Factura de compra no encontrada."
}

Tipos de fichaje

GET/time-entry-typesConsultar tipos de fichaje
Tabla maestra con los tipos de fichaje configurados en el taller, los mismos que se usan en TallerGP. De aquí se obtienen los valores válidos de `start_type_id` y `end_type_id`. Cada tipo tiene un sentido: `entry` para las entradas y `exit` para las salidas. En las salidas, `counts_as_break` indica si ese periodo se considera una parada o interrupción. El identificador de un tipo **solo es único dentro del taller**, no entre talleres, y no tiene por qué ser un número pequeño. Solo se devuelven los tipos activos.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
typequeryNoFiltra por sentido: `entry` para tipos de entrada, `exit` para tipos de salida.
{
  "type": "string",
  "enum": [
    "entry",
    "exit"
  ]
}

Respuestas documentadas

HTTP 200 · Tipos de fichaje del taller.
{
  "description": "Tipos de fichaje del taller.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "description": "Identificador del tipo, único dentro del taller"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "entry",
                    "exit"
                  ],
                  "description": "Sentido del fichaje"
                },
                "description": {
                  "type": "string",
                  "description": "Descripción configurada en el taller"
                },
                "order": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Orden de presentación"
                },
                "counts_as_break": {
                  "type": "boolean",
                  "description": "Solo en salidas: el período se considera parada"
                },
                "automatic_close": {
                  "type": "boolean",
                  "description": "El tipo se cierra automáticamente"
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 400 · El parámetro type no es entry ni exit.
{
  "description": "El parámetro type no es entry ni exit.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "example": {
        "status": 400,
        "message": "Validation failed",
        "errors": [
          "type must be either entry or exit"
        ]
      }
    }
  }
}
HTTP 401 · Token no válido o no autorizado.
{
  "description": "Token no válido o no autorizado.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "example": {
        "error": true,
        "message": "Invalid or expired API Key.",
        "code": "unauthorized"
      }
    }
  }
}

Neumáticos

GET/tyresObtiene listado de neumáticos con paginación.
Retorna un listado paginado de neumáticos. Soporta paginación con page y per_page.

Autenticación

[
  {
    "Bearer": []
  }
]

Parámetros

CampoUbicaciónObligatorioDescripción y formato
pagequeryNoNúmero de página.
{
  "type": "integer"
}
per_pagequeryNoNúmero de elementos por página.
{
  "type": "integer"
}

Respuestas documentadas

HTTP 200 · Listado paginado de neumáticos.
{
  "description": "Listado paginado de neumáticos."
}
HTTP 401 · No autorizado. Token inválido o ausente.
{
  "description": "No autorizado. Token inválido o ausente.",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}

Tipos de cita

GET/appointment-typesConsultar tipos de cita
Tipos de cita configurados en el taller, los mismos que se usan en TallerGP. De aquí se obtienen los valores válidos de `appointment_type_id` al crear una cita. El identificador de un tipo **solo es único dentro del taller**, no entre talleres, y no tiene por qué ser un número pequeño. `duration` se devuelve en horas y suele venir vacía: la mayoría de los tipos no la tienen configurada. Cuando sí la tiene, una cita creada con ese tipo y sin `duration` propia la hereda. Solo se devuelven los tipos activos, ordenados por su orden de presentación y después por nombre. Los que no tienen orden van al final.

Autenticación

[
  {
    "Bearer": []
  }
]

Respuestas documentadas

HTTP 200 · Tipos de cita del taller.
{
  "description": "Tipos de cita del taller.",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "description": "Identificador del tipo. Único dentro del taller, no entre talleres."
                },
                "name": {
                  "type": "string",
                  "description": "Descripción configurada en el taller."
                },
                "color": {
                  "type": "string",
                  "nullable": true,
                  "description": "Color en hexadecimal, con almohadilla."
                },
                "duration": {
                  "type": "number",
                  "format": "float",
                  "nullable": true,
                  "description": "Duración en horas. Nula si no está informada; la mayoría de los tipos no la tienen."
                },
                "order": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Orden de presentación. Los tipos sin orden se devuelven al final."
                }
              }
            }
          }
        }
      }
    }
  }
}
HTTP 401 ·
{
  "description": "",
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "reason": {
            "description": "Error en la petición",
            "example": "Source website could not be found",
            "type": "string"
          },
          "success": {
            "description": "Will be false if the operation failed",
            "example": false,
            "type": "boolean"
          }
        },
        "type": "object"
      }
    }
  }
}

Origen y actualización

Referencia de TallerGP v1.0.20, fechada el 24 de septiembre de 2026. Adaptación consultada el 26 de septiembre de 2026. La documentación original puede incorporar cambios posteriores.

Contenido técnico de TallerGP Developers, cuya especificación declara la licencia Creative Commons Attribution 4.0. Adaptación: presentación, navegación y contexto de PRO Integra360. Se mantienen los endpoints y esquemas de la fuente. Descargar especificación original.