> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementar Bookings API a partir de la especificación OpenAPI

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero
  title="Implementar la API de reservas a partir de la especificación OpenAPI"
  description="Entrégale a Devin una especificación YAML y obtén manejadores de rutas de Express completamente implementados, modelos de Prisma, validación con Zod y pruebas de integración con Supertest, todo alineado con los patrones de tu base de código existente."
  prompt="Implementa los siguientes endpoints de la API de reservas usando nuestro stack existente de Express + Prisma. Sigue los patrones en src/api/v2/users/ para la estructura de rutas, manejo de errores y middleware. Deriva los esquemas de Zod a partir de los esquemas de la especificación que se muestran a continuación.

Endpoints:
- GET /api/v2/bookings (listar con paginación: parámetros de consulta page, startDate, endDate)
- POST /api/v2/bookings (crear — 201 en caso de éxito, 409 en caso de conflicto de franja horaria)
- GET /api/v2/bookings/:id
- PATCH /api/v2/bookings/:id (actualización parcial)
- DELETE /api/v2/bookings/:id (borrado lógico)
- POST /api/v2/bookings/:id/confirm (200 en caso de éxito, 422 si ya está cancelada)
- POST /api/v2/bookings/:id/cancel

Esquema CreateBookingInput (obligatorios: title, startTime, endTime, roomId):
- title: string, maxLength 200
- startTime: string, date-time
- endTime: string, date-time
- roomId: string, uuid
- notes: string, maxLength 1000, opcional

Escribe pruebas de integración con Supertest para cada endpoint: cubre casos de éxito, errores de validación, fallos de autenticación y casos límite como solapamiento de franjas horarias. Ejecuta todas las pruebas y verifica que cada endpoint funcione. Si algo falla, depura y corrige; sigue iterando hasta que todas las pruebas pasen. No abras un PR hasta que todo funcione de extremo a extremo."
  category="Desarrollo de funcionalidades"
  features=""
/>

<div className="uc-detail-wrapper">
  <Tip>¿Prefieres no configurarlo manualmente? Pega un enlace a esta página en una sesión de Devin y pídele que lo configure todo por ti.</Tip>

  <Steps>
    <Step title="(Opcional) Analiza los patrones de API existentes">
      Si no estás seguro de cómo está estructurada tu API de Express o en qué patrones basarte, utiliza [Ask Devin](https://app.devin.ai/search?utm_source=docs\&utm_medium=use-case-gallery) para investigarlo primero:

      <PromptBlock agent="ada">
        ```txt Investiga nuestros patrones de API de Express theme={null}
        Muéstrame cómo está estructurada nuestra API de Express:
        1. ¿Cuál es la estructura de carpetas dentro de src/api/v2/?
        2. ¿Cómo interactúan los handlers de rutas, controladores y servicios?
        3. ¿Qué middleware usamos para autenticación y validación?
        4. ¿Cómo se formatean las respuestas de error?
        5. ¿Cómo es nuestra configuración de pruebas (Supertest, configuración de la base de datos de pruebas)?
        ```
      </PromptBlock>

      También puedes usar [DeepWiki](https://deepwiki.com) para explorar APIs de código abierto con patrones similares; por ejemplo, busca ejemplos de Express + Prisma + Zod para ver cómo otros proyectos estructuran sus handlers de rutas y la validación.

      Puedes iniciar una sesión de Devin directamente desde Ask Devin, y mantendrá todo lo que haya aprendido como contexto.
    </Step>

    <Step title="Configura Devin para usar tu especificación OpenAPI">
      Comienza indicando a Devin dónde está la especificación y qué recurso debe implementar. Devin lee cada ruta, esquema y definición de error en el YAML y luego las compara con tus rutas existentes de Express para hacer coincidir las convenciones automáticamente.

      Aquí tienes un extracto del tipo de especificación con la que trabaja Devin: una definición estándar de OpenAPI 3.0 para un recurso de reservas:

      ```yaml theme={null}
      # openapi/bookings-v2.yaml (excerpt)
      openapi: "3.0.3"
      info:
        title: Bookings API
        version: "2.0.0"
      paths:
        /api/v2/bookings:
          get:
            summary: List bookings
            parameters:
              - name: page
                in: query
                schema: { type: integer, default: 1 }
              - name: startDate
                in: query
                schema: { type: string, format: date }
              - name: endDate
                in: query
                schema: { type: string, format: date }
            responses:
              "200":
                description: Paginated list of bookings
                content:
                  application/json:
                    schema:
                      $ref: "#/components/schemas/BookingListResponse"
          post:
            summary: Create a booking
            requestBody:
              required: true
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/CreateBookingInput"
            responses:
              "201":
                description: Booking created
              "409":
                description: Time slot conflict
        /api/v2/bookings/{id}/confirm:
          post:
            summary: Confirm a booking
            responses:
              "200":
                description: Booking confirmed
              "422":
                description: Booking already cancelled
      components:
        schemas:
          CreateBookingInput:
            type: object
            required: [title, startTime, endTime, roomId]
            properties:
              title:
                type: string
                maxLength: 200
              startTime:
                type: string
                format: date-time
              endTime:
                type: string
                format: date-time
              roomId:
                type: string
                format: uuid
      ```

      <PromptBlock>
        ```txt Implementar la API de reservas desde la especificación OpenAPI theme={null}
        Implementa los endpoints definidos en openapi/bookings-v2.yaml para
        /api/v2/bookings. La especificación define:

        - GET /api/v2/bookings (lista con paginación + filtro por rango de fechas)
        - POST /api/v2/bookings (crear)
        - GET /api/v2/bookings/:id
        - PATCH /api/v2/bookings/:id (actualización parcial)
        - DELETE /api/v2/bookings/:id (eliminación lógica)
        - POST /api/v2/bookings/:id/confirm
        - POST /api/v2/bookings/:id/cancel

        Usa nuestro stack existente de Express y Prisma. Sigue los patrones en
        src/api/v2/users/ para la estructura de rutas, el manejo de errores y el middleware.
        Deriva los esquemas de Zod a partir de las definiciones de solicitud/respuesta de OpenAPI.

        ## Testing & verification
        - Write integration tests with Supertest for every endpoint
        - Cover success cases, validation errors, auth failures, and
          business logic edge cases (e.g., overlapping time slots)
        - Run all tests and verify every endpoint works correctly
        - If anything fails — test failures, runtime errors, missing
          middleware — debug and fix it. Keep iterating until all tests pass.
        - Do not open a PR until everything works end-to-end
        ```
      </PromptBlock>

      If your spec isn't checked into the repo yet, paste it directly into the session or attach the YAML/JSON file when starting.
    </Step>

    <Step title="Devin matches your Express patterns">
      The single most impactful thing you can do is reference a well-implemented resource in your codebase. Devin studies that code and replicates the folder structure, naming conventions, middleware chain, and error handling — so the new endpoints look like they were written by the same developer.

      For example, Devin reads `src/api/v2/users/router.ts` and produces a matching bookings router:

      ```typescript theme={null}
      // src/api/v2/bookings/router.ts  (generated by Devin)
      import { Router } from "express";
      import { authenticate } from "@/middleware/auth";
      import { validate } from "@/middleware/validate";
      import { BookingsController } from "./controller";
      import {
        createBookingSchema,
        updateBookingSchema,
        listBookingsQuerySchema,
      } from "./schemas";

      const router = Router();
      const ctrl = new BookingsController();

      router.use(authenticate);

      router.get("/", validate({ query: listBookingsQuerySchema }), ctrl.list);
      router.post("/", validate({ body: createBookingSchema }), ctrl.create);
      router.get("/:id", ctrl.getById);
      router.patch("/:id", validate({ body: updateBookingSchema }), ctrl.update);
      router.delete("/:id", ctrl.softDelete);
      router.post("/:id/confirm", ctrl.confirm);
      router.post("/:id/cancel", ctrl.cancel);

      export default router;
      ```

      Devin también deriva esquemas de Zod directamente a partir de las definiciones de componentes de OpenAPI, de modo que la validación de solicitudes se mantenga sincronizada con la especificación:

      ```typescript theme={null}
      // src/api/v2/bookings/schemas.ts  (generated by Devin)
      import { z } from "zod";

      export const createBookingSchema = z.object({
        title: z.string().max(200),
        startTime: z.string().datetime(),
        endTime: z.string().datetime(),
        roomId: z.string().uuid(),
        notes: z.string().max(1000).optional(),
      });

      export const updateBookingSchema = createBookingSchema.partial();

      export const listBookingsQuerySchema = z.object({
        page: z.coerce.number().int().positive().default(1),
        limit: z.coerce.number().int().min(1).max(100).default(20),
        startDate: z.string().date().optional(),
        endDate: z.string().date().optional(),
      });
      ```

      Asegúrate de que la [Configuración de Environment](/es/onboard-devin/environment) incluya la configuración de la base de datos de pruebas y todas las variables de entorno necesarias para que Devin pueda ejecutar toda la batería de pruebas en local. Si tu API necesita credenciales (URL de base de datos, secreto JWT, etc.), agrégalas como [Secrets](/es/product-guides/secrets) antes de iniciar la sesión, o proporciónaselas durante la sesión a través del chat.
    </Step>

    <Step title="Devin delivers a tested PR">
      Devin lee la especificación, estudia tu código existente e implementa cada endpoint para ajustarse tanto al contrato de OpenAPI como a las convenciones de tu base de código de Express. Así es una PR típica:

      ```
      feat: Implement /api/v2/bookings endpoints from OpenAPI spec

      src/api/v2/bookings/
        router.ts              (Express route definitions + middleware)
        controller.ts          (request handling)
        service.ts             (business logic)
        repository.ts          (Prisma queries)
        schemas.ts             (Zod validation from spec)
      prisma/migrations/
        20260219_add_bookings/  (migration)
      src/__tests__/
        bookings.integration.ts (Supertest tests)
      ```

      Devin runs the Supertest suite before opening the PR:

      ```
        /api/v2/bookings
          GET /
            passes returns paginated bookings (42ms)
            passes filters by date range (38ms)
            passes returns 401 without auth (8ms)
          POST /
            passes creates booking with valid data (61ms)
            passes returns 400 for missing required fields (12ms)
            passes returns 409 for overlapping time slot (29ms)
          PATCH /:id
            passes updates booking fields (22ms)
            passes returns 404 for non-existent booking (9ms)
          POST /:id/confirm
            passes transitions status to confirmed (18ms)
            passes returns 422 for already-cancelled booking (11ms)

        16 passing (412ms)
      ```
    </Step>

    <Step title="Itera sobre lo que la especificación no cubre">
      La especificación OpenAPI define el contrato, pero rara vez captura las reglas de negocio, la lógica de autorización o los requisitos de rendimiento. Utiliza prompts de seguimiento para cubrir los vacíos:

      <PromptBlock>
        ```txt Add authorization rules theme={null}
        Solo el creador de la reserva o un administrador deberían poder realizar operaciones PATCH o DELETE
        sobre una reserva. Los endpoints confirm y cancel también deberían requerir el
        rol de organizador. Usa nuestro middleware existente de comprobación de roles de
        src/middleware/authorize.ts.
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Add rate limiting and caching theme={null}
        Añade rate limiting a POST /api/v2/bookings (20 por minuto por usuario).
        Almacena en caché las respuestas de GET /api/v2/bookings en Redis con un TTL de 30 segundos,
        que se invalide ante cualquier operación de escritura.
        ```
      </PromptBlock>
    </Step>

    <Step title="Revisa el PR con Devin Review">
      Una vez que Devin abre la pull request (PR), usa [Devin Review](https://app.devin.ai/review?utm_source=docs\&utm_medium=use-case-gallery) para revisar la implementación. Devin Review puede detectar problemas como falta de manejo de errores, formatos de respuesta inconsistentes o endpoints que no coinciden con la especificación.

      Si Devin Review señala problemas, puedes usar **Autofix** para que Devin corrija automáticamente los problemas detectados — abre una sesión de seguimiento, aplica las correcciones y envía un commit actualizado sin que tengas que describir manualmente cada cambio.
    </Step>
  </Steps>
</div>
