{"openapi":"3.1.0","info":{"title":"Zeph CRM API","version":"1.0.0","description":"API REST de Zeph CRM. Todas las rutas requieren una API key (`Authorization: Bearer vk_live_…`) creada en Settings → API Keys, con los scopes que cada operación pide.\n\n**Formato de respuesta:** éxito → `{ \"data\": … }`; listas → `{ \"data\": [...], \"pagination\": { cursor, hasMore, total } }`; error → `{ \"error\": { code, message, details? } }`.\n\n**Paginación por cursor:** pasá el `pagination.cursor` de la respuesta anterior como `?cursor=` para la página siguiente. `limit` va de 1 a 100 (default 20).\n\n**Rate limit:** por API key (default 100 req/min). Cada respuesta trae `X-RateLimit-Remaining` y `X-RateLimit-Reset` (epoch en segundos). Al superarlo: 429.\n\n**Multi-tenant:** todo se filtra por la organización dueña de la key; un id de otra organización responde 404.\n\n**Borrado:** no está disponible por API. Los `DELETE` de recursos responden 405.","contact":{"name":"Zeph Docs","url":"https://www.zephcrm.com/docs"}},"servers":[{"url":"https://www.zephcrm.com/api/v1","description":"API v1"}],"tags":[{"name":"Leads","description":"Prospectos sin calificar. Fuente configurable por nombre."},{"name":"Contacts","description":"Personas. Email único por organización."},{"name":"Companies","description":"Empresas. Nombre único por organización."},{"name":"Opportunities","description":"Oportunidades de venta en el pipeline."},{"name":"Activities","description":"Tareas, llamadas, reuniones, emails y notas."},{"name":"Pipeline","description":"Etapas del pipeline de la organización."},{"name":"Sequences","description":"Secuencias de seguimiento por email y sus enrollments."},{"name":"Campaigns","description":"Campañas de email con métricas y respuestas. Sólo lectura."},{"name":"Templates","description":"Templates de email reutilizables."},{"name":"Emails","description":"Envío de emails sueltos desde la casilla conectada del usuario y su historial."},{"name":"Search","description":"Búsqueda global en varios recursos."}],"security":[{"bearerAuth":[]}],"paths":{"/leads":{"get":{"operationId":"listLead","tags":["Leads"],"summary":"Listar leads","description":"`search` busca en nombre, apellido y email. Para usar el CRM como cola: `?status=NEW` es la entrada, `?custom.<field>=…` el estado fino.","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"},{"name":"status","in":"query","description":"Filtrar por estado.","schema":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."}},{"name":"contact_id","in":"query","description":"Leads vinculados a alguno de estos contactos (uuids separados por coma, hasta 100; más es 400). Consultalo con el lote entero antes de promover, para no crearle dos leads a nadie. Si un contacto puede tener varios leads, pedí `limit=100`.","schema":{"type":"string","example":"6f1c…,9a2e…"}},{"name":"created_after","in":"query","description":"Creados desde esta fecha (inclusive).","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"created_before","in":"query","description":"Creados hasta esta fecha (inclusive).","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"tag","in":"query","description":"Leads con alguno de estos tags (separados por coma, sin distinguir mayúsculas). Repetir el parámetro exige todos.","schema":{"type":"string","example":"fintech,saas"}},{"name":"industry","in":"query","description":"Leads cuya empresa vinculada tenga alguna de estas industrias (separadas por coma).","schema":{"type":"string","example":"Software"}},{"name":"custom.<field>","in":"query","description":"Igualdad exacta sobre un campo personalizado: `?custom.pipeline_state=awaiting_approval`. `a,b` = cualquiera de los dos; varias claves se combinan con AND. `true`/`false` encuentran tanto el booleano como el texto, y un número (`7`, `-1.5`) tanto el número como el texto.","schema":{"type":"string"}}],"responses":{"200":{"description":"Página de resultados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Lead"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["leads:read"]}],"x-required-scope":"leads:read"},"post":{"operationId":"createLead","tags":["Leads"],"summary":"Crear lead","description":"`source` se resuelve por nombre y se crea si no existe; `tags` también. Un status fuera del enum responde 400, igual que un campo desconocido. Con `contactId` el lead queda vinculado a ese contacto y, si no mandás `companyId`, hereda su empresa (`companyId`/`companyRef` en la respuesta). No se deduplica: consultá antes `GET /leads?contact_id=`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadCreate"}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Lead"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ContactOptedOut"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["leads:write"]}],"x-required-scope":"leads:write"}},"/leads/{id}":{"get":{"operationId":"getLead","tags":["Leads"],"summary":"Obtener lead","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Detalle","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/LeadDetail"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["leads:read"]}],"x-required-scope":"leads:read"},"patch":{"operationId":"updateLead","tags":["Leads"],"summary":"Actualizar lead","description":"Actualización parcial: sólo se tocan los campos presentes en el body.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadUpdate"}}}},"responses":{"200":{"description":"Actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/LeadDetail"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["leads:write"]}],"x-required-scope":"leads:write"},"delete":{"operationId":"deleteLead","tags":["Leads"],"summary":"Eliminar leads (no disponible)","description":"Borrar registros no está disponible por API. Siempre responde 405; usá la UI del CRM.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["leads:write"]}],"x-required-scope":"leads:write"}},"/leads/bulk":{"patch":{"operationId":"bulkUpdateLeads","tags":["Leads"],"summary":"Actualizar hasta 100 leads en una llamada","description":"Para lotes: marcar un estado, asignar, etiquetar o escribir campos personalizados en muchos leads con una sola request en vez de una por lead. Todo o nada: si un id no es de la organización no se toca ninguno.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadBulkUpdate"}}}},"responses":{"200":{"description":"Actualizados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/LeadBulkResult"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["leads:write"]}],"x-required-scope":"leads:write"}},"/contacts":{"get":{"operationId":"listContact","tags":["Contacts"],"summary":"Listar contacts","description":"`search` busca en nombre, apellido y email. Para usar los contactos como cola: `?custom.<field>=…&email_opt_out=false&sort=createdAt&order=asc`, y reclamar el lote con `PATCH /contacts/bulk`. Cada contacto trae `companyRef` (la empresa completa), así no hace falta un `GET /companies/{id}` por contacto.","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"},{"name":"company_id","in":"query","description":"Sólo contactos de esta empresa.","schema":{"type":"string","format":"uuid"}},{"name":"email_opt_out","in":"query","description":"`false` = sólo quienes NO se dieron de baja. Mandalo siempre que vayas a escribirle a alguien. Otro valor que no sea `true`/`false` responde 400.","schema":{"type":"string","enum":["true","false"]}},{"name":"created_after","in":"query","description":"Creados desde esta fecha (inclusive).","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"created_before","in":"query","description":"Creados hasta esta fecha (inclusive).","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"tag","in":"query","description":"Contactos con alguno de estos tags (separados por coma, sin distinguir mayúsculas). Repetir el parámetro exige todos.","schema":{"type":"string","example":"fintech,saas"}},{"name":"custom.<field>","in":"query","description":"Igualdad exacta sobre un campo personalizado: `?custom.outbound_status=pending`. `a,b` = cualquiera de los dos; varias claves se combinan con AND. `true`/`false` encuentran tanto el booleano como el texto, y un número (`7`, `-1.5`) tanto el número como el texto.","schema":{"type":"string"}}],"responses":{"200":{"description":"Página de resultados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:read"]}],"x-required-scope":"contacts:read"},"post":{"operationId":"createContact","tags":["Contacts"],"summary":"Crear contact","description":"El email es único por organización: si ya existe un contacto con ese email responde 409 con su id.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreate"}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Contact"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/DuplicateEmail"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:write"]}],"x-required-scope":"contacts:write"}},"/contacts/{id}":{"get":{"operationId":"getContact","tags":["Contacts"],"summary":"Obtener contact","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Detalle","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ContactDetail"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:read"]}],"x-required-scope":"contacts:read"},"patch":{"operationId":"updateContact","tags":["Contacts"],"summary":"Actualizar contact","description":"Actualización parcial: sólo se tocan los campos presentes en el body.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpdate"}}}},"responses":{"200":{"description":"Actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ContactDetail"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DuplicateEmail"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:write"]}],"x-required-scope":"contacts:write"},"delete":{"operationId":"deleteContact","tags":["Contacts"],"summary":"Eliminar contacts (no disponible)","description":"Borrar registros no está disponible por API. Siempre responde 405; usá la UI del CRM.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:write"]}],"x-required-scope":"contacts:write"}},"/contacts/bulk":{"patch":{"operationId":"bulkUpdateContacts","tags":["Contacts"],"summary":"Actualizar hasta 100 contactos en una llamada","description":"Para lotes: reclamar contactos escribiendo un estado propio en `customFields`, asignar dueño o etiquetar, con una sola request en vez de una por contacto. Todo o nada: si un id no es de la organización no se toca ninguno.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkUpdate"}}}},"responses":{"200":{"description":"Actualizados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ContactBulkResult"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:write"]}],"x-required-scope":"contacts:write"},"post":{"operationId":"bulkCreateContacts","tags":["Contacts"],"summary":"Crear hasta 100 contactos en una llamada","description":"Alta masiva para ingesta. Deduplica por email sin distinguir mayúsculas, como `POST /contacts`, pero un email existente no es error: la fila vuelve como `existing` con el id del contacto que ya estaba. Responde 201 si se creó al menos uno, 200 si no.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkCreate"}}}},"responses":{"200":{"description":"Ninguno nuevo: todos existían","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ContactBulkCreateResult"}},"required":["data"]}}}},"201":{"description":"Se creó al menos un contacto","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ContactBulkCreateResult"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["contacts:write"]}],"x-required-scope":"contacts:write"}},"/companies":{"get":{"operationId":"listCompany","tags":["Companies"],"summary":"Listar companies","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"}],"responses":{"200":{"description":"Página de resultados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Company"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["companies:read"]}],"x-required-scope":"companies:read"},"post":{"operationId":"createCompany","tags":["Companies"],"summary":"Crear companie","description":"El nombre es único por organización (sin distinguir mayúsculas): si ya existe responde 409 con su id.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyCreate"}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Company"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/DuplicateName"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["companies:write"]}],"x-required-scope":"companies:write"}},"/companies/{id}":{"get":{"operationId":"getCompany","tags":["Companies"],"summary":"Obtener companie","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Detalle","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompanyDetail"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["companies:read"]}],"x-required-scope":"companies:read"},"patch":{"operationId":"updateCompany","tags":["Companies"],"summary":"Actualizar companie","description":"Actualización parcial: sólo se tocan los campos presentes en el body.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyUpdate"}}}},"responses":{"200":{"description":"Actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompanyDetail"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DuplicateName"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["companies:write"]}],"x-required-scope":"companies:write"},"delete":{"operationId":"deleteCompany","tags":["Companies"],"summary":"Eliminar companies (no disponible)","description":"Borrar registros no está disponible por API. Siempre responde 405; usá la UI del CRM.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["companies:write"]}],"x-required-scope":"companies:write"}},"/opportunities":{"get":{"operationId":"listOpportunity","tags":["Opportunities"],"summary":"Listar opportunities","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"},{"name":"stage_id","in":"query","description":"Filtrar por etapa del pipeline.","schema":{"type":"string","format":"uuid"}},{"name":"contact_id","in":"query","description":"Filtrar por contacto.","schema":{"type":"string","format":"uuid"}},{"name":"company_id","in":"query","description":"Filtrar por empresa.","schema":{"type":"string","format":"uuid"}},{"name":"created_after","in":"query","description":"Creadas desde esta fecha.","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"created_before","in":"query","description":"Creadas hasta esta fecha.","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"close_after","in":"query","description":"Con cierre esperado desde esta fecha.","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"close_before","in":"query","description":"Con cierre esperado hasta esta fecha.","schema":{"type":"string","format":"date-time","example":"2026-01-01"}}],"responses":{"200":{"description":"Página de resultados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Opportunity"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["opportunities:read"]}],"x-required-scope":"opportunities:read"},"post":{"operationId":"createOpportunity","tags":["Opportunities"],"summary":"Crear opportunitie","description":"Si `companyId` se omite, hereda la empresa del contacto. Si la etapa es ganada/perdida, se sella `wonAt`/`lostAt` al crear.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpportunityCreate"}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Opportunity"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["opportunities:write"]}],"x-required-scope":"opportunities:write"}},"/opportunities/{id}":{"get":{"operationId":"getOpportunity","tags":["Opportunities"],"summary":"Obtener opportunitie","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Detalle","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OpportunityDetail"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["opportunities:read"]}],"x-required-scope":"opportunities:read"},"patch":{"operationId":"updateOpportunity","tags":["Opportunities"],"summary":"Actualizar opportunitie","description":"Actualización parcial: sólo se tocan los campos presentes en el body.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpportunityUpdate"}}}},"responses":{"200":{"description":"Actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OpportunityDetail"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["opportunities:write"]}],"x-required-scope":"opportunities:write"},"delete":{"operationId":"deleteOpportunity","tags":["Opportunities"],"summary":"Eliminar opportunities (no disponible)","description":"Borrar registros no está disponible por API. Siempre responde 405; usá la UI del CRM.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["opportunities:write"]}],"x-required-scope":"opportunities:write"}},"/activities":{"get":{"operationId":"listActivity","tags":["Activities"],"summary":"Listar activities","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"},{"name":"type","in":"query","description":"Filtrar por tipo.","schema":{"type":"string","enum":["TASK","CALL","MEETING","EMAIL","NOTE"]}},{"name":"status","in":"query","description":"`PENDING` = sin completar, `COMPLETED` = completadas.","schema":{"type":"string","enum":["PENDING","COMPLETED"]}},{"name":"assigned_to","in":"query","description":"Filtrar por usuario asignado.","schema":{"type":"string","format":"uuid"}},{"name":"contact_id","in":"query","description":"Filtrar por contacto.","schema":{"type":"string","format":"uuid"}},{"name":"company_id","in":"query","description":"Actividades cuyo contacto pertenece a esta empresa.","schema":{"type":"string","format":"uuid"}},{"name":"opportunity_id","in":"query","description":"Filtrar por oportunidad.","schema":{"type":"string","format":"uuid"}},{"name":"due_after","in":"query","description":"Con vencimiento desde esta fecha.","schema":{"type":"string","format":"date-time","example":"2026-01-01"}},{"name":"due_before","in":"query","description":"Con vencimiento hasta esta fecha.","schema":{"type":"string","format":"date-time","example":"2026-01-01"}}],"responses":{"200":{"description":"Página de resultados","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Activity"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["activities:read"]}],"x-required-scope":"activities:read"},"post":{"operationId":"createActivity","tags":["Activities"],"summary":"Crear activitie","description":"`dueDate` es obligatoria para `TASK`. `contactId`, `opportunityId` y `assignedToId` deben existir en la organización (404 si no).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityCreate"}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Activity"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["activities:write"]}],"x-required-scope":"activities:write"}},"/activities/{id}":{"get":{"operationId":"getActivity","tags":["Activities"],"summary":"Obtener activitie","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Detalle","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ActivityDetail"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["activities:read"]}],"x-required-scope":"activities:read"},"patch":{"operationId":"updateActivity","tags":["Activities"],"summary":"Actualizar activitie","description":"Actualización parcial: sólo se tocan los campos presentes en el body.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityUpdate"}}}},"responses":{"200":{"description":"Actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ActivityDetail"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["activities:write"]}],"x-required-scope":"activities:write"},"delete":{"operationId":"deleteActivity","tags":["Activities"],"summary":"Eliminar activities (no disponible)","description":"Borrar registros no está disponible por API. Siempre responde 405; usá la UI del CRM.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["activities:write"]}],"x-required-scope":"activities:write"}},"/pipeline-stages":{"get":{"operationId":"listPipelineStages","tags":["Pipeline"],"summary":"Listar etapas del pipeline","description":"Ordenadas por `order`. Sin paginación: una organización tiene pocas etapas.","responses":{"200":{"description":"Etapas","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStage"}}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["pipeline:read"]}],"x-required-scope":"pipeline:read"}},"/search":{"get":{"operationId":"search","tags":["Search"],"summary":"Búsqueda global","description":"Busca en varios recursos a la vez. Requiere al menos un scope `:read`; cada tipo aparece sólo si la key tiene su scope. Máximo `limit` resultados por tipo.","security":[{"bearerAuth":["leads:read"]},{"bearerAuth":["contacts:read"]},{"bearerAuth":["companies:read"]},{"bearerAuth":["opportunities:read"]},{"bearerAuth":["activities:read"]}],"parameters":[{"name":"q","in":"query","required":true,"description":"Texto a buscar (mínimo 2 caracteres).","schema":{"type":"string","minLength":2}},{"name":"types","in":"query","description":"Tipos a incluir, separados por coma. Por defecto todos los permitidos.","schema":{"type":"string","example":"leads,contacts"}},{"name":"limit","in":"query","description":"Máximo por tipo (1–20).","schema":{"type":"integer","minimum":1,"maximum":20,"default":5}}],"responses":{"200":{"description":"Resultados por tipo","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchResults"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/sequences":{"get":{"operationId":"listSequences","tags":["Sequences"],"summary":"Listar secuencias de seguimiento","description":"Las 50 más recientes. Sin paginación.","responses":{"200":{"description":"Secuencias","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Sequence"}}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["sequences:read"]}],"x-required-scope":"sequences:read"}},"/sequences/{id}":{"get":{"operationId":"getSequence","tags":["Sequences"],"summary":"Obtener secuencia con sus pasos","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Secuencia","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SequenceDetail"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["sequences:read"]}],"x-required-scope":"sequences:read"}},"/sequences/{id}/enrollments":{"post":{"operationId":"enrollLeads","tags":["Sequences"],"summary":"Enrolar contactos en una secuencia","description":"Hasta 100 ids por llamada en `contactIds` (o `leadIds`, deprecado). Un contacto con un seguimiento activo no se vuelve a enrolar: aparece en `skipped` con `code` y motivo. El email sale desde la casilla conectada del usuario de la API key. Las secuencias propias de una campaña responden 422 `SEQUENCE_OWNED_BY_CAMPAIGN`.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollRequest"}}}},"responses":{"201":{"description":"Resultado del enrolamiento","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EnrollResult"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"description":"No se pudo enrolar","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"ENROLLMENT_FAILED","message":"Sequence is not active"}}},{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"SEQUENCE_OWNED_BY_CAMPAIGN","message":"Sequence belongs to a campaign"}}}]}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["sequences:write"]}],"x-required-scope":"sequences:write"}},"/enrollments":{"get":{"operationId":"listEnrollments","tags":["Sequences"],"summary":"Listar enrollments","description":"Hay que pasar al menos uno de `leadId`, `contactId`, `sequenceId` o `campaignId`. Los 50 más recientes.","parameters":[{"name":"leadId","in":"query","description":"Enrollments de este lead y de su contacto. 404 si el lead no existe.","schema":{"type":"string","format":"uuid"}},{"name":"contactId","in":"query","description":"Enrollments de este contacto (con o sin lead).","schema":{"type":"string","format":"uuid"}},{"name":"sequenceId","in":"query","description":"Enrollments de esta secuencia. 404 si es la secuencia propia de una campaña que el dueño de la key no ve.","schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"query","description":"Enrollments que originó esta campaña. 404 si no existe o el dueño de la key no la ve.","schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","description":"Filtrar por estado.","schema":{"type":"string","enum":["ACTIVE","WAITING_APPROVAL","REPLIED","COMPLETED","CANCELLED","FAILED"]}}],"responses":{"200":{"description":"Enrollments","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Enrollment"}}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["sequences:read"]}],"x-required-scope":"sequences:read"}},"/enrollments/{id}":{"delete":{"operationId":"cancelEnrollment","tags":["Sequences"],"summary":"Cancelar un enrollment","description":"Sólo se cancelan los que están en `ACTIVE` o `WAITING_APPROVAL`; el resto responde 422. Uno que vino de una campaña lo cancela sólo un dueño de key que la creó o es ADMIN; si no, responde 404, igual que uno inexistente.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Cancelado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EnrollmentCancelled"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/InvalidState"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["sequences:write"]}],"x-required-scope":"sequences:write"}},"/campaigns":{"get":{"operationId":"listCampaigns","tags":["Campaigns"],"summary":"Listar campañas con métricas","description":"Sólo campañas (no newsletters): se mandan esperando respuesta, y la tasa de respuesta es la métrica que importa. Las tasas ya vienen calculadas.","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"},{"name":"status","in":"query","description":"Filtrar por estado: DRAFT, SCHEDULED, SENDING, COMPLETED o CANCELLED (no distingue mayúsculas).","schema":{"type":"string","enum":["DRAFT","SCHEDULED","SENDING","COMPLETED","CANCELLED"]}}],"responses":{"200":{"description":"Campañas","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["campaigns:read"]}],"x-required-scope":"campaigns:read"}},"/campaigns/{id}/recipients":{"get":{"operationId":"listCampaignRecipients","tags":["Campaigns"],"summary":"Destinatarios de una campaña","description":"`?replied=true` devuelve a quién ir a buscar, con `contactId` y `leadId` para encadenar con el resto de la API. Los que respondieron van primero.","parameters":[{"$ref":"#/components/parameters/id"},{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"name":"replied","in":"query","description":"Sólo los que respondieron (`true`) o los que no (`false`).","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Destinatarios","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignRecipient"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["campaigns:read"]}],"x-required-scope":"campaigns:read"}},"/emails":{"get":{"operationId":"listEmails","tags":["Emails"],"summary":"Emails enviados","description":"Hay que pasar al menos un filtro. Los 50 más recientes. Sirve para saber qué se le mandó ya a alguien antes de volver a escribirle.","parameters":[{"name":"leadId","in":"query","description":"Enviados vinculados a este lead.","schema":{"type":"string","format":"uuid"}},{"name":"contactId","in":"query","description":"Enviados vinculados a este contacto.","schema":{"type":"string","format":"uuid"}},{"name":"opportunityId","in":"query","description":"Enviados vinculados a esta oportunidad.","schema":{"type":"string","format":"uuid"}},{"name":"to","in":"query","description":"Enviados a esta dirección (sin distinguir mayúsculas).","schema":{"type":"string","format":"email"}}],"responses":{"200":{"description":"Emails","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SentEmail"}}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["emails:read"]}],"x-required-scope":"emails:read"},"post":{"operationId":"sendEmail","tags":["Emails"],"summary":"Enviar un email","description":"Manda un email real, de a uno, desde la casilla Gmail/Outlook conectada del dueño de la API key. A quien se dio de baja no se le escribe: 422 `EMAIL_OPT_OUT` (salvo `to: \"owner\"`, que es un preview a uno mismo). Queda registrado en el CRM (y en el timeline del lead/contacto si se vincula) con `threadId` para seguir el hilo. Para un preview: `to: \"owner\"`. Mandá siempre `idempotencyKey`: es lo que garantiza que un reintento no duplique el envío.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSend"}}}},"responses":{"200":{"description":"Ya se había enviado con esta `idempotencyKey`: se devuelve el original, no se manda de nuevo","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SentEmail"}},"required":["data"]}}}},"201":{"description":"Enviado y registrado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SentEmail"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/InProgress"},"422":{"description":"`EMAIL_OPT_OUT`: el destinatario se dio de baja (el contacto de `contactId`, el contacto del lead de `leadId`, o un contacto con la dirección de `to`); no reintentar. `NO_EMAIL_ACCOUNT`: el dueño de la key no tiene casilla conectada.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"EMAIL_OPT_OUT","message":"The recipient has opted out of emails"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/SendFailed"}},"security":[{"bearerAuth":["emails:write"]}],"x-required-scope":"emails:write"}},"/templates":{"get":{"operationId":"listTemplates","tags":["Templates"],"summary":"Listar templates de email","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"$ref":"#/components/parameters/order"},{"$ref":"#/components/parameters/search"},{"name":"active","in":"query","description":"Sólo activos (`true`) o inactivos (`false`).","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Templates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["templates:read"]}],"x-required-scope":"templates:read"},"post":{"operationId":"createTemplate","tags":["Templates"],"summary":"Crear template de email","description":"El nombre es único por organización. Las variables `{{nombre}}` se detectan en asunto y cuerpo.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreate"}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Template"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/DuplicateName"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearerAuth":["templates:write"]}],"x-required-scope":"templates:write"}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key con prefijo `vk_live_` (las `vx_live_` antiguas siguen siendo válidas). Los scopes que cada operación requiere figuran en `x-required-scope` y en el campo `security`."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Código estable para tratar en código.","enum":["UNAUTHORIZED","FORBIDDEN","RATE_LIMITED","NOT_FOUND","INVALID_JSON","VALIDATION_ERROR","DUPLICATE_EMAIL","DUPLICATE_NAME","METHOD_NOT_ALLOWED","ENROLLMENT_FAILED","SEQUENCE_OWNED_BY_CAMPAIGN","INVALID_STATE","NO_EMAIL_ACCOUNT","SEND_FAILED","IN_PROGRESS","CONTACT_OPTED_OUT","EMAIL_OPT_OUT"]},"message":{"type":"string","description":"Mensaje legible."},"details":{"type":"object","additionalProperties":true,"description":"En `VALIDATION_ERROR`: errores por campo (`{ campo: [mensajes] }`). Un campo que el endpoint no conoce aparece como `{ campo: [\"Unknown field\"] }`."}},"required":["code","message"]}},"required":["error"]},"Pagination":{"type":"object","properties":{"cursor":{"type":"string","description":"Cursor para la página siguiente. Ausente cuando `hasMore` es false."},"hasMore":{"type":"boolean"},"total":{"type":"integer","description":"Total de registros que cumplen el filtro."}},"required":["hasMore","total"]},"Tag":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"type":"string","description":"Hex, ej. `#6b7280`."}}},"LeadCompanyRef":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"website":{"type":["string","null"]},"employeeCount":{"type":["integer","null"]},"industry":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"country":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}}},"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"company":{"type":["string","null"],"description":"Nombre de empresa como texto libre (no es la relación con Company)."},"position":{"type":["string","null"]},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."},"notes":{"type":["string","null"]},"aiScore":{"type":["integer","null"],"description":"Puntaje 0–100 calculado por IA, si está disponible."},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"assignedToId":{"type":"string","format":"uuid"},"followUpDate":{"type":["string","null"],"format":"date-time"},"leadSourceId":{"type":["string","null"],"format":"uuid"},"leadSource":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"source":{"type":["string","null"],"description":"Alias plano: nombre de `leadSource`."},"sourceDetail":{"type":["string","null"]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/Tag"},"description":"Tags de la organización asignados al lead."},"companyId":{"type":["string","null"],"format":"uuid","description":"Empresa vinculada (registro Company)."},"companyRef":{"$ref":"#/components/schemas/LeadCompanyRef","description":"Empresa vinculada (registro Company), con lo enumerable: industria, tamaño, país, sitio."},"contactId":{"type":["string","null"],"format":"uuid","description":"Contacto del que salió el lead, si lo hay."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"LeadDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"company":{"type":["string","null"],"description":"Nombre de empresa como texto libre (no es la relación con Company)."},"position":{"type":["string","null"]},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."},"notes":{"type":["string","null"]},"aiScore":{"type":["integer","null"],"description":"Puntaje 0–100 calculado por IA, si está disponible."},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"assignedToId":{"type":"string","format":"uuid"},"followUpDate":{"type":["string","null"],"format":"date-time"},"leadSourceId":{"type":["string","null"],"format":"uuid"},"leadSource":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"source":{"type":["string","null"],"description":"Alias plano: nombre de `leadSource`."},"sourceDetail":{"type":["string","null"]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/Tag"},"description":"Tags de la organización asignados al lead."},"companyId":{"type":["string","null"],"format":"uuid","description":"Empresa vinculada (registro Company)."},"companyRef":{"$ref":"#/components/schemas/LeadCompanyRef","description":"Empresa vinculada (registro Company), con lo enumerable: industria, tamaño, país, sitio."},"contactId":{"type":["string","null"],"format":"uuid","description":"Contacto del que salió el lead, si lo hay."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"assignedTo":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"contactRef":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"}},"description":"Contacto vinculado."}}},"LeadCreate":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","format":"email"},"phone":{"type":"string","maxLength":50},"company":{"type":"string","maxLength":100},"position":{"type":"string","maxLength":100},"notes":{"type":"string","maxLength":2000},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."},"assignedToId":{"type":"string","format":"uuid","description":"Si se omite, se asigna al usuario dueño de la API key."},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"followUpDate":{"type":"string","description":"Fecha ISO 8601.","format":"date-time"},"source":{"type":"string","description":"Nombre de la fuente del lead. Se busca sin distinguir mayúsculas y se crea si no existe.","maxLength":100},"sourceDetail":{"type":"string","maxLength":200},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":20,"description":"Nombres de tags. Se buscan sin distinguir mayúsculas y se crean los que no existen."},"contactId":{"type":"string","format":"uuid","description":"Contacto del que sale el lead. Debe ser de la organización (404 si no) y no estar dado de baja (422 `CONTACT_OPTED_OUT`). Si no se manda `companyId`, el lead hereda la empresa del contacto."},"companyId":{"type":"string","format":"uuid","description":"Empresa vinculada (registro Company, no el texto de `company`). Debe ser de la organización (404 si no). Si viene junto con `contactId`, gana esta."}},"required":["firstName","lastName","email"],"additionalProperties":false},"LeadUpdate":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","format":"email"},"phone":{"type":"string","maxLength":50},"company":{"type":"string","maxLength":100},"position":{"type":"string","maxLength":100},"notes":{"type":"string","maxLength":2000},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."},"assignedToId":{"type":"string","format":"uuid"},"customFields":{"type":"object","additionalProperties":true,"description":"Se MERGEA por clave con lo que ya tiene el lead: cada clave enviada pisa la anterior, `null` la elimina y las no enviadas quedan como están."},"source":{"type":"string","description":"Nombre de la fuente del lead. Se busca sin distinguir mayúsculas y se crea si no existe.","maxLength":100},"sourceDetail":{"type":"string","maxLength":200},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":20,"description":"Reemplaza el conjunto completo de tags. `[]` deja el lead sin tags."}},"description":"Sólo se aplican los campos enviados. `followUpDate` no es editable por PATCH. `aiScore` es calculado por el CRM y no se escribe.","additionalProperties":false},"LeadBulkUpdate":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"description":"Todos deben ser de la organización; si falta alguno, 404 con la lista y no se toca nada."},"data":{"type":"object","properties":{"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."},"assignedToId":{"type":"string","format":"uuid"},"notes":{"type":["string","null"],"maxLength":2000},"followUpDate":{"type":["string","null"],"format":"date-time"},"customFields":{"type":"object","additionalProperties":true,"description":"Se MERGEA por clave con lo que ya tiene el lead: cada clave enviada pisa la anterior, `null` la elimina y las no enviadas quedan como están."},"addTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":20,"description":"Tags a AGREGAR a cada lead (no reemplaza los que ya tiene)."}},"description":"Al menos un campo.","additionalProperties":false}},"required":["ids","data"],"additionalProperties":false},"LeadBulkResult":{"type":"object","properties":{"updated":{"type":"integer","description":"Cantidad de leads actualizados."}}},"Contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"mobile":{"type":["string","null"]},"position":{"type":["string","null"]},"companyId":{"type":["string","null"],"format":"uuid"},"companyRef":{"$ref":"#/components/schemas/LeadCompanyRef","description":"Empresa vinculada, con la misma forma que en `/leads`: sitio, empleados, industria, país."},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"ownerId":{"type":"string","format":"uuid"},"emailOptOut":{"type":"boolean","description":"`true` = se dio de baja de los emails. No escribirle ni promoverlo a lead."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/Tag"},"description":"Tags de la organización asignados al contacto."}}},"ContactDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"mobile":{"type":["string","null"]},"position":{"type":["string","null"]},"companyId":{"type":["string","null"],"format":"uuid"},"companyRef":{"$ref":"#/components/schemas/LeadCompanyRef","description":"Empresa vinculada, con la misma forma que en `/leads`: sitio, empleados, industria, país."},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"notes":{"type":["string","null"]},"emailOptOut":{"type":"boolean","description":"`true` = se dio de baja de los emails. No escribirle ni promoverlo a lead."},"company":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"description":"Forma corta de la empresa; `companyRef` trae la completa."},"owner":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}}}},"ContactCreate":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"type":["string","null"],"description":"Único por organización (sin distinguir mayúsculas).","format":"email"},"phone":{"type":["string","null"],"maxLength":50},"mobile":{"type":["string","null"],"maxLength":50},"position":{"type":["string","null"],"maxLength":100},"companyId":{"type":["string","null"],"format":"uuid"},"notes":{"type":["string","null"],"maxLength":2000},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"ownerId":{"type":"string","format":"uuid","description":"Si se omite, el dueño es el usuario de la API key."}},"required":["firstName","lastName"],"additionalProperties":false},"ContactUpdate":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"type":["string","null"],"description":"Único por organización (sin distinguir mayúsculas).","format":"email"},"phone":{"type":["string","null"],"maxLength":50},"mobile":{"type":["string","null"],"maxLength":50},"position":{"type":["string","null"],"maxLength":100},"companyId":{"type":["string","null"],"format":"uuid"},"notes":{"type":["string","null"],"maxLength":2000},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"emailOptOut":{"type":"boolean","const":true,"description":"Sólo `true`: da de baja al contacto de los emails y sella `emailOptOutAt`. Desde ahí `POST /emails` se niega a escribirle (422 `EMAIL_OPT_OUT`). Volver a darlo de alta no se puede por API (400): se hace desde la UI."}},"description":"Sólo se aplican los campos enviados.","additionalProperties":false},"ContactBulkUpdate":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"description":"Todos deben ser de la organización; si falta alguno, 404 con la lista y no se toca nada."},"data":{"type":"object","properties":{"ownerId":{"type":"string","format":"uuid","description":"Debe ser un usuario de la organización."},"customFields":{"type":"object","additionalProperties":true,"description":"Se MERGEA por clave con lo que ya tiene el contacto: cada clave enviada pisa la anterior, `null` la elimina y las no enviadas quedan como están."},"addTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":20,"description":"Tags a AGREGAR a cada contacto (no reemplaza los que ya tiene)."}},"description":"Al menos un campo.","additionalProperties":false}},"required":["ids","data"],"additionalProperties":false},"ContactBulkResult":{"type":"object","properties":{"updated":{"type":"integer","description":"Cantidad de contactos actualizados."}}},"ContactBulkCreate":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactCreate"},"minItems":1,"maxItems":100,"description":"Cada fila con las mismas reglas que `POST /contacts`. `companyId` y `ownerId` deben ser de la organización (si alguno no, 404 y no se crea nada)."}},"required":["contacts"],"additionalProperties":false},"ContactBulkCreateResult":{"type":"object","properties":{"created":{"type":"integer","description":"Filas insertadas ahora."},"existing":{"type":"integer","description":"Filas cuyo email ya tenía contacto (sin distinguir mayúsculas)."},"duplicate":{"type":"integer","description":"Filas que repiten el email de otra fila anterior del mismo lote."},"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","description":"Posición de la fila en `contacts`."},"id":{"type":"string","format":"uuid","description":"Id del contacto: el nuevo, el que ya existía, o el de la fila anterior con el mismo email."},"status":{"type":"string","enum":["created","existing","duplicate"]},"email":{"type":["string","null"]}},"required":["index","id","status","email"]},"description":"Una entrada por fila, en el mismo orden del body."}}},"Company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"website":{"type":["string","null"],"format":"uri"},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"employeeCount":{"type":["integer","null"]},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CompanyDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"website":{"type":["string","null"],"format":"uri"},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"employeeCount":{"type":["integer","null"]},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"logoUrl":{"type":["string","null"]},"owner":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"industry":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"country":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"_count":{"type":"object","properties":{"contacts":{"type":"integer"},"opportunities":{"type":"integer"}}}}},"CompanyCreate":{"type":"object","properties":{"name":{"type":"string","description":"Único por organización (sin distinguir mayúsculas).","minLength":1,"maxLength":100},"website":{"type":["string","null"],"format":"uri"},"phone":{"type":["string","null"],"maxLength":50},"address":{"type":["string","null"],"maxLength":200},"city":{"type":["string","null"],"maxLength":100},"employeeCount":{"type":["integer","null"],"minimum":1},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"ownerId":{"type":"string","format":"uuid","description":"Si se omite, el dueño es el usuario de la API key."}},"required":["name"]},"CompanyUpdate":{"type":"object","properties":{"name":{"type":"string","description":"Único por organización (sin distinguir mayúsculas).","minLength":1,"maxLength":100},"website":{"type":["string","null"],"format":"uri"},"phone":{"type":["string","null"],"maxLength":50},"address":{"type":["string","null"],"maxLength":200},"city":{"type":["string","null"],"maxLength":100},"employeeCount":{"type":["integer","null"],"minimum":1},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"industryId":{"type":"string","format":"uuid"},"countryId":{"type":"string","format":"uuid"}},"description":"Sólo se aplican los campos enviados."},"Opportunity":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"value":{"type":"number","description":"Monto en la moneda indicada."},"currency":{"type":"string","enum":["USD","ARS","EUR"]},"expectedCloseDate":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"stageId":{"type":"string","format":"uuid"},"contactId":{"type":"string","format":"uuid"},"companyId":{"type":["string","null"],"format":"uuid"},"quoteTotal":{"type":["number","null"]},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"OpportunityDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"value":{"type":"number","description":"Monto en la moneda indicada."},"currency":{"type":"string","enum":["USD","ARS","EUR"]},"expectedCloseDate":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"stageId":{"type":"string","format":"uuid"},"contactId":{"type":"string","format":"uuid"},"companyId":{"type":["string","null"],"format":"uuid"},"quoteTotal":{"type":["number","null"]},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"lostReason":{"type":["string","null"]},"wonAt":{"type":["string","null"],"format":"date-time"},"lostAt":{"type":["string","null"],"format":"date-time"},"quoteItems":{"type":["array","null"],"items":{"type":"object","additionalProperties":true}},"quoteSubtotal":{"type":["number","null"]},"quoteTax":{"type":["number","null"]},"quoteDiscount":{"type":["number","null"]},"quoteNotes":{"type":["string","null"]},"stage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"isWon":{"type":"boolean"},"isLost":{"type":"boolean"}}},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"]}}},"company":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"assignedTo":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}}}},"OpportunityCreate":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"value":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","ARS","EUR"],"default":"USD"},"expectedCloseDate":{"type":"string","description":"Fecha ISO 8601.","format":"date-time"},"stageId":{"type":"string","format":"uuid","description":"Debe pertenecer a la organización (ver `GET /pipeline-stages`)."},"contactId":{"type":"string","format":"uuid","description":"Debe pertenecer a la organización."},"companyId":{"type":["string","null"],"format":"uuid","description":"Si se omite, hereda la empresa del contacto."},"assignedToId":{"type":"string","format":"uuid","description":"Si se omite, se asigna al usuario de la API key."},"description":{"type":["string","null"],"maxLength":2000},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."},"followUpDate":{"type":"string","description":"Fecha ISO 8601.","format":"date-time"}},"required":["title","value","expectedCloseDate","stageId","contactId"]},"OpportunityUpdate":{"type":"object","properties":{"title":{"type":"string"},"value":{"type":"number"},"currency":{"type":"string","enum":["USD","ARS","EUR"]},"expectedCloseDate":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"stageId":{"type":"string","format":"uuid"},"contactId":{"type":"string","format":"uuid"},"companyId":{"type":["string","null"],"format":"uuid"},"assignedToId":{"type":"string","format":"uuid"},"customFields":{"type":["object","null"],"additionalProperties":true,"description":"Campos personalizados definidos por la organización. Objeto libre."}},"description":"Sólo se aplican los campos enviados."},"Activity":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["TASK","CALL","MEETING","EMAIL","NOTE"]},"title":{"type":"string"},"description":{"type":["string","null"]},"dueDate":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time","description":"`null` = pendiente."},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"contactId":{"type":["string","null"],"format":"uuid"},"opportunityId":{"type":["string","null"],"format":"uuid"},"assignedToId":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ActivityDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["TASK","CALL","MEETING","EMAIL","NOTE"]},"title":{"type":"string"},"description":{"type":["string","null"]},"dueDate":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"reminderAt":{"type":["string","null"],"format":"date-time"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"contact":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"]}}},"opportunity":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"}}},"assignedTo":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"createdBy":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ActivityCreate":{"type":"object","properties":{"type":{"type":"string","enum":["TASK","CALL","MEETING","EMAIL","NOTE"]},"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"dueDate":{"type":"string","description":"Fecha ISO 8601. Obligatoria cuando `type` es `TASK`.","format":"date-time"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"],"default":"MEDIUM"},"contactId":{"type":"string","format":"uuid","description":"Debe pertenecer a la organización."},"opportunityId":{"type":"string","format":"uuid","description":"Debe pertenecer a la organización."},"assignedToId":{"type":"string","format":"uuid","description":"Debe pertenecer a la organización. Si se omite, el usuario de la API key."}},"required":["type","title"]},"ActivityUpdate":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":["string","null"]},"dueDate":{"type":["string","null"],"format":"date-time"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"type":{"type":"string","enum":["TASK","CALL","MEETING","EMAIL","NOTE"]},"contactId":{"type":["string","null"],"format":"uuid"},"opportunityId":{"type":["string","null"],"format":"uuid"},"assignedToId":{"type":"string","format":"uuid"},"completedAt":{"type":["string","null"],"format":"date-time","description":"Fecha para marcar como completada; `null` para reabrir."}},"description":"Sólo se aplican los campos enviados."},"PipelineStage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"order":{"type":"integer"},"color":{"type":["string","null"]},"probability":{"type":"integer","description":"Probabilidad de cierre 0–100."},"isDefault":{"type":"boolean","description":"Etapa inicial de las oportunidades nuevas."},"isWon":{"type":"boolean"},"isLost":{"type":"boolean"}}},"Sequence":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"isActive":{"type":"boolean"},"reviewMode":{"type":"boolean","description":"Si es true, cada borrador espera aprobación humana antes de enviarse."},"language":{"type":["string","null"]},"stepCount":{"type":"integer"},"activeEnrollments":{"type":"integer","description":"Enrollments en estado ACTIVE o WAITING_APPROVAL."},"createdAt":{"type":"string","format":"date-time"}}},"SequenceStep":{"type":"object","properties":{"order":{"type":"integer"},"mode":{"type":"string","enum":["AI","TEMPLATE","MANUAL"],"description":"De dónde sale el contenido del paso."},"briefing":{"type":["string","null"],"description":"Instrucciones para la IA (modo AI)."},"templateId":{"type":["string","null"],"format":"uuid","description":"Template usado (modo TEMPLATE)."},"subject":{"type":["string","null"],"description":"Sólo el primer paso lleva asunto; los demás responden en el hilo."},"delayValue":{"type":"integer"},"delayUnit":{"type":"string","enum":["hours","days"]}}},"SequenceDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"isActive":{"type":"boolean"},"reviewMode":{"type":"boolean"},"tone":{"type":["string","null"]},"language":{"type":["string","null"]},"sendWindow":{"type":["object","null"],"description":"Ventana de envío en la zona horaria de la organización. `null` = sin restricción.","properties":{"days":{"type":"array","items":{"type":"integer","description":"0 = domingo … 6 = sábado"}},"startHour":{"type":"integer"},"endHour":{"type":"integer"}}},"createdAt":{"type":"string","format":"date-time"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStep"}}}},"EnrollRequest":{"type":"object","properties":{"contactIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":100,"description":"Contactos a enrolar. El seguimiento es del contacto."},"leadIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":100,"deprecated":true,"description":"Deprecado: usá `contactIds`. Se sigue aceptando; la respuesta lleva el header `Deprecation: true` y un `Link` a esta documentación."}},"description":"Al menos uno de los dos, hasta 100 ids en total y sin repetidos.","additionalProperties":false},"EnrollResult":{"type":"object","properties":{"enrolled":{"type":"integer","description":"Cantidad de contactos enrolados."},"skipped":{"type":"array","items":{"type":"object","properties":{"leadId":{"type":["string","null"],"format":"uuid"},"contactId":{"type":["string","null"],"format":"uuid"},"code":{"type":"string","enum":["NOT_FOUND","NO_EMAIL","OPT_OUT","ALREADY_ACTIVE","LEAD_CLOSED"]},"reason":{"type":"string","description":"Motivo legible."}}},"description":"Los que no se enrolaron, con un código estable y el motivo."}}},"Enrollment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["ACTIVE","WAITING_APPROVAL","REPLIED","COMPLETED","CANCELLED","FAILED"]},"currentStep":{"type":"integer","description":"Último paso enviado (0 = todavía ninguno)."},"totalSteps":{"type":"integer"},"nextSendAt":{"type":["string","null"],"format":"date-time"},"threadId":{"type":["string","null"],"description":"Hilo de email en el que se conversa."},"repliedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"cancelledAt":{"type":["string","null"],"format":"date-time"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"sequence":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid","description":"`null` si es la secuencia propia de una campaña que el dueño de la key no ve."},"name":{"type":["string","null"],"description":"`null` si es la secuencia propia de una campaña que el dueño de la key no ve."},"reviewMode":{"type":"boolean"}}},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"]}}},"campaignId":{"type":["string","null"],"format":"uuid","description":"Campaña que originó el seguimiento, si vino de una. `null` también si el dueño de la key no ve esa campaña (un ADMIN ve todas; otro rol, sólo las que creó)."},"repliedAfterStep":{"type":["integer","null"],"description":"Paso después del cual respondió."},"lead":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"}},"description":"Lead vinculado. `null` cuando el seguimiento es sólo del contacto."}}},"EnrollmentCancelled":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["CANCELLED"]}}},"Campaign":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"version":{"type":"integer","description":"1 = campaña de un solo email; 2 = campaña outbound con pasos propios."},"subject":{"type":["string","null"],"description":"`null` cuando el paso 1 lo redacta la IA: cada email lleva su propio asunto."},"status":{"type":"string","enum":["DRAFT","SCHEDULED","SENDING","COMPLETED","CANCELLED"]},"sentAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"totalRecipients":{"type":"integer"},"totalSent":{"type":"integer"},"totalOpened":{"type":"integer"},"totalClicked":{"type":"integer"},"totalBounced":{"type":"integer"},"totalReplied":{"type":"integer"},"repliesCheckedAt":{"type":["string","null"],"format":"date-time","description":"Última corrida del cron que buscó respuestas."},"templateId":{"type":["string","null"],"format":"uuid"},"followUpSequenceId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"openRate":{"type":"number","description":"Porcentaje sobre `totalSent`, un decimal."},"clickRate":{"type":"number","description":"Porcentaje sobre `totalSent`, un decimal."},"replyRate":{"type":"number","description":"Porcentaje sobre `totalSent`, un decimal."},"followUpSequence":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"stepCount":{"type":"integer"}}},"followUp":{"type":["object","null"],"properties":{"running":{"type":"integer"},"awaitingApproval":{"type":"integer"},"replied":{"type":"integer"},"completed":{"type":"integer"},"cancelled":{"type":"integer"},"failed":{"type":"integer"},"total":{"type":"integer"}},"description":"Estado de los seguimientos que disparó esta campaña. `null` si no tiene secuencia asociada."},"steps":{"type":"array","items":{"type":"object","properties":{"order":{"type":"integer"},"mode":{"type":"string","enum":["AI","TEMPLATE","MANUAL"]},"sent":{"type":"integer","description":"Emails enviados de este paso."},"repliedAfter":{"type":"integer","description":"Respuestas que llegaron después de este paso."}}},"description":"Pasos de una campaña v2. Vacío en las v1."}}},"CampaignRecipient":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["PENDING","SENT","DELIVERED","OPENED","CLICKED","BOUNCED","FAILED"]},"sentAt":{"type":["string","null"],"format":"date-time"},"openedAt":{"type":["string","null"],"format":"date-time"},"clickedAt":{"type":["string","null"],"format":"date-time"},"bouncedAt":{"type":["string","null"],"format":"date-time"},"repliedAt":{"type":["string","null"],"format":"date-time"},"replied":{"type":"boolean"},"email":{"type":"string"},"contactId":{"type":["string","null"],"format":"uuid"},"contactName":{"type":["string","null"]},"leadId":{"type":["string","null"],"format":"uuid","description":"Lead del seguimiento; si no tiene, el más reciente del contacto."},"leadStatus":{"type":["string","null"],"enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."},"enrollment":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["ACTIVE","WAITING_APPROVAL","REPLIED","COMPLETED","CANCELLED","FAILED"]},"currentStep":{"type":"integer"}},"description":"Seguimiento de este destinatario (campañas v2). `null` si no tiene."},"skippedReason":{"type":["string","null"],"description":"Código por el que se omitió al lanzar la campaña."}}},"Template":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subject":{"type":"string"},"variables":{"type":"array","items":{"type":"string"},"description":"Variables `{{nombre}}` detectadas en asunto y cuerpo."},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"TemplateCreate":{"type":"object","properties":{"name":{"type":"string","description":"Único por organización (sin distinguir mayúsculas).","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","description":"HTML del email. Se normaliza al guardar (colores a hexadecimal). Las variables se detectan solas.","minLength":1,"maxLength":200000},"isActive":{"type":"boolean","default":true}},"required":["name","subject","body"]},"SentEmail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"subject":{"type":"string"},"toEmail":{"type":"string"},"toName":{"type":["string","null"]},"cc":{"type":["string","null"]},"bcc":{"type":["string","null"]},"messageId":{"type":["string","null"],"description":"Id del mensaje en el proveedor. Puede venir como `unconfirmed:<id>` cuando el proveedor aceptó el email pero no devolvió su id: en ese caso no es un id del proveedor y no sirve para buscar el mensaje ni el hilo."},"threadId":{"type":["string","null"],"description":"Hilo (Gmail threadId / Outlook conversationId). Pasalo en un envío posterior para responder en el mismo hilo."},"idempotencyKey":{"type":["string","null"]},"source":{"type":"string","enum":["CRM","EXTERNAL"]},"leadId":{"type":["string","null"],"format":"uuid"},"contactId":{"type":["string","null"],"format":"uuid"},"opportunityId":{"type":["string","null"],"format":"uuid"},"sentAt":{"type":"string","format":"date-time"},"openedAt":{"type":["string","null"],"format":"date-time"},"openCount":{"type":"integer"},"emailAccount":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","description":"Casilla desde la que salió."},"provider":{"type":"string","enum":["GOOGLE","MICROSOFT"]}}}}},"EmailSend":{"type":"object","properties":{"to":{"type":"string","description":"Una dirección, o un atajo: `lead` (el email del lead de `leadId`), `contact` (el de `contactId`) u `owner` (la casilla del dueño de la key, para mandarse un preview).","example":"lead"},"toName":{"type":"string","description":"Si se usa un atajo y se omite, sale el nombre del lead/contacto.","maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","description":"HTML del email. Se normaliza al guardar (colores a hexadecimal).","minLength":1,"maxLength":200000},"cc":{"type":"string","description":"Direcciones separadas por coma.","maxLength":500},"bcc":{"type":"string","description":"Direcciones separadas por coma.","maxLength":500},"leadId":{"type":"string","format":"uuid","description":"Vincula el envío al timeline del lead. Debe ser de la organización."},"contactId":{"type":"string","format":"uuid","description":"Vincula el envío al timeline del contacto."},"opportunityId":{"type":"string","format":"uuid","description":"Vincula el envío a la oportunidad."},"emailAccountId":{"type":"string","format":"uuid","description":"Casilla a usar. Si se omite, la primera activa del dueño de la key."},"threadId":{"type":"string","description":"Hilo devuelto por un envío anterior, para responder en él.","maxLength":200},"inReplyTo":{"type":"string","description":"Message-ID RFC 2822 al que se responde.","maxLength":500},"idempotencyKey":{"type":"string","description":"Recomendada. La misma clave dentro de la organización devuelve el envío original con 200 en vez de mandar otra vez. Ej: `outbound-{leadId}-{runId}`.","minLength":1,"maxLength":200}},"required":["to","subject","body"]},"SearchResults":{"type":"object","properties":{"leads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"company":{"type":["string","null"]},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","CONVERTED","LOST"],"description":"`LOST` es el lead descartado."}}}},"contacts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"]},"position":{"type":["string","null"]}}}},"companies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"website":{"type":["string","null"]},"city":{"type":["string","null"]}}}},"opportunities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"value":{"type":"number"},"currency":{"type":"string","enum":["USD","ARS","EUR"]}}}},"activities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["TASK","CALL","MEETING","EMAIL","NOTE"]},"title":{"type":"string"},"dueDate":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}}}}},"description":"Sólo aparecen las claves de los tipos para los que la key tiene scope `:read` (y que se pidieron en `types`)."}},"parameters":{"id":{"name":"id","in":"path","required":true,"description":"UUID del registro.","schema":{"type":"string","format":"uuid"}},"cursor":{"name":"cursor","in":"query","description":"Cursor devuelto en `pagination.cursor` de la página anterior.","schema":{"type":"string"}},"limit":{"name":"limit","in":"query","description":"Cantidad por página (1–100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},"sort":{"name":"sort","in":"query","description":"Campo por el que ordenar.","schema":{"type":"string","default":"createdAt"}},"order":{"name":"order","in":"query","description":"Dirección del orden.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"search":{"name":"search","in":"query","description":"Búsqueda de texto (sin distinguir mayúsculas). Qué campos cubre depende del recurso.","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"Body inválido o falló la validación","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"VALIDATION_ERROR","message":"Invalid input"}}}}}},"Unauthorized":{"description":"API key ausente, inválida, vencida o de una organización inactiva","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"UNAUTHORIZED","message":"Invalid or missing API key"}}}}}},"Forbidden":{"description":"La key no tiene el scope requerido","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"FORBIDDEN","message":"Missing required scope: leads:read"}}}}}},"NotFound":{"description":"El registro no existe en esta organización","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"NOT_FOUND","message":"Lead not found"}}}}}},"DuplicateEmail":{"description":"Ya existe un contacto con ese email","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"DUPLICATE_EMAIL","message":"A contact with this email already exists"}}}}}},"DuplicateName":{"description":"Ya existe un registro con ese nombre","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"DUPLICATE_NAME","message":"A company with this name already exists"}}}}}},"MethodNotAllowed":{"description":"Operación no disponible por API","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"METHOD_NOT_ALLOWED","message":"DELETE is not available via API. Use the CRM UI to delete records."}}}}}},"EnrollmentFailed":{"description":"No se pudo enrolar (secuencia inactiva, sin casilla conectada, etc.)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"ENROLLMENT_FAILED","message":"Sequence is not active"}}}}}},"SequenceOwnedByCampaign":{"description":"La secuencia es la propia de una campaña y se maneja desde la campaña","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"SEQUENCE_OWNED_BY_CAMPAIGN","message":"Sequence belongs to a campaign"}}}}}},"InvalidState":{"description":"El registro no está en un estado que admita la operación","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"INVALID_STATE","message":"Enrollment is COMPLETED, nothing to cancel"}}}}}},"RateLimited":{"description":"Se superó el límite de la key","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded"}}}}}},"NoEmailAccount":{"description":"El dueño de la key no tiene una casilla conectada","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"NO_EMAIL_ACCOUNT","message":"The API key owner has no active email account connected."}}}}}},"SendFailed":{"description":"El proveedor de email rechazó el envío","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"SEND_FAILED","message":"Gmail API error: invalid grant"}}}}}},"ContactOptedOut":{"description":"El contacto se dio de baja de los emails y no se puede promover a lead","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"CONTACT_OPTED_OUT","message":"Contact has opted out of emails and cannot be promoted to a lead"}}}}}},"InProgress":{"description":"Otro request con la misma idempotencyKey está enviando en este momento","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"}],"example":{"error":{"code":"IN_PROGRESS","message":"A send with this idempotencyKey is in progress"}}}}}}}}}