Settings
Settings API
Endpoints for managing tenant-level business configuration, including company info, tax settings, PDF branding, and logo.
Get Settings
GET /api/settings
Permission: config:manage (Owner only)
Retrieve the current tenant's settings. The logoUrl is returned as a presigned S3 URL (temporary, valid for a limited time).
Response 200 OK:
{
"data": {
"id": "clxyz...",
"companyName": "Acme Solutions S.A. de C.V.",
"email": "contacto@acme.mx",
"phone": "+52 55 1234 5678",
"address": "Av. Reforma 222, Col. Juárez, CDMX",
"logoUrl": "https://s3.amazonaws.com/...presigned...",
"bankInfo": {
"bankName": "BBVA México",
"clabe": "012345678901234567"
},
"defaultNotes": "Cotización válida por 15 días",
"taxRate": "0.16",
"quoteValidityDays": 15,
"currency": "MXN",
"pdfBranding": {
"primaryColor": "#1A56DB",
"accentColor": "#c96b3c",
"fontFamily": "Helvetica",
"headerLayout": "left",
"footerText": "Gracias por su preferencia"
},
"reminderDaysBefore": 3
}
}Errors:
| Status | Error | When |
|---|---|---|
| 403 | "Sin permisos" | Role lacks config:manage |
| 404 | "Negocio no encontrado" | Tenant not found |
Update Settings
PUT /api/settings
Permission: config:manage (Owner only)
Update one or more tenant settings. All fields are optional — only include fields you want to change.
Request Body:
{
"companyName": "Acme Solutions S.A. de C.V.",
"phone": "+52 55 1234 5678",
"email": "nuevo@acme.mx",
"address": "Av. Reforma 222, Col. Juárez, CDMX",
"taxRate": 0.16,
"quoteValidityDays": 30,
"currency": "MXN",
"defaultNotes": "Precios sujetos a cambio sin previo aviso",
"bankInfo": {
"bankName": "BBVA México",
"clabe": "012345678901234567"
},
"pdfBranding": {
"primaryColor": "#1A56DB",
"accentColor": "#c96b3c",
"fontFamily": "Helvetica",
"headerLayout": "left",
"footerText": "Gracias por su preferencia"
},
"reminderDaysBefore": 5
}| Field | Type | Required | Description |
|---|---|---|---|
| companyName | string | No | Company name (min 2 characters) |
| phone | string | No | Phone number |
| string | No | Valid email | |
| address | string | No | Business address |
| taxRate | number | No | Tax rate between 0 and 1 (e.g., 0.16 = 16%) |
| quoteValidityDays | integer | No | Default quote validity in days (1–365) |
| currency | string | No | 3-letter currency code (e.g., MXN, USD, COP) |
| defaultNotes | string | No | Default notes for new quotes |
| bankInfo | object | null | No | Bank details (bankName, clabe). Set to null to remove. |
| pdfBranding | object | null | No | PDF styling options. Set to null to reset. |
| pdfBranding.primaryColor | string | No | Hex color (e.g., #1A56DB) |
| pdfBranding.accentColor | string | No | Hex color (e.g., #c96b3c) |
| pdfBranding.fontFamily | string | No | Helvetica, Times, or Courier |
| pdfBranding.headerLayout | string | No | left, center, or right |
| pdfBranding.footerText | string | No | Footer text (max 200 characters) |
| reminderDaysBefore | integer | No | Days before expiry to send reminder (1–30) |
Response 200 OK:
{
"data": { ...updated tenant settings... }
}Side Effects:
- Triggers onboarding step
company_infocompletion - Logs audit entry with action
update
Upload Logo
POST /api/settings/logo
Permission: config:manage (Owner only)
Upload a company logo via multipart form data. The image is stored in S3 and the tenant's logoUrl is updated.
Request: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
| logo | File | Yes | Image file (PNG, JPG, WebP, or SVG). Max 2MB. |
cURL Example:
curl -X POST "https://cotizera.com/api/settings/logo" \
-H "Cookie: next-auth.session-token=YOUR_TOKEN" \
-F "logo=@/path/to/logo.png"Response 200 OK:
{
"logoUrl": "https://s3.amazonaws.com/...presigned...",
"s3Key": "logos/tenant-id/logo.png"
}Errors:
| Status | Error | When |
|---|---|---|
| 400 | "No se proporcionó un archivo" | Missing logo field |
| 400 | "Tipo de archivo no permitido. Use PNG, JPG, WebP o SVG." | Invalid file type |
| 400 | "El archivo excede el tamaño máximo de 2MB" | File too large |