Referencia de la API
Autentícate y consulta la API de Hiring para ofertas de empleo, candidatos y candidaturas.
Por qué es importante
La API de Hiring da a los sistemas externos acceso de lectura a tus datos de contratación: los portales de empleo obtienen las ofertas publicadas, los sistemas HRIS sincronizan los registros de candidatos, los dashboards rastrean las métricas del pipeline. Los scopes de los tokens garantizan que cada integración solo vea lo que necesita.
URL base
Todos los endpoints de la API son accesibles a través de:
https://startupkit.app/api/v1
Reemplaza startupkit.app con tu dominio real de Kit.
Autenticación
Cada solicitud requiere un token de API en el encabezado Authorization:
Authorization: Bearer YOUR_TOKEN
Formato alternativo (ambos funcionan):
Authorization: token YOUR_TOKEN
Crea tokens en Settings > API. Cada token debe tener scopes explícitos para acceder a los endpoints de contratación.
| Scope | Acceso |
|---|---|
job_postings:read |
Ofertas de empleo y etapas |
candidates:read |
Datos personales del candidato (nombre, email, teléfono), descarga de CV |
applications:read |
Candidaturas, historial de etapas, descarga de CV |
Los tokens sin ningún scope no pueden acceder a los endpoints de contratación.
Formato y ciclo de vida del token
- Formato: Cadena hexadecimal de 32 caracteres (p. ej.,
a1b2c3d4e5f6...) - Rastreo de último uso: Cada solicitud exitosa actualiza
last_used_at - Expiración: Se puede definir un
expires_atopcional al crear el token - Alertas de inactividad: Los tokens sin usar durante más de 30 días activan notificaciones de administrador
- Revocación automática: Los tokens se revocan automáticamente cuando un usuario es eliminado de la cuenta
Buena práctica: Crea tokens separados por integración con los scopes mínimos necesarios.
Alcance por cuenta
Cada token de API está vinculado a una cuenta específica. La cuenta se determina automáticamente a partir del token; no se necesita ningún parámetro account_id.
Cuando un miembro del equipo es eliminado de una cuenta, sus tokens para esa cuenta se revocan automáticamente.
Respuestas de error
| Estado | Significado | Causas comunes |
|---|---|---|
400 |
Solicitud incorrecta | Contexto de cuenta ausente (caso límite en autenticación por sesión) |
401 |
No autorizado | Token ausente, inválido o expirado |
403 |
Prohibido | El token no tiene el scope requerido para este endpoint |
404 |
No encontrado | El recurso no existe o no pertenece a tu cuenta |
422 |
Entidad no procesable | Errores de validación (principalmente para endpoints fuera de contratación) |
Paginación
Los endpoints de lista devuelven resultados paginados:
{
"data": [...],
"pagination": {
"current_page": 1,
"total_pages": 3,
"total_count": 42,
"per_page": 20
}
}
Pasa ?page=2 para obtener las páginas siguientes.
Ofertas de empleo
Scope requerido: job_postings:read
Listar ofertas de empleo
GET /api/v1/job_postings
Ejemplo:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://startupkit.app/api/v1/job_postings?status=published
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
status |
string | Filtrar por draft, published o closed |
page |
integer | Número de página |
Respuesta:
{
"data": [
{
"id": "job_abc123",
"title": "Senior Rails Developer",
"status": "published",
"department": "Engineering",
"location": "New York, NY",
"employment_type": "full_time",
"remote": true,
"salary_min": "120000.0",
"salary_max": "180000.0",
"salary_currency": "USD",
"salary_period": "year",
"published_at": "2026-01-15T10:00:00Z",
"closed_at": null,
"created_at": "2026-01-10T08:30:00Z",
"updated_at": "2026-02-01T14:20:00Z",
"stages": [
{
"id": "stg_def456",
"name": "Screening",
"stage_type": "default",
"position": 0
}
],
"counts": {
"total_applications": 24,
"active_applications": 18,
"rejected": 6
}
}
],
"pagination": { ... }
}
Obtener una oferta de empleo
GET /api/v1/job_postings/:id
Devuelve la misma estructura que un elemento de la respuesta de lista.
Listar etapas
GET /api/v1/job_postings/:job_posting_id/stages
Respuesta:
{
"data": [
{
"id": "stg_def456",
"name": "Screening",
"stage_type": "default",
"position": 0
}
]
}
Las etapas están ordenadas por posición. Sin paginación.
Candidatos
Scope requerido: candidates:read
Listar candidatos
GET /api/v1/candidates
Ejemplo:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://startupkit.app/api/v1/[email protected]
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
search |
string | Buscar por nombre o email |
page |
integer | Número de página |
Respuesta:
{
"data": [
{
"id": "cand_ghi789",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+1-555-0100",
"status": "active",
"github_username": "johndoe",
"created_at": "2026-01-20T09:15:00Z",
"applications": [
{
"id": "app_jkl012",
"job_posting_id": "job_abc123",
"job_posting_title": "Senior Rails Developer",
"current_stage_name": "Interview",
"status": "active",
"submitted_at": "2026-01-20T09:15:00Z"
}
]
}
],
"pagination": { ... }
}
Obtener un candidato
GET /api/v1/candidates/:id
Devuelve la misma estructura que un elemento de la respuesta de lista.
Candidaturas
Scope requerido: applications:read
Listar candidaturas
GET /api/v1/applications
Ejemplo:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://startupkit.app/api/v1/applications?job_posting_id=job_abc123&status=active
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
job_posting_id |
string | Filtrar por ID con prefijo de la oferta de empleo |
status |
string | Filtrar por active o rejected |
page |
integer | Número de página |
Respuesta:
{
"data": [
{
"id": "app_jkl012",
"job_posting_id": "job_abc123",
"candidate_id": "cand_ghi789",
"current_stage_name": "Interview",
"status": "active",
"submitted_at": "2026-01-20T09:15:00Z",
"created_at": "2026-01-20T09:15:00Z",
"updated_at": "2026-02-10T11:30:00Z",
"candidate": {
"id": "cand_ghi789",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]"
},
"stage_history": [
{
"id": "sp_mno345",
"stage_name": "Screening",
"stage_type": "default",
"status": "completed",
"started_at": "2026-01-20T09:15:00Z",
"completed_at": "2026-01-25T16:00:00Z"
},
{
"id": "sp_pqr678",
"stage_name": "Interview",
"stage_type": "interview",
"status": "in_progress",
"started_at": "2026-01-25T16:00:00Z",
"completed_at": null
}
]
}
],
"pagination": { ... }
}
Obtener una candidatura
GET /api/v1/applications/:id
Devuelve la misma estructura que un elemento de la respuesta de lista. Cuando el token tiene el scope candidates:read y la candidatura tiene un CV adjunto, la respuesta incluye metadatos del CV:
{
"id": "app_jkl012",
"resume_filename": "john_doe_resume.pdf",
"resume_content_type": "application/pdf",
"resume_byte_size": 245760,
...
}
Estos campos se omiten cuando no hay CV adjunto o cuando falta el scope candidates:read.
Descargar CV
Scopes requeridos: applications:read + candidates:read
GET /api/v1/applications/:application_id/resume
Descarga el CV del candidato para la candidatura indicada. Devuelve una redirección 302 a una URL firmada con tiempo limitado (válida durante 30 minutos).
Ejemplo:
curl -L -H "Authorization: Bearer YOUR_TOKEN" \
-o resume.pdf \
https://startupkit.app/api/v1/applications/app_jkl012/resume
Respuesta:
302 Found– Redirección a la URL de descarga firmada. Usa-L(seguir redirecciones) con curl.403 Forbidden– El token no tiene el scopeapplications:readocandidates:read.404 Not Found– Candidatura no encontrada, o sin CV adjunto.
Notas:
- Las URL firmadas expiran a los 30 minutos. Si expira, solicita una nueva.
- El encabezado
Content-Dispositionestá configurado comoattachment(inicia la descarga en el navegador). - Tipos de archivo de CV: PDF, DOC, DOCX (según lo subido por el candidato).
Ocultamiento de datos personales del candidato
Cuando un token tiene applications:read pero no candidates:read, los datos del candidato en las respuestas de candidaturas se ocultan y solo muestran el ID:
{
"candidate": {
"id": "cand_ghi789"
}
}
Los campos first_name, last_name y email no se incluyen. Esto permite que las integraciones de portales de empleo rastreen el estado de las candidaturas sin exponer la información de contacto de los candidatos.
Diagnóstico de problemas
Problemas de autenticación
401 Unauthorized
Si recibes una respuesta 401, verifica:
- Formato del token: Asegúrate de que el token sea exactamente el que se muestra en Settings > API (cadena hexadecimal de 32 caracteres)
- Encabezado Authorization: Debe ser
Authorization: Bearer TOKENoAuthorization: token TOKEN - Expiración del token: Comprueba si
expires_atha pasado en Settings > API - Membresía en la cuenta: Confirma que el propietario del token sigue siendo miembro de la cuenta
403 Forbidden
Cuando recibes un 403, el token es válido pero no tiene el scope requerido:
- Verifica los scopes requeridos: Cada endpoint documenta su scope requerido (p. ej.,
job_postings:read) - Añade los scopes faltantes: Edita el token en Settings > API y añade el scope necesario
- Formato del scope: Debe coincidir exactamente:
job_postings:read, nojob_postingsniread
Problemas de acceso a datos
Array data vacío en las respuestas
Si la API devuelve {"data": [], "pagination": {...}} pero esperas resultados:
- Aislamiento por cuenta: Los tokens de API solo ven datos de la cuenta a la que están vinculados
- Verifica la cuenta: Comprueba a qué cuenta pertenece el token en Settings > API
- Acceso entre cuentas: Los tokens no pueden acceder a datos de otras cuentas, incluso si el usuario es miembro de ellas
Los datos personales del candidato están ocultos
Si solo ves {"candidate": {"id": "cand_..."}} sin nombre ni email:
- Comportamiento esperado: Esto ocurre cuando el token tiene
applications:readpero nocandidates:read - Añade el scope: Para ver los detalles completos del candidato, añade el scope
candidates:reada tu token - Privacidad por diseño: Esto permite que las integraciones rastreen candidaturas sin exponer información de contacto
Problemas de consultas y filtros
404 al buscar recursos específicos
- Usa IDs con prefijo: Las ofertas de empleo usan el formato
job_abc123, no IDs de base de datos como42 - Sensibilidad a mayúsculas: Los IDs con prefijo distinguen entre mayúsculas y minúsculas
- Alcance de la cuenta: El recurso debe pertenecer a la cuenta del token
Los parámetros de filtro no funcionan
- Valores de estado válidos:
- Ofertas de empleo:
draft,published,closed(distingue mayúsculas) - Candidaturas:
active,rejected(distingue mayúsculas)
- Ofertas de empleo:
- Formato de parámetros: Usa
?status=published, no?status=Publishedni?filter[status]=published
Preguntas frecuentes
¿Cómo funciona la paginación?
Todos los endpoints de lista devuelven 20 elementos por página (fijo). Usa ?page=2 para la siguiente página. El objeto pagination muestra total_pages y total_count.
¿Los tokens expiran automáticamente?
Solo si defines expires_at al crear el token. De lo contrario, los tokens permanecen válidos hasta que:
- Se revoquen manualmente en Settings > API
- El usuario sea eliminado de la cuenta
- La cuenta sea eliminada
¿Debo usar un solo token para múltiples integraciones?
No. La buena práctica es un token por integración con los scopes mínimos. Esto facilita:
- Auditar qué integración está haciendo solicitudes (a través de
last_used_at) - Revocar el acceso a una integración específica sin afectar a las demás
- Otorgar permisos diferentes a distintos sistemas
¿Cuál es la relación entre los webhooks y la API?
Los webhooks te notifican de eventos (nueva candidatura, cambio de etapa). La API te permite consultar el estado actual. Usa los webhooks para activar tu sistema y luego usa la API para obtener los detalles completos.
¿Puedo obtener más de 20 elementos por página?
No. El tamaño de página está fijado en 20 elementos para garantizar un rendimiento consistente. Usa el parámetro page para iterar sobre todos los resultados.
Lista de verificación rápida
- Crea un token de API en Settings > API – cada token está vinculado a esa cuenta
- Asigna solo los scopes que tu integración necesita (buena práctica: un token por integración con los scopes mínimos)
- Comprueba
expires_aten Settings > API para ver cuándo expira el token (si se definió) - Incluye
Authorization: Bearer TOKENen cada solicitud - Usa IDs con prefijo (p. ej.,
job_abc123) en las URLs, no IDs de base de datos - Maneja las respuestas
400y422para errores de validación - Maneja las respuestas
401– tu token puede haber expirado o sido revocado - Maneja las respuestas
403– a tu token puede faltarle un scope requerido - Usa el parámetro
pagepara paginar grandes conjuntos de resultados (20 elementos por página)