# Endpoints An endpoint runs when your app or the CLI calls it. `integrations/atlas-demo/endpoints/cancel-booking.ts`: ```ts import { createEndpoint } from "@browserlayer/sdk"; import { z } from "zod"; import bookingReference from "../connector/references/booking.js"; import cancelBooking from "../connector/flows/cancel-booking.js"; export default createEndpoint({ description: "Cancel a booking after the account holder verifies the request.", connection: "required", input: z.object({ bookingId: bookingReference.id }), output: z.object({ bookingId: bookingReference.id, cancelled: z.literal(true), }), async exec(ctx, { bookingId }) { const reference = await ctx.references.resolve(bookingReference, bookingId); await ctx.run(cancelBooking, reference); return { bookingId, cancelled: true as const }; }, }); ``` The complete connector is included in the [Atlas walkthrough](/docs/atlas). This endpoint exposes its contract and delegates website work to it. ## Run locally ```sh browserlayer run atlas-demo cancel-booking --local \ --connection --input '{"bookingId":""}' --wait ``` Use a booking ID returned by your sync. If verification is requested, complete it in Link and inspect the same run afterward. | Option | Meaning | | ----------------------------------- | ----------------------------------------------------------- | | `connection: "required"` | Require a connection; run reauthentication first if defined | | `connection: "optional"` or omitted | No automatic authentication prerequisite | | `input` / `output` | Required Zod schemas | | `description` | Required description shown with the contract | You can implement a small endpoint directly. Extract an internal flow when it owns reusable or substantial website orchestration; one wrapper per helper is not required. **Next:** [Call from your app](/docs/call-endpoint).