# Routes

URL: https://zerodev.ca/docs/prism/developer-documentation/routes

> API endpoints for your module, with permissions, rate limits and signed responses.



A route is an endpoint on the API port. Put each one in its own folder under `src/routes/` as `route.js`.

```js title="modules/example/src/routes/items/route.js"
import { Routes } from "#prism/modules";

export class ItemsRoute extends Routes {
    constructor(prism) {
        super(prism, {
            name: "items",
            path: "/items",
            permissions: { GET: "example.view", POST: "example.edit" }
        });
    }

    async GET(request) {
        const items = this.prism.modules.models.get(this.module, "example_items");
        return items.page(items.query(request.query));
    }

    async POST(request) {
        const created = await this.prism.modules.handlers.get(this.module, "items").create(request.body.identifier, request.body.name);
        await this.audit(request, "items.create", created.id);
        return created;
    }
}
```

This answers `GET` and `POST` on `/api/modules/example/items`.

Add a method for each HTTP verb you need: `GET`, `POST`, `PUT`, `PATCH` or `DELETE`. Whatever it returns is sent as JSON. Returning nothing sends `204`. A thrown error with a `status`, such as from `fail()`, is sent as that status with `{ error }`.

## Options

| Key           | Default   | What it does                                                                                         |
| ------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| `name`        | Required  | The route name.                                                                                      |
| `path`        | Required  | The path. Supports Express parameters such as `/items/:id`.                                          |
| `absolute`    | `false`   | Mount `path` as is instead of under `/api/modules/<module>`. Use it for public `/api/v1/` endpoints. |
| `aliases`     | `[]`      | Extra full paths for the same route, such as an `/api/v1/` path for API tokens.                      |
| `access`      | `private` | `public` lets anyone call it. `private` needs a signed-in session or an API token.                   |
| `permissions` | `{}`      | One permission for every method, or one per method.                                                  |
| `limit`       | None      | Rate limit per IP, such as `{ window: 60, max: 30 }` for 30 a minute.                                |
| `raw`         | `false`   | Keep the raw body on `request.rawBody`, for webhooks that check a signature.                         |

When the module is turned off, its routes answer `404`. Routes with fewer `:params` are mounted first, so `/items/key` wins over `/items/:id`.

## Public Endpoints

Endpoints that products, the store or an SDK read are public, versioned and signed:

```js
export class CatalogRoute extends Routes {
    constructor(prism) {
        super(prism, { name: "catalog", path: "/api/v1/example/items", absolute: true, access: "public", limit: { window: 60, max: 120 } });
    }

    async GET(request, response) {
        const items = this.prism.modules.models.get(this.module, "example_items");
        this.signed(response, this.listing(request, "items", await items.page(items.query(request.query))));
    }
}
```

The site on the web port forwards every `/api/v1/` request to the API, so these work on the store's own address.

## Helpers

| Helper                                        | What it does                                                                           |
| --------------------------------------------- | -------------------------------------------------------------------------------------- |
| `this.can(request, permission)`               | Whether the caller has the permission.                                                 |
| `this.require(request, permission)`           | Throws `403` if they do not.                                                           |
| `this.actor(request)`                         | Who is calling. See [Actors](/docs/prism/developer-documentation/internal-api#actors). |
| `this.ip(request)`                            | The caller's IP, behind proxies too.                                                   |
| `this.audit(request, action, target, detail)` | Adds an entry to the audit log.                                                        |
| `this.signed(response, data, status)`         | Sends `data` with an `x-prism-signature` header.                                       |
| `this.listing(request, name, page)`           | Wraps a `page()` result as `{ success, total, [name] }` on `/api/v1/` paths.           |
| `this.versioned(request)`                     | Whether the request came in on an `/api/v1/` path.                                     |

## Signed Responses

```js
async GET(request, response) {
    this.signed(response, { success: true, item });
}
```

`signed` sends the response itself, so return nothing after it. Clients check the header against `GET /api/v1/public-key`. See [Signed Responses](/docs/prism/api#signed-responses).
