# Create Vitruvio Endpoint > All messages shown to the user must be written in Portuguese. You are creating a new REST endpoint inside a Vitruvio repository. Follow these steps in order. ## Step 1 — Confirm you are inside a Vitruvio repo ```bash ls vitruvio.json 2>/dev/null && echo "OK" || echo "NOT_A_VITRUVIO_REPO" ``` If `NOT_A_VITRUVIO_REPO`, stop and tell the user to `cd` into the correct repo. ## Step 2 — Collect endpoint details Ask the user (in a single message, only ask what is missing from their original request): - **Key** — kebab-case unique identifier. Forms the URL path. Changing it later breaks external integrations. - **Name** — human-readable label shown in the Vitruvio UI. - **Description** — one sentence about what this endpoint does. - **HTTP verbs** — which methods to implement: GET, POST, PUT, PATCH, DELETE. Only scaffold the ones actually needed. - **Auth mode** — one of: - `PUBLIC` — no authentication (default) - `STATIC_TOKEN` — token in query param `_x_token_auth` or header `X-WS-TOKEN-AUTH` - `VITRUVIO_WS_USER_AUTH` — Vitruvio bearer token; `loggedUser` is available in the script - `HTTP_BASIC_AUTH` — HTTP basic auth; `loggedUser` is available; roles validated by Vitruvio admin ## Step 3 — Create the file Target path: `endpoints/.js` URL after deploy: | authMode | URL | |---|---| | `PUBLIC` | `/api/integration/public/` | | `STATIC_TOKEN` | `/api/integration/tokenauth/` | | `VITRUVIO_WS_USER_AUTH` | `/api/integration/bearerauth/` | | `HTTP_BASIC_AUTH` | `/api/integration/bauth/` | Template (include only the requested verbs): ```javascript /** * Nome: * Sigla: * Descrição: * Auth: */ function WebService() { // this.onGet = function(params) { ... } ← GET / DELETE: params has .headers and .query // this.onPost = function(params) { ... } ← POST / PUT / PATCH: params also has .requestBody (string, always JSON.parse before use) this.onPost = function(params) { try { var body = JSON.parse(params.requestBody); if (!body.id) throw 'Missing required field: id'; // implementation here return JSON.stringify({ success: true }); } catch (e) { return JSON.stringify({ error: e.toString() }); } }; } module.exports = new WebService(); ``` Rules (Rhino ES5 — no exceptions): - No `let`, `const`, arrow functions, template literals, destructuring, spread, `class`, or `import/export` - Use `var` everywhere - Always `JSON.parse(params.requestBody)` before accessing the body — never trust it raw - Always return strings — `JSON.stringify(obj)`, not raw objects - Return `null` or nothing for `204 No Content`; return a string for `200 OK` - Remove unused verb stubs entirely — don't leave placeholder bodies - Never concatenate user input into SQL strings; use named bind params (`:paramName`) - Don't hardcode datasource names or tokens — read from `vConfigService` or a DB config table - Put heavy logic in a separate script loaded via `libService.loadScript`, not inline in the endpoint ## Step 4 — Register in vitruvio.json Read `vitruvio.json`, find or create the `"endpoints"` array, and add: ```json { "key": "", "name": "", "description": "", "language": "javascript", "authMode": "", "active": true, "source": "endpoints/.js" } ``` Preserve the existing file structure and all other entries. Write the updated `vitruvio.json` back. ## Step 5 — Report Tell the user: - File created: `endpoints/.js` - Registered in `vitruvio.json` with key `` - URL once deployed (based on authMode) - Which verbs were scaffolded