Saltar al contenido principal

API Key Externa (/api/ext)

App: Minotaur Sales API
Publicado por: Minotaur Sales
Compatible con: app.minotaursales.io


Documentación de endpoints externos protegidos con API Key.

Autenticación

Todos los endpoints de este documento usan:

Authorization: X-API-Key YOUR_API_KEY
Content-Type: application/json

URL base:

https://api.minotaursales.io/api/ext

Ejemplo:

curl --location 'https://api.minotaursales.io/api/ext/contacts/list' \
--header 'Authorization: X-API-Key YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{}'

Formatos de respuesta comunes

DefaultResponse

Muchos endpoints de create/update/delete responden con:

{
"success": true,
"data": {},
"message": "Operation completed"
}

PaginateResponse<T>

{
"data": [],
"pagination": {
"total_records": 0,
"current_page": 1,
"total_pages": 1
}
}

Cliente (/customer)

GET /customer/summary (customer:read)

Retorna el resumen del cliente asociado al API Key: datos de cuenta, conteo de usuarios y suscripción activa.

Respuesta 200:

{
"customer": {
"id": "7a70f0db-aa4c-43fd-bbf5-f7b0d33c9172",
"business_name": "Acme Inc",
"status": "OK",
"country": null,
"city": null
},
"users_count": 5,
"subscription": {
"id": "3a35dea5-7354-43c8-a3ea-5abec718b2ab",
"status": "active",
"balance": 40000,
"price": "20000",
"periodicity": "month",
"currency": "usd",
"tier": {
"id": "66c609bc-cb1a-4a2b-a34b-212d3acb616b",
"title": "Free Tier",
"tier": 1,
"is_free": true,
"price": "20000"
},
"active_seats": 1
}
}

Contactos (/contacts)

POST /contacts/list (contacts:read)

Request (ejemplo mínimo):

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Respuesta 200 (ContactsResponse[]):

[
{
"id": "7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"first_name": "Ana",
"middle_name": null,
"last_name": "Perez",
"gender": null,
"birth_year": null,
"linkedin_url": null,
"facebook_url": null,
"twitter_url": null,
"work_email": "ana@example.com",
"personal_email": null,
"other_emails": null,
"industry": "Software",
"job_title": "Engineer",
"location_locality": "Bogota",
"location_country": "CO",
"location_region": "Cundinamarca",
"location_postal_code": null,
"phone_numbers": [],
"company": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"company_name": "Acme",
"industry": "Software"
},
"mobile_phone": null,
"score": 87,
"verification_status": "verified",
"last_verified": "2026-04-01T10:30:00.000Z",
"hubspot_synced_at": null,
"custom_fields": {}
}
]

POST /contacts/metadata (contacts:read)

Request:

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Respuesta 200 (ContactMetadataResponse):

{
"pagination": {
"current_page": 1,
"total_records": 1,
"total_pages": 1
}
}

POST /contacts (contacts:create)

Campos requeridos:

  • first_name
  • last_name
  • work_email
  • phone_numbers (puede ser arreglo vacío)

Campos opcionales:

  • assigned_to — UUID del usuario al que se asigna el contacto. Si no se especifica, el contacto queda sin asignar.
  • list_ids — UUIDs de listas existentes donde se agregará el contacto. Solo se agrega a listas si se envían explícitamente; el API Key no crea ni usa "My Contacts" automáticamente. Sin list_ids, el contacto no se agrega a ninguna lista.
  • company — objeto con id (compañía existente) o name (busca o crea por nombre). Ambos campos son opcionales; industry es opcional al crear por nombre.

Request:

{
"first_name": "Ana",
"last_name": "Perez",
"work_email": "ana@example.com",
"phone_numbers": [],
"job_title": "Engineer",
"company": {
"name": "Acme",
"industry": "Software"
},
"list_ids": ["f1e2d3c4-b5a6-7890-abcd-ef1234567890"],
"assigned_to": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd"
}

Respuesta 201 (DefaultResponse):

{
"success": true,
"message": "Contact created successfully"
}

GET /contacts/:id (contacts:read)

Respuesta 200 (ContactsResponse):

{
"id": "7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"first_name": "Ana",
"middle_name": null,
"last_name": "Perez",
"gender": null,
"birth_year": null,
"linkedin_url": null,
"facebook_url": null,
"twitter_url": null,
"work_email": "ana@example.com",
"personal_email": null,
"other_emails": null,
"industry": "Software",
"job_title": "Engineer",
"location_locality": "Bogota",
"location_country": "CO",
"location_region": "Cundinamarca",
"location_postal_code": null,
"phone_numbers": [],
"company": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"company_name": "Acme",
"industry": "Software"
},
"mobile_phone": null,
"score": 87,
"verification_status": "verified",
"last_verified": "2026-04-01T10:30:00.000Z",
"hubspot_synced_at": null,
"custom_fields": {}
}

PATCH /contacts/:id (contacts:update)

Todos los campos son opcionales; solo se actualizan los enviados en el body.

Campos relevantes:

  • assigned_to — UUID del usuario al que se asigna el contacto.
  • list_ids — UUIDs de listas existentes a las que se agregará el contacto.
  • company — objeto con id (compañía existente) o name (busca o crea por nombre).

Request:

{
"job_title": "Senior Engineer",
"phone_numbers": [
{ "country_code": "+57", "number": "3001234567" }
],
"company": {
"name": "Acme",
"industry": "Software"
},
"list_ids": ["f1e2d3c4-b5a6-7890-abcd-ef1234567890"],
"assigned_to": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd"
}

Respuesta 200 (DefaultResponse):

{
"success": true
}

DELETE /contacts/:id (contacts:delete)

Respuesta 200 (DefaultResponse):

{
"success": true,
"data": {},
"message": "Contact deleted"
}

Compañías (/company)

POST /company/list (companies:read)

Request:

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Respuesta 200 (CompaniesResponse[]):

[
{
"id": "30ea8d4e-6b76-4f8f-bcf8-a1cc5af13b4b",
"company_name": "Acme Inc",
"size": "51-200",
"industry": "Software",
"twitter_url": null,
"linkedin_url": "https://linkedin.com/company/acme",
"facebook_url": null,
"location_locality": "Bogota",
"location_metro": null,
"location_region": "Cundinamarca",
"location_street_address": null,
"location_address_line_2": null,
"location_postal_code": null,
"location_country": "CO",
"last_verified": "2026-04-01T10:30:00.000Z",
"verification_status": "verified",
"score": 80,
"custom_fields": {}
}
]

POST /company/metadata (companies:read)

Request:

{
"filters": {},
"paginate": { "page": 1, "limit": 25 }
}

Respuesta 200 (CompanyMetadataResponse):

{
"pagination": {
"current_page": 1,
"total_records": 1,
"total_pages": 1
}
}

POST /company (companies:create)

Campos requeridos: type, company_name.

Request:

{
"type": "COMPANY",
"company_name": "Acme Inc",
"industry": "Software"
}

Respuesta 201 (DefaultResponse)

GET /company/:id (companies:read)

Respuesta 200 (CompaniesResponse | null)

PATCH /company/:id (companies:update)

Respuesta 200 (DefaultResponse)

DELETE /company/:id (companies:delete)

Respuesta 200 (DefaultResponse)


Listas (/list-contact)

POST /list-contact/list (list_contacts:read)

Request (page y limit en la raíz del body):

{
"page": 1,
"limit": 25
}

Respuesta 200 (ListContactResponse[]):

[
{
"id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"name": "Prospects Latam",
"description": "Lista inicial",
"owner_id": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd",
"owner_name": "API Owner",
"source": "manual",
"collaborators": [],
"rules": [
{
"field": "location_country",
"operator": "contains",
"value": "CO",
"logic_operator": "AND"
}
],
"contacts_count": 120,
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}
]

POST /list-contact (list_contacts:create)

Request:

{
"name": "Prospects Latam",
"description": "Lista inicial",
"rules": [
{
"field": "location_country",
"operator": "contains",
"value": "CO"
}
]
}

Respuesta 201 (CreateListContactResponse):

{
"id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"name": "Prospects Latam"
}

PATCH /list-contact/:id (list_contacts:update)

Respuesta 200 (DefaultResponse)

DELETE /list-contact/:id (list_contacts:delete)

Respuesta 200 (DefaultResponse)

POST /list-contact/duplicate (list_contacts:read)

Request:

{
"list_id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"new_name": "Prospects Latam Copia"
}

Respuesta 200 (DefaultResponse)

POST /list-contact/verify-contacts/:id (list_contacts:read)

Sin body. Inicia el proceso de verificación de los contactos de la lista.

Respuesta 200 (DefaultResponse)


Detalles de Lista (/list-contact-details)

POST /list-contact-details/add-contacts (list_contact_details:update)

Agrega uno o más contactos existentes a una lista.

Request:

{
"list_id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"contact_ids": [
"7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"a96f2d7f-743f-4747-9198-7ca35ccab774"
]
}

Respuesta 200 (DefaultResponse):

{
"success": true,
"message": "Contacts added successfully"
}

Productos (/products)

POST /products/list (products:read)

Request:

{
"paginate": { "page": 1, "limit": 25 }
}

Respuesta 201 (ProductListItemResponse[]):

[
{
"id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c",
"name": "Plan Básico",
"currency": "USD",
"price": 99.99,
"unit": "month",
"active": true,
"opportunities_count": 3,
"pipelines_count": 1,
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}
]

POST /products (products:create)

Campos requeridos: name, price, unit.

Request:

{
"name": "Plan Básico",
"price": 99.99,
"unit": "month",
"currency": "USD"
}

Respuesta 201 (DefaultResponse)

GET /products/:id (products:read)

Respuesta 200 (ProductResponse)

PATCH /products/:id (products:update)

Respuesta 200 (DefaultResponse)

DELETE /products/:id (products:delete)

Respuesta 200 (DefaultResponse)


Oportunidades (/opportunities)

POST /opportunities/list (opportunities:read)

Request:

{
"paginate": { "page": 1, "limit": 25 }
}

Respuesta 201 (OpportunityResponse[]):

[
{
"id": "e2d4f6a8-1b3c-5d7e-9f0a-2b4c6d8e0f1a",
"name": "Deal con Acme",
"description": "Oportunidad inicial",
"price": 500.00,
"priority": "HIGHT",
"stage_id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"contacts_ids": ["7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c"],
"company_id": "30ea8d4e-6b76-4f8f-bcf8-a1cc5af13b4b",
"user_id_assigned": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd",
"estimated_closing_date": "2026-07-01T00:00:00.000Z",
"close_date": "2026-07-15T00:00:00.000Z",
"details": []
}
]

POST /opportunities (opportunities:create)

Campos requeridos: name, contacts_ids, stage_id, user_id_assigned, products, estimated_closing_date, close_date, priority (URGENT | HIGHT | MEDIUM | LOW | NONE).

Campos opcionales: description, company_id, source_id.

Request:

{
"name": "Deal con Acme",
"description": "Oportunidad inicial",
"contacts_ids": ["7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c"],
"company_id": "30ea8d4e-6b76-4f8f-bcf8-a1cc5af13b4b",
"stage_id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"user_id_assigned": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd",
"estimated_closing_date": "2026-07-01T00:00:00.000Z",
"close_date": "2026-07-15T00:00:00.000Z",
"priority": "HIGHT",
"products": [
{
"id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c",
"price": 99.99,
"quantity": 2
}
]
}

Respuesta 201 (DefaultResponse)

GET /opportunities/:id (opportunities:read)

Respuesta 200 (OpportunityResponse)

PATCH /opportunities/:id (opportunities:update)

Para actualizar productos usar la estructura products.add, products.remove, products.update.

Respuesta 200 (DefaultResponse)

DELETE /opportunities/:id (opportunities:delete)

Respuesta 200 (DefaultResponse)


Pipelines (/pipelines)

GET /pipelines (pipelines:read)

Retorna todos los pipelines del cliente.

Respuesta 200 (PipelineExternalItem[]):

[
{
"id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"name": "Pipeline de Ventas",
"description": "Pipeline principal",
"currency": "USD",
"active": true
}
]

GET /pipelines/:id (pipelines:read)

Retorna el pipeline con sus etapas.

Respuesta 200 (PipelineResponse):

{
"id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"name": "Pipeline de Ventas",
"description": "Pipeline principal",
"currency": "USD",
"active": true,
"visibility": "PUBLIC",
"stages": [
{
"id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"name": "Prospecto",
"order": 1,
"pipeline_id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"probability_percentage": 10,
"status": "OPEN"
}
],
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}

Etapas (/stages)

POST /stages/list (stages:read)

Retorna las etapas de un pipeline.

Campo requerido: pipeline_id.

Request:

{
"pipeline_id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"paginate": { "page": 1, "limit": 25 }
}

Respuesta 201 (StageResponse[]):

[
{
"id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"name": "Prospecto",
"order": 1,
"pipeline_id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"probability_percentage": 10,
"status": "OPEN",
"total_opportunities": 5
}
]

Prospectos (/prospect)

Requiere conectividad con el cluster de Elasticsearch.

POST /prospect/filters (prospect:read)

Retorna valores sugeridos para autocompletar filtros.

Request:

{
"source": "job_title",
"search": "engineer"
}

Respuesta 201:

[
{
"type": "job_title",
"value": "Software Engineer"
}
]

POST /prospect/metadata (prospect:read)

paginate.limit acepta solo: 10, 25, 50, 100.

Request:

{
"filters": {},
"paginate": { "page": 1, "limit": 25 },
"all_contacts": false
}

Respuesta 201 (MetadataContactFilterResponse):

{
"pagination": {
"current_page": 1,
"total_records": 1200,
"total_pages": 48
},
"filters_applied": {
"first_name": [],
"last_name": [],
"job_title": [],
"job_company_name": [],
"job_company_industry": [],
"location_locality": [],
"location_region": [],
"location_country": [],
"location_postal_code": [],
"date_verified": { "gte": null, "lte": null }
}
}

POST /prospect/list (prospect:read)

paginate.limit acepta solo: 10, 25, 50, 100.

Request:

{
"filters": {},
"paginate": { "page": 1, "limit": 25 },
"all_contacts": false
}

Respuesta 201 (ProspectContactResponse[])


Service Handler (/service-handler)

POST /service-handler/unlock-contacts (payment_prospect:create)

Desbloquea contactos del catálogo de prospectos según filtros. Consume créditos de la suscripción.

Request:

{
"filters": {},
"order_by": { "score": "DESC" },
"total_records": 100,
"sync_hubspot": false
}

Respuesta 200:

{
"id": "7ec0d9c6-cab6-46cf-8d5a-b5f22f17f6da",
"status": "PENDING"
}

POST /service-handler/unlock-selected-contacts (payment_prospect:create)

Desbloquea contactos específicos por ID. Consume créditos de la suscripción.

Request:

{
"ids": [
"7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"a96f2d7f-743f-4747-9198-7ca35ccab774"
],
"sync_hubspot": false
}

Respuesta 200:

{
"id": "dc7248f7-bc52-4710-b854-a8caac8ca5a6",
"status": "PENDING"
}

POST /service-handler/verify-email (verify_email:create)

Inicia la verificación de emails para una lista de contactos. Consume créditos de verificación.

Request:

{
"emails": [
{
"email": "ana@example.com",
"contact_id": "7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c"
}
],
"sync_hubspot": false
}

Respuesta 200:

{
"id": "f2c4f038-63fc-4f78-a86d-88f26a7398d8",
"status": "PENDING"
}

Errores frecuentes

401 Unauthorized

Cuando falta o es inválido el header Authorization:

{
"statusCode": 401,
"message": "The provided API key is invalid or unauthorized."
}

400 Bad Request

Cuando el body no cumple validaciones (campos requeridos, UUID inválido, tipos incorrectos, limit fuera de rango).

403 Forbidden

Cuando el API Key no tiene el permiso requerido para el endpoint:

{
"statusCode": 403,
"message": "User does not have permission"
}