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

# Your first change

> Add a table and two endpoints to the starter backend, deploy them to the Xano Engine, and call them with curl.

The scaffold's `xano/index.ts` registers nothing yet. This page adds a `notes` table, an
endpoint that creates a note and one that lists them, then deploys the result to the Xano Engine
on your machine.

<Steps>
  <Step title="Define the table and endpoints">
    Replace `xano/index.ts` with:

    ```ts theme={null}
    import { workspace, table, apiGroup, query, f, input, inp, ref, s } from "@xano/sdk";

    // `id` (int primary key) and `created_at` are added for you.
    export const notes = table({
      name: "notes",
      schema: {
        body: f.text({ required: true }),
      },
    });

    // Pin the canonical slug so the public path stays /api:notes/... everywhere.
    export const api = apiGroup({ name: "notes", canonical: "notes" });

    export const createNote = query({
      name: "create_note",
      verb: "POST",
      apiGroup: api,
      input: { body: input.text({ required: true }) },
      stack: [s.db.add({ table: notes, row: { body: inp("body") }, as: "note" })],
      response: ref("note"),
    });

    export const listNotes = query({
      name: "notes",
      verb: "GET",
      apiGroup: api,
      stack: [s.db.query({ table: notes, as: "rows" })],
      response: ref("rows"),
    });

    export default workspace("my-app")
      .registerTables([notes])
      .registerApiGroups([api])
      .registerQueries([createNote, listNotes]);
    ```

    Keep the name your scaffold passed to `workspace()` if it differs from `my-app`.

    <Note>
      A pinned `canonical` is the public slug, and it is unique across your Xano instance, not
      only your workspace. On the Engine nothing else holds it. When you later promote to a shared
      instance where another workspace already uses `notes`, the promote refuses with
      `SDK_IDENTITY_CONFLICT`, so pick a slug specific to your project (for example
      `canonical: "my-app-notes"`) before you ship.
    </Note>
  </Step>

  <Step title="Deploy to the Xano Engine">
    <Note>
      **On Windows or an Intel Mac?** There is no Xano Engine build for your machine yet. Wherever this
      page says `npm run xano:deploy`, run `npm run xano:deploy:ephemeral` instead: it deploys the same
      code to an ephemeral in Xano's cloud. That needs a Xano account, so sign in first
      ([Connect to Xano](/start/connect-to-xano)). See
      [where the Engine differs today](/run/xano-engine#where-the-engine-differs-today).
    </Note>

    ```bash theme={null}
    npm run xano:deploy
    ```

    The script regenerates `xano/routes.gen.ts`, type-checks `xano/`, and deploys to the Xano
    Engine with `--keep-data`, so rows you create survive the next redeploy. It prints the
    Engine's URL:

    ```
    → Deploying xano/index.ts → Xano Engine
      on Xano Engine · 127.0.0.1:53358 · workspace 1
    i Wrote xano/xano.lock — commit it.
      It pins this project's object identities and public URLs: renames stay renames, and the
      URLs stay yours. A later deploy honors what it records.
    ✓ Redeployed to xanosdk-4f2a91c03b7e, keeping its data (URL unchanged) (838ms)
      http://127.0.0.1:53358
    ```

    The first build also writes `xano/xano.lock`. Commit it: it pins each object's identity, so a
    later rename renames the object instead of deleting and recreating it.
  </Step>

  <Step title="Call it">
    Use the URL the deploy printed:

    ```bash theme={null}
    curl -s -X POST http://127.0.0.1:53358/api:notes/create_note \
      -H "content-type: application/json" \
      -d '{"body":"hello"}'
    ```

    ```json theme={null}
    {"id":1,"created_at":1791924378059,"body":"hello"}
    ```

    ```bash theme={null}
    curl -s http://127.0.0.1:53358/api:notes/notes
    ```

    ```json theme={null}
    [{"id":1,"created_at":1791924378059,"body":"hello"}]
    ```
  </Step>
</Steps>

## The loop from here

Change a def object, run `npm run xano:deploy` again, and call the endpoint. A type error stops
the script before anything is deployed. `npm run xano:deploy -- --reset` starts the Engine's data
over from your seed rows.

As the backend grows, split it into files the way the scaffold's `xano/EXAMPLE.md` suggests:
`xano/tables/<name>.ts`, `xano/api/<group>.ts`, and one file per endpoint, all registered in
`xano/index.ts`.

## Next

* Add columns, relations and seed rows: [Data and tables](/build/data-and-tables).
* Add path params, auth and middleware: [APIs, functions and middleware](/build/apis-and-middleware).
* Assert the endpoint works: [Tests](/build/tests).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.