# HTTP triggers and routing

> HTTP trigger behavior for JavaScript functions, covering input sources, path parameters, authentication scopes, payload limits, and calling a deployed trigger.

A JavaScript function that declares a `method` and a `path` is exposed as an HTTP endpoint. This is what makes a function usable as the backend of a [Coded App](https://docs.uipath.com/apps/automation-cloud/latest/user-guide): the app calls the endpoint, and the function holds the credentials and business rules that must never reach the browser.

```typescript
export default defineFunction({
  name: "get-order",
  method: "GET",
  path: "/orders/:id",
  input: defineSchema<{ id: string }>(),
  handler: async (input, ctx) => fetchOrder(input.id),
});
```

The supported methods are:

- `GET`
- `POST`
- `PUT`
- `PATCH`
- `DELETE`

## Where the input comes from

| Method | Request data read as input |
|---|---|
| `GET` | The query string |
| `POST`, `PUT`, `PATCH`, `DELETE` | The JSON request body |

Path parameters are merged in as well, so `/orders/:id` supplies `id` alongside the rest of the input. Every path parameter must be declared in the input type: the derived schema is closed, so an undeclared one is rejected as an unknown property.

Path parameters merge underneath the body, so a body field of the same name wins. Distinct names avoid a silent override.

## Path parameters

| Pattern | Matches |
|---|---|
| `:param` | Exactly one segment — `/users/:id` matches `/users/42` |
| `:param{regex}` | One segment, constrained — `/users/:id{[0-9]+}` |
| `:param?` | The segment, or nothing — `/list/:filter?` matches `/list` and `/list/open` |
| `*` | A trailing catch-all, including the bare prefix |

Values are also available as strings on `ctx.params`, keyed by name. More specific routes win regardless of declaration order, so a literal `/users/me` takes precedence over `/users/:id`. Routing behaves identically in a local `serve` and when deployed.

## Calling a deployed trigger

Once the function is published and deployed, its `path` becomes the slug of an Orchestrator HTTP trigger, and the trigger resolves incoming requests by route matching. The caller sends a bearer token; the platform passes the caller's identity to the function as [`ctx.user`](javascript-function-context.md).

A deployed trigger is registered under a **package-prefixed name**: a function called `get-order` in the package `orders-functions` registers as `orders-functions_get-order`. Resolving the function by name requires that prefixed form.

From a Coded App, use the `Functions` service in the [UiPath TypeScript SDK](https://uipath.github.io/uipath-typescript/) rather than building the URL by hand.

:::note
When a function is invoked through the SDK's `Functions.invoke()`, path parameters are not substituted into the URL — the declared slug is sent as written and the values travel as query parameters or in the body. The handler still receives the right input, but `ctx.params` holds the literal pattern, and a regex-constrained parameter will not match. A resolved path requires building the URL in the caller.
:::

## Authentication

Callers authenticate with a bearer token from an External Application. Which scopes that token needs depends on where the caller runs.

A **deployed Coded App** requests the scopes registered on its External Application — the platform injects them into the app at deployment. Register the app with the Orchestrator scopes the function's callers need, for example:

```bash
uip admin external-apps create "My App" \
  --non-confidential \
  --redirect-uri "https://<org>.uipath.host/my-app" \
  --user-scope "OR.Execution,OR.Folders"
```

`OR.Jobs` is also required if the app starts jobs or reads their results.

When you run the same app **locally**, its scope string comes from `uipath.json` instead, and there you can also request `OR.Default` — the scope that makes Orchestrator apply the caller's folder and tenant role assignments:

```
openid profile email offline_access OR.Default OR.Execution OR.Folders
```

:::note
`OR.Default` cannot be added to an External Application registration; the API rejects it as an unknown scope. It is therefore available to a locally run app through `uipath.json`, but not to a deployed Coded App.
:::

## Payload limits

An HTTP trigger passes the request through as job arguments, so the request and the response are both bounded.

| Direction | Limit | Past the limit |
|---|---|---|
| Request | 10,000 characters of serialized input | `500`, with `errorCode 4801` and the message `JobArguments length should be less than 10000 characters` |
| Response | Approximately 512 KB | `200` with an **empty body**, and no error |

The empty response is the one to design against: the status says success and nothing reports the loss. When a payload can exceed either limit, invoke the function as a job instead — a job carries large input and output as attachments. See [Invoking functions](invoking-functions.md).

:::tip
Returning a reference rather than the data itself — a storage bucket path, or an identifier the caller fetches separately — keeps the limits from constraining the design.
:::

## Next steps

- [Function context](javascript-function-context.md) — read the caller's identity and the request.
- [Accessing platform services](javascript-platform-services.md) — reach Orchestrator from the handler.
- [Routing reference](https://uipath.github.io/uipath-typescript/js-functions/platform-context/) — the full matching rules.
