Logo StartupKit
ES

API pública de empleos

Construye tu propio sitio de empleo (por ejemplo, con Next.js en Vercel) sobre tu pipeline de contratación de Kit. Lista los puestos publicados y recibe candidaturas a través de una API REST pública, un SDK de TypeScript oficial y una plantilla de Next.js con un clic.

Por qué es importante

El portal de empleo alojado por Kit y el widget integrable cubren la mayoría de las necesidades. Pero si quieres control total sobre el diseño — un sitio de empleo a medida, una landing page propia para cada puesto o una bolsa de trabajo que encaje con tu producto — la Public Jobs API te permite leer tus ofertas publicadas y enviar candidaturas directamente a tu pipeline de Kit, mientras Kit sigue encargándose del cribado, las etapas, las entrevistas y la comunicación con los candidatos.

También hay un SDK de TypeScript oficial y una plantilla de Next.js desplegable con un clic para publicar un sitio de empleo a medida en minutos — o prescinde de ambos y llama directamente a los endpoints REST de abajo con cualquier cliente HTTP.

Claves API

Crea un par de claves en Hiring → Career Portal → Public API Keys. Cada par incluye:

  • Clave publicable (pk_…) — segura para incluir en un navegador. Puede leer ofertas publicadas y enviar candidaturas, nada más, y nunca expone datos de los candidatos. Antes de poder enviar candidaturas, debes configurar al menos una defensa antibots — una lista de orígenes permitidos o tu propio widget de Cloudflare Turnstile —, de lo contrario, las peticiones de candidatura se rechazan con 403 bot_protection_required. La lectura de ofertas funciona sin esa configuración.
  • Clave secreta (sk_…) — solo para uso en el servidor (por ejemplo, una Server Action de Next.js). Se salta las comprobaciones de origen y Turnstile del navegador. Nunca la expongas en código del lado del cliente. Ninguna de las dos claves puede leer datos personales de los candidatos.

La clave secreta se muestra una sola vez, al crearla o rotarla. Puedes rotarla en cualquier momento desde la página de configuración de la clave; la clave secreta anterior deja de funcionar de inmediato.

Autentica cada petición con una cabecera bearer:

Authorization: Bearer sk_your_secret_key

Endpoints

URL base: https://startupkit.app (o tu dominio personalizado de empleo).

Listar ofertas publicadas

GET /api/public/v1/jobs?department=&location=&employment_type=&remote=&page=&per_page=

Devuelve únicamente los puestos publicados de tu cuenta.

{
  "data": [
    {
      "id": "JdK2hQ8…",
      "title": "Senior Rails Developer",
      "department": "Engineering",
      "location": "Remote",
      "employment_type": "full_time",
      "remote": true,
      "published_at": "2026-06-01T12:00:00Z",
      "url": "https://careers.yourco.com/JdK2hQ8…",
      "salary": { "min": 120000, "max": 160000, "currency": "USD", "period": "YEAR" }
    }
  ],
  "pagination": { "current_page": 1, "total_pages": 3, "total_count": 42, "per_page": 20 }
}

El id es el token público de la oferta — úsalo en los endpoints de detalle y de candidatura.

Obtener una oferta con su formulario de candidatura

GET /api/public/v1/jobs/:public_token

Devuelve la oferta junto con un application_form que describe exactamente qué campos y preguntas mostrar, el aviso de consentimiento que hay que mostrar, los tipos y el tamaño de currículum aceptados, y si Turnstile es obligatorio.

{
  "id": "JdK2hQ8…",
  "title": "Senior Rails Developer",
  "description_html": "<p>We're hiring…</p>",
  "accepting_applications": true,
  "stages": [{ "name": "Application Review", "type": "application_form" }],
  "application_form": {
    "fields": [
      { "name": "cover_letter", "type": "textarea", "label": "Cover letter", "required": false }
    ],
    "questions": [
      { "key": "why_us", "type": "text", "prompt": "Why do you want to join?", "required": true, "max_length": 2000 }
    ],
    "consent_disclosure_html": "<p>By applying you agree…</p>",
    "resume": {
      "content_types": ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
      "max_byte_size": 10485760
    },
    "turnstile": { "required": false, "sitekey": null }
  }
}

Subir un currículum (URL prefirmada)

Los currículums se suben directamente al almacenamiento, así que nunca pasan por tu servidor (lo que evita los límites de tamaño del cuerpo en entornos serverless).

POST /api/public/v1/direct_uploads
{ "blob": { "filename": "cv.pdf", "byte_size": 102400, "checksum": "<base64 MD5>", "content_type": "application/pdf" } }
{
  "signed_id": "eyJf…",
  "direct_upload": { "url": "https://…s3…", "headers": { "Content-Type": "application/pdf", "Content-MD5": "" } }
}

Envía los bytes del archivo con PUT a direct_upload.url usando los headers devueltos, y luego pasa el signed_id como resume_signed_id al enviar la candidatura.

Enviar una candidatura

POST /api/public/v1/jobs/:public_token/applications
{
  "application": {
    "email": "[email protected]",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "phone": "+1 555 0100",
    "responses": { "cover_letter": "…", "why_us": "…" },
    "resume_signed_id": "eyJf…"
  },
  "turnstile_token": "<token>"
}

Devuelve 201 con una confirmación mínima, sin datos personales:

{ "id": "app_9fQ…", "status": "submitted", "job": "JdK2hQ8…", "submitted_at": "2026-06-11T09:30:00Z" }

El turnstile_token solo se necesita en envíos desde el navegador (pk_) cuando la clave tiene Turnstile configurado; las llamadas desde el servidor (sk_) se lo saltan.

Errores

Los errores se devuelven en un sobre consistente:

{ "error": { "code": "validation_failed", "message": "Email can't be blank", "fields": { "email": ["can't be blank"] } } }
Estado Código Significado
401 invalid_key Clave API ausente o inválida
403 bot_protection_required La clave publicable (pk_) no tiene configurada ni lista de orígenes permitidos ni Turnstile
403 origin_not_allowed El origen del navegador no está en la lista de permitidos de la clave
404 not_found Oferta no encontrada o no publicada
409 already_applied Este email ya envió una candidatura a esta oferta
422 validation_failed Campos de candidatura inválidos (consulta fields)
422 turnstile_failed Falló la verificación de Turnstile
422 invalid_content_type / file_too_large Subida de currículum rechazada

Actualizaciones de estado vía webhooks

Para hacer seguimiento de las candidaturas después del envío, configura webhooks salientes. Los eventos relevantes incluyen application.submitted, application.advanced y application.rejected, además de job_posting.published/paused/closed. Los payloads de candidatura incluyen tanto el id numérico como el prefix_id de la API (app_…), y el public_token de la oferta, para que puedas correlacionar los eventos de webhook con los registros de la API.

SDK y plantilla de Next.js

Dos puntos de partida oficiales y de código abierto se apoyan en el contrato REST de arriba — usa cualquiera de los dos, o prescinde de ambos y llama a los endpoints directamente con cualquier cliente HTTP.

  • SDK de TypeScript — @startupkit-app/jobs. Un cliente tipado y sin dependencias (fetch nativo, ESM + CJS, Node ≥ 18.17) que corre en Node, navegadores y runtimes edge. Instálalo con npm install @startupkit-app/jobs y luego:

    import { createClient } from "@startupkit-app/jobs";
    
    const kit = createClient({ secretKey: process.env.KIT_SECRET_KEY });
    
    const page = await kit.listJobs({ department: "Engineering", remote: true });
    const job = await kit.getJob(page.data[0].id);
    const { signed_id } = await kit.uploadFile(resumeFile);
    await kit.apply(job.id, { email: "[email protected]", resume_signed_id: signed_id });
    

    En código de navegador, pasa publishableKey (pk_…) en lugar de secretKey. Otros métodos: allJobs() itera de forma asíncrona por todas las páginas, y createUpload() da control de más bajo nivel sobre la subida prefirmada. Las respuestas que no son 2xx lanzan KitApiError (con .code y .fields); los fallos que nunca llegan a la API lanzan KitNetworkError. El cliente usa por defecto la URL base https://app.startupkit.app; pasa baseUrl para sobrescribirla con un dominio de empleo personalizado.

  • Plantilla de Next.js — nextjs-job-board. Un sitio de empleo listo para producción (Next.js App Router, Server Components + Server Actions, ISR con revalidación por etiqueta) que puedes bifurcar o desplegar con un clic. Renderiza el formulario de candidatura dinámicamente a partir del esquema de la API, hace subidas de currículum prefirmadas directas al almacenamiento, emite JSON-LD schema.org JobPosting (listo para Google for Jobs) y, opcionalmente, revalida al instante mediante webhooks. Define una sola variable de entorno — STARTUPKIT_SECRET_KEY (tu clave sk_…) — y despliega:

    Deploy with Vercel

    Demo en vivo: nextjs-job-board-orcin.vercel.app. Variables de entorno opcionales: STARTUPKIT_BASE_URL (por defecto https://app.startupkit.app), NEXT_PUBLIC_TURNSTILE_SITE_KEY, REVALIDATE_SECRET y NEXT_PUBLIC_COMPANY_NAME.

Ambos consumen el contrato de arriba, así que también puedes desarrollar con cualquier framework usando HTTP plano. Un sitio de empleo personalizado típico encadena cuatro llamadas: listar las ofertas, obtener una oferta con su formulario, solicitar una subida prefirmada para el currículum y enviar la candidatura. Como todo es JSON plano sobre HTTPS, la misma integración funciona desde el servidor (clave sk_) o desde el navegador (clave pk_ con una defensa antibots configurada).

Límites de uso

Los envíos de candidaturas están limitados a 10/hora por IP y las peticiones de subida a 30/hora por IP, además de los límites de uso globales de la API. Las claves de navegador están protegidas adicionalmente por su lista de orígenes permitidos y, de forma opcional, por Turnstile.

Escriba para buscar...