Skip to content

Consultas

Esta sección documenta los endpoints de consulta para obtener información sobre empresas, cuentas, suscripciones y otros datos relacionados con la gestión empresarial.

  • Autenticación mediante Bearer Token
  • Respuestas en formato JSON estructurado
  • Paginación en consultas extensas
  • Filtros y búsquedas avanzadas
  • Códigos de estado HTTP estándar

  • Endpoint: GET /api/v1/admin/companies/all-companies
  • Método: GET
  • Autenticación: Bearer Token requerido (Admin)
  • Descripción: Obtiene la lista completa de todas las empresas registradas en el sistema
Authorization: Bearer {token}
Accept: application/json
ParámetroTipoDescripción
pageintegerNúmero de página para paginación (default: 1)
limitintegerCantidad de registros por página (default: 15, max: 100)
searchstringBúsqueda por nombre, RUC o razón social
statusstringFiltrar por estado: “active”, “inactive”, “suspended”
subscription_statusstringFiltrar por estado de suscripción: “active”, “expired”, “trial”
created_fromdateFecha de creación desde (YYYY-MM-DD)
created_todateFecha de creación hasta (YYYY-MM-DD)
sort_bystringCampo para ordenar: “name”, “created_at”, “ruc”, “subscription_expires”
sort_orderstringOrden: “asc” o “desc” (default: “desc”)
GET /api/v1/admin/companies/all-companies?page=1&limit=20&status=active&sort_by=created_at
Authorization: Bearer {token}
Accept: application/json
{
"message": "Empresas obtenidas exitosamente",
"status": "SUCCESS",
"payload": {
"current_page": 1,
"data": [
{
"id": "61247344",
"company_name": "Empresa Ejemplo S.A.",
"trade_name": "Ejemplo Corp",
"ruc": "1234567890001",
"email": "[email protected]",
"phone": "+593987654321",
"address": {
"street": "Av. Principal 123",
"city": "Quito",
"province": "Pichincha",
"postal_code": "170501",
"country": "Ecuador"
},
"status": "active",
"subscription": {
"plan": "premium",
"status": "active",
"expires_at": "2024-12-31T23:59:59Z",
"documents_limit": 10000,
"documents_used": 2547
},
"sri_configuration": {
"environment": "production",
"configured": true,
"last_validation": "2024-01-15T10:30:00Z"
},
"statistics": {
"total_documents": 2547,
"documents_this_month": 156,
"establishments_count": 3,
"emission_points_count": 8,
"users_count": 12
},
"created_at": "2023-06-15T08:00:00Z",
"updated_at": "2024-01-15T14:30:00Z",
"last_activity": "2024-01-15T16:45:00Z"
},
{
"id": "61247345",
"company_name": "Comercial ABC Ltda.",
"trade_name": "ABC Store",
"ruc": "0987654321001",
"email": "[email protected]",
"phone": "+593912345678",
"address": {
"street": "Calle Secundaria 456",
"city": "Guayaquil",
"province": "Guayas",
"postal_code": "090101",
"country": "Ecuador"
},
"status": "active",
"subscription": {
"plan": "basic",
"status": "active",
"expires_at": "2024-06-30T23:59:59Z",
"documents_limit": 1000,
"documents_used": 789
},
"sri_configuration": {
"environment": "production",
"configured": true,
"last_validation": "2024-01-14T15:20:00Z"
},
"statistics": {
"total_documents": 789,
"documents_this_month": 45,
"establishments_count": 1,
"emission_points_count": 2,
"users_count": 3
},
"created_at": "2023-08-20T10:15:00Z",
"updated_at": "2024-01-14T15:20:00Z",
"last_activity": "2024-01-15T12:30:00Z"
}
],
"first_page_url": "http://api.example.com/api/v1/admin/companies/all-companies?page=1",
"from": 1,
"last_page": 25,
"last_page_url": "http://api.example.com/api/v1/admin/companies/all-companies?page=25",
"next_page_url": "http://api.example.com/api/v1/admin/companies/all-companies?page=2",
"path": "http://api.example.com/api/v1/admin/companies/all-companies",
"per_page": 20,
"prev_page_url": null,
"to": 20,
"total": 487
},
"meta": {
"total_companies": 487,
"active_companies": 423,
"inactive_companies": 64,
"companies_with_active_subscription": 398,
"total_documents_issued": 1247589,
"documents_this_month": 45632
}
}
{
"message": "Acceso denegado",
"status": "ERROR",
"payload": null,
"error": {
"authorization": [
"Se requieren permisos de administrador para acceder a esta información"
],
"required_permissions": [
"admin.companies.view_all"
]
}
}
Terminal window
curl -X GET \
"{{apiFacEcDev}}/api/v1/admin/companies/all-companies?page=1&limit=20&status=active" \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {{bearerToken}}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $bearerToken,
'Accept' => 'application/json',
])->get($apiUrl . '/api/v1/admin/companies/all-companies', [
'page' => 1,
'limit' => 20,
'status' => 'active',
'sort_by' => 'created_at',
'sort_order' => 'desc'
]);
$companies = $response->json();
const axios = require('axios');
const getAllCompanies = async (filters = {}) => {
try {
const params = new URLSearchParams({
page: filters.page || 1,
limit: filters.limit || 20,
...(filters.status && { status: filters.status }),
...(filters.search && { search: filters.search }),
...(filters.subscription_status && { subscription_status: filters.subscription_status }),
...(filters.sort_by && { sort_by: filters.sort_by }),
...(filters.sort_order && { sort_order: filters.sort_order })
});
const response = await axios.get(
`${apiUrl}/api/v1/admin/companies/all-companies?${params}`,
{
headers: {
'Authorization': `Bearer ${bearerToken}`,
'Accept': 'application/json'
}
}
);
console.log('Empresas obtenidas:', response.data);
return response.data;
} catch (error) {
console.error('Error:', error.response.data);
throw error;
}
};

  • Endpoint: GET /api/v1/companies/all-accounts
  • Método: GET
  • Autenticación: Bearer Token requerido
  • Descripción: Obtiene la lista de cuentas asociadas al usuario autenticado
Authorization: Bearer {token}
Accept: application/json
ParámetroTipoDescripción
include_inactivebooleanIncluir cuentas inactivas (default: false)
with_statisticsbooleanIncluir estadísticas detalladas (default: true)
with_subscriptionbooleanIncluir información de suscripción (default: true)
GET /api/v1/companies/all-accounts?include_inactive=false&with_statistics=true
Authorization: Bearer {token}
Accept: application/json
{
"message": "Cuentas obtenidas exitosamente",
"status": "SUCCESS",
"payload": {
"user_id": 123,
"total_accounts": 3,
"accounts": [
{
"account_id": "61247344",
"company_name": "Mi Empresa Principal S.A.",
"trade_name": "Empresa Principal",
"ruc": "1234567890001",
"role": "owner",
"permissions": [
"companies.manage",
"documents.create",
"documents.view",
"users.manage",
"reports.view"
],
"status": "active",
"subscription": {
"plan": "premium",
"status": "active",
"expires_at": "2024-12-31T23:59:59Z",
"documents_limit": 10000,
"documents_used": 2547,
"usage_percentage": 25.47
},
"statistics": {
"total_documents": 2547,
"documents_this_month": 156,
"documents_today": 8,
"revenue_this_month": 15420.50,
"establishments_count": 3,
"emission_points_count": 8,
"active_users": 12
},
"last_activity": "2024-01-15T16:45:00Z",
"joined_at": "2023-06-15T08:00:00Z"
},
{
"account_id": "61247345",
"company_name": "Sucursal Norte Ltda.",
"trade_name": "Sucursal Norte",
"ruc": "0987654321001",
"role": "administrator",
"permissions": [
"documents.create",
"documents.view",
"reports.view"
],
"status": "active",
"subscription": {
"plan": "basic",
"status": "active",
"expires_at": "2024-06-30T23:59:59Z",
"documents_limit": 1000,
"documents_used": 789,
"usage_percentage": 78.9
},
"statistics": {
"total_documents": 789,
"documents_this_month": 45,
"documents_today": 2,
"revenue_this_month": 8750.25,
"establishments_count": 1,
"emission_points_count": 2,
"active_users": 3
},
"last_activity": "2024-01-15T12:30:00Z",
"joined_at": "2023-08-20T10:15:00Z"
},
{
"account_id": "61247346",
"company_name": "Consultora XYZ S.A.S.",
"trade_name": "XYZ Consulting",
"ruc": "1122334455001",
"role": "user",
"permissions": [
"documents.view",
"reports.view"
],
"status": "active",
"subscription": {
"plan": "trial",
"status": "trial",
"expires_at": "2024-02-15T23:59:59Z",
"documents_limit": 100,
"documents_used": 23,
"usage_percentage": 23.0
},
"statistics": {
"total_documents": 23,
"documents_this_month": 23,
"documents_today": 1,
"revenue_this_month": 1250.00,
"establishments_count": 1,
"emission_points_count": 1,
"active_users": 1
},
"last_activity": "2024-01-15T09:15:00Z",
"joined_at": "2024-01-15T08:00:00Z"
}
],
"summary": {
"total_documents_all_accounts": 3359,
"total_revenue_this_month": 25420.75,
"accounts_by_status": {
"active": 3,
"inactive": 0,
"suspended": 0
},
"accounts_by_plan": {
"premium": 1,
"basic": 1,
"trial": 1
}
}
}
}
Terminal window
curl -X GET \
"{{apiFacEcDev}}/api/v1/companies/all-accounts?include_inactive=false" \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {{bearerToken}}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $bearerToken,
'Accept' => 'application/json',
])->get($apiUrl . '/api/v1/companies/all-accounts', [
'include_inactive' => false,
'with_statistics' => true,
'with_subscription' => true
]);
$accounts = $response->json();
const axios = require('axios');
const getAllAccounts = async (options = {}) => {
try {
const params = new URLSearchParams({
include_inactive: options.includeInactive || false,
with_statistics: options.withStatistics !== false,
with_subscription: options.withSubscription !== false
});
const response = await axios.get(
`${apiUrl}/api/v1/companies/all-accounts?${params}`,
{
headers: {
'Authorization': `Bearer ${bearerToken}`,
'Accept': 'application/json'
}
}
);
console.log('Cuentas obtenidas:', response.data);
return response.data;
} catch (error) {
console.error('Error:', error.response.data);
throw error;
}
};

  • Endpoint: GET /api/v1/companies/my-subscription
  • Método: GET
  • Autenticación: Bearer Token requerido
  • Descripción: Obtiene información detallada de la suscripción del usuario autenticado
Authorization: Bearer {token}
Accept: application/json
GET /api/v1/companies/my-subscription
Authorization: Bearer {token}
Accept: application/json
{
"message": "Mi suscripción",
"status": "DELETED",
"payload": {
"started_at": "2025-02-17 00:00:00",
"expired_at": "2025-03-17 20:09:10",
"canceled_at": null,
"suppressed_at": null,
"was_switched": 0,
"plan": {
"code": "month-0003",
"description": "Comprobantes electrónicos ilimitados al mes",
"price": "1.00",
"periodicity_type": "Month",
"periodicity_lang": "Mes",
"periodicity": 1,
"features": [
{
"code": "accounts",
"description": "Cuentas de compañías",
"count": 1,
"consumption": 0,
"balance": 1
},
{
"code": "emission_point",
"description": "Puntos de emisión",
"count": 2,
"consumption": 0,
"balance": 2
},
{
"code": "clients",
"description": "Clientes",
"count": 999999999,
"consumption": 0,
"balance": 999999999
},
{
"code": "documents",
"description": "Documentos",
"count": 999999999,
"consumption": 0,
"balance": 999999999
},
{
"code": "send_document",
"description": "Enviar documentos al SRI",
"count": 999999999,
"consumption": 0,
"balance": 999999999
},
{
"code": "send_document_mail",
"description": "Enviar documentos al correo",
"count": 999999999,
"consumption": 0,
"balance": 999999999
}
]
},
"subscriber": {
"uuid": 61247344,
"name": "EDWARD REYES",
"email": "[email protected]",
"message": null,
"status": "active",
"ruc": "0952615177001",
"created_at": "2025-01-05 17:53:48",
"address": "CERECITA KM 51 VIA A LA COSTA"
}
}
Terminal window
curl -X GET \
"{{apiFacEcDev}}/api/v1/companies/my-subscription" \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {{bearerToken}}'

  • Endpoint: GET /api/v1/companies/my-accounts
  • Método: GET
  • Autenticación: Bearer Token requerido
  • Descripción: Obtiene la lista de cuentas empresariales asociadas al usuario autenticado
Authorization: Bearer {token}
Accept: application/json
ParámetroTipoDescripción
pageintegerNúmero de página para paginación (default: 1)
number_paginateintegerCantidad de registros por página (default: 25)
GET /api/v1/companies/my-accounts?page=1&number_paginate=25
Authorization: Bearer {token}
Accept: application/json
{
"message": "Lista de valores",
"status": "OK",
"payload": {
"items": [
{
"uuid": 61247344,
"ruc": "0952615177001",
"type_person": null,
"code_person": null,
"name": "EDWARD REYES VILLON",
"commercial_name": "EDWARD REYES",
"matriz_address": "Km 51 vía a la Costa",
"environment": "TEST",
"status_process": "processed",
"warnings": [],
"is_contable": "NO",
"currency": "DOLAR",
"has_logo": true,
"has_configured": true,
"has_mysign": true,
"mail_cc": "[email protected]",
"documents_created": 196,
"documents_deleted": 27,
"documents_emited": 52,
"retention_agent": null,
"is_rimpe": false,
"is_protected": true,
"is_principal": true,
"created_at": "2025-06-18 19:59:09",
"establishments": []
}
],
"count_items": 1,
"current_page": 1,
"number_paginate": 25,
"last_page": 1
}
}
CampoTipoDescripción
uuidintegerID único de la cuenta
rucstringRUC de la empresa
namestringRazón social de la empresa
commercial_namestringNombre comercial
matriz_addressstringDirección de la matriz
environmentstringAmbiente: “TEST” o “PRODUCTION”
status_processstringEstado del procesamiento
is_contablestringSi es contable: “SI” o “NO”
currencystringMoneda: “DOLAR” o “PESO”
has_logobooleanSi tiene logo configurado
has_configuredbooleanSi está completamente configurada
has_mysignbooleanSi tiene firma digital
documents_createdintegerTotal de documentos creados
documents_deletedintegerTotal de documentos eliminados
documents_emitedintegerTotal de documentos emitidos
is_rimpebooleanSi es RIMPE
is_protectedbooleanSi está protegida
is_principalbooleanSi es cuenta principal
Terminal window
curl -X GET \
"{{apiFacEcDev}}/api/v1/companies/my-accounts?page=1&number_paginate=25" \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {{bearerToken}}'
  • Selector de cuentas: Para mostrar un dropdown con las cuentas disponibles
  • Dashboard multi-empresa: Para cambiar entre diferentes contextos empresariales
  • Gestión de permisos: Para verificar roles y permisos por cuenta
  • Estadísticas generales: Para mostrar resúmenes de actividad por empresa
  • Este endpoint solo devuelve las cuentas a las que el usuario tiene acceso
  • La paginación es útil para usuarios con muchas cuentas empresariales
  • Los campos has_configured, has_logo y has_mysign indican el estado de configuración
  • El campo is_principal identifica la cuenta principal del usuario

  • Endpoint: GET /api/v1/companies/show-logo/:accountId
  • Método: GET
  • Autenticación: Bearer Token requerido
  • Descripción: Obtiene el logo de una empresa específica
Authorization: Bearer {token}
Accept: application/json
ParámetroTipoRequeridoDescripción
accountIdstringID de la cuenta empresarial
ParámetroTipoDescripción
sizestringTamaño del logo: “small”, “medium”, “large”, “original” (default: “medium”)
formatstringFormato de respuesta: “json”, “base64”, “url” (default: “json”)
GET /api/v1/companies/show-logo/61247344?size=medium&format=json
Authorization: Bearer {token}
Accept: application/json
{
"message": "Logo obtenido exitosamente",
"status": "SUCCESS",
"payload": {
"account_id": "61247344",
"company_name": "Mi Empresa S.A.",
"logo": {
"has_logo": true,
"original_filename": "logo-empresa.png",
"mime_type": "image/png",
"file_size": 45678,
"dimensions": {
"width": 800,
"height": 600
},
"urls": {
"small": "https://dev-facturacion.e-dinky.test/storage/logos/61247344/small.png",
"medium": "https://dev-facturacion.e-dinky.test/storage/logos/61247344/medium.png",
"large": "https://dev-facturacion.e-dinky.test/storage/logos/61247344/large.png",
"original": "https://dev-facturacion.e-dinky.test/storage/logos/61247344/original.png"
},
"base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"uploaded_at": "2023-06-15T10:30:00Z",
"updated_at": "2024-01-10T14:20:00Z"
}
}
}
{
"message": "No se encontró logo para esta empresa",
"status": "SUCCESS",
"payload": {
"account_id": "61247344",
"company_name": "Mi Empresa S.A.",
"logo": {
"has_logo": false,
"default_logo_url": "https://dev-facturacion.e-dinky.test/assets/default-company-logo.png"
}
}
}
Terminal window
curl -X GET \
"{{apiFacEcDev}}/api/v1/companies/show-logo/61247344?size=medium" \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {{bearerToken}}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $bearerToken,
'Accept' => 'application/json',
])->get($apiUrl . '/api/v1/companies/show-logo/' . $accountId, [
'size' => 'medium',
'format' => 'json'
]);
$logo = $response->json();
const axios = require('axios');
const getCompanyLogo = async (accountId, options = {}) => {
try {
const params = new URLSearchParams({
size: options.size || 'medium',
format: options.format || 'json'
});
const response = await axios.get(
`${apiUrl}/api/v1/companies/show-logo/${accountId}?${params}`,
{
headers: {
'Authorization': `Bearer ${bearerToken}`,
'Accept': 'application/json'
}
}
);
console.log('Logo obtenido:', response.data);
return response.data;
} catch (error) {
console.error('Error:', error.response.data);
throw error;
}
};

class CompanyFilters {
constructor() {
this.filters = {
search: '',
status: [],
subscription_status: [],
plan_type: [],
date_range: {
from: null,
to: null
},
usage_range: {
min: 0,
max: 100
},
location: {
country: '',
province: '',
city: ''
}
};
}
setSearch(query) {
this.filters.search = query;
return this;
}
setStatus(statuses) {
this.filters.status = Array.isArray(statuses) ? statuses : [statuses];
return this;
}
setSubscriptionStatus(statuses) {
this.filters.subscription_status = Array.isArray(statuses) ? statuses : [statuses];
return this;
}
setDateRange(from, to) {
this.filters.date_range = { from, to };
return this;
}
setUsageRange(min, max) {
this.filters.usage_range = { min, max };
return this;
}
buildQueryParams() {
const params = new URLSearchParams();
if (this.filters.search) {
params.append('search', this.filters.search);
}
this.filters.status.forEach(status => {
params.append('status[]', status);
});
this.filters.subscription_status.forEach(status => {
params.append('subscription_status[]', status);
});
if (this.filters.date_range.from) {
params.append('created_from', this.filters.date_range.from);
}
if (this.filters.date_range.to) {
params.append('created_to', this.filters.date_range.to);
}
return params.toString();
}
}
// Uso del sistema de filtros
const filters = new CompanyFilters()
.setSearch('Empresa')
.setStatus(['active', 'trial'])
.setSubscriptionStatus(['active'])
.setDateRange('2023-01-01', '2024-01-31')
.setUsageRange(20, 80);
const queryString = filters.buildQueryParams();
class IntelligentSearch
{
public function search($query, $filters = [])
{
$searchTerms = $this->parseSearchQuery($query);
$results = [];
// Búsqueda exacta por RUC
if ($this->isRucFormat($query)) {
$results['exact_ruc'] = $this->searchByRuc($query);
}
// Búsqueda por nombre de empresa
if ($this->isCompanyName($query)) {
$results['company_name'] = $this->searchByCompanyName($searchTerms);
}
// Búsqueda por email
if ($this->isEmail($query)) {
$results['email'] = $this->searchByEmail($query);
}
// Búsqueda por teléfono
if ($this->isPhone($query)) {
$results['phone'] = $this->searchByPhone($query);
}
// Búsqueda fuzzy
$results['fuzzy'] = $this->fuzzySearch($searchTerms);
return $this->rankResults($results, $query);
}
private function parseSearchQuery($query)
{
// Remover caracteres especiales y dividir en términos
$cleaned = preg_replace('/[^\w\[email protected]]/', '', $query);
return array_filter(explode(' ', $cleaned));
}
private function isRucFormat($query)
{
return preg_match('/^\d{13}$/', $query);
}
private function rankResults($results, $originalQuery)
{
$ranked = [];
foreach ($results as $type => $items) {
foreach ($items as $item) {
$score = $this->calculateRelevanceScore($item, $originalQuery, $type);
$ranked[] = array_merge($item, [
'relevance_score' => $score,
'match_type' => $type
]);
}
}
// Ordenar por relevancia
usort($ranked, function($a, $b) {
return $b['relevance_score'] <=> $a['relevance_score'];
});
return $ranked;
}
}
  • 200 OK: Consulta exitosa
  • 400 Bad Request: Parámetros inválidos
  • 401 Unauthorized: Token de autorización inválido
  • 403 Forbidden: Sin permisos para la operación
  • 404 Not Found: Recurso no encontrado
  • 422 Unprocessable Entity: Error de validación
  • 429 Too Many Requests: Límite de consultas excedido
  • 500 Internal Server Error: Error interno del servidor
  • Use paginación para grandes conjuntos de datos
  • Implemente caché para consultas frecuentes
  • Use índices apropiados en campos de búsqueda
  • Limite los campos devueltos cuando sea posible
  • Implemente filtros eficientes
  • Use agregaciones para estadísticas
  • Considere vistas materializadas para reportes
  • Mantenga índices actualizados
  • Use compresión para respuestas grandes
  • Implemente lazy loading para datos relacionados
  • Considere GraphQL para consultas complejas
  • Use CDN para recursos estáticos como logos
  • Valide permisos antes de cada consulta
  • Registre accesos para auditoría
  • Use rate limiting por usuario/IP
  • Sanitice parámetros de entrada
const buildAdminDashboard = async () => {
try {
// Obtener resumen de empresas
const companiesData = await getAllCompanies({
page: 1,
limit: 10,
sort_by: 'created_at',
sort_order: 'desc'
});
// Obtener estadísticas generales
const stats = {
totalCompanies: companiesData.meta.total_companies,
activeCompanies: companiesData.meta.active_companies,
totalDocuments: companiesData.meta.total_documents_issued,
documentsThisMonth: companiesData.meta.documents_this_month
};
// Obtener empresas con mayor actividad
const topCompanies = companiesData.payload.data
.sort((a, b) => b.statistics.documents_this_month - a.statistics.documents_this_month)
.slice(0, 5);
// Obtener alertas de suscripciones próximas a vencer
const expiringSubscriptions = companiesData.payload.data
.filter(company => {
const expiresAt = new Date(company.subscription.expires_at);
const thirtyDaysFromNow = new Date();
thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);
return expiresAt <= thirtyDaysFromNow;
});
return {
stats,
topCompanies,
expiringSubscriptions,
recentCompanies: companiesData.payload.data.slice(0, 5)
};
} catch (error) {
console.error('Error construyendo dashboard:', error);
throw error;
}
};
class DataSynchronizer
{
public function syncCompanyData($accountId)
{
try {
// Obtener datos actuales
$currentData = $this->getCurrentCompanyData($accountId);
// Obtener datos desde la API
$apiData = $this->getCompanyFromApi($accountId);
// Comparar y detectar cambios
$changes = $this->detectChanges($currentData, $apiData);
if (!empty($changes)) {
// Aplicar cambios
$this->applyChanges($accountId, $changes);
// Registrar sincronización
$this->logSynchronization($accountId, $changes);
// Notificar cambios importantes
$this->notifyImportantChanges($accountId, $changes);
}
return [
'success' => true,
'changes_detected' => count($changes),
'last_sync' => now(),
'changes' => $changes
];
} catch (Exception $e) {
Log::error("Error sincronizando datos de empresa {$accountId}: {$e->getMessage()}");
return [
'success' => false,
'error' => $e->getMessage(),
'last_sync' => null
];
}
}
}
  • Permisos: Algunos endpoints requieren permisos específicos de administrador
  • Paginación: Use paginación para consultas que pueden devolver muchos resultados
  • Caché: Los datos se cachean por períodos cortos para mejorar el rendimiento
  • Límites: Existen límites de consultas por minuto para prevenir abuso
  • Filtros: Use filtros específicos para optimizar las consultas
  • Estadísticas: Las estadísticas se actualizan en tiempo real
  • Logos: Los logos se almacenan en múltiples tamaños para optimizar la carga