Deployment¶
From defineFunction to a live HTTP trigger — what happens at each stage and what you need to do.
The pipeline¶
defineFunction() calls in .ts files
│
▼
uip functions pack
│
├─ generates entry-points.json (one entry per function)
├─ generates bindings_v2.json (one HttpTrigger per function)
└─ produces .uipath/<name>.<ver>.nupkg
│
▼
uip functions publish
│
▼
Orchestrator reads the .nupkg
→ creates / updates one API Trigger per function
Pack¶
uip functions pack reads each function file's default-exported defineFunction and generates two manifest files before zipping everything into a .nupkg.
What pack generates¶
entry-points.json¶
One entry per function. The uniqueId is stable across re-packs — preserved from the previous file if one exists. Re-packing does not create duplicate triggers; Orchestrator updates existing ones in place.
{
"$schema": "https://cloud.uipath.com/draft/2024-12/entry-point",
"$id": "entry-points.json",
"entryPoints": [
{
"filePath": "content/functions/hello.ts",
"uniqueId": "a1b2c3d4-…",
"type": "function",
"input": { "type": "object", "properties": { "name": { "type": "string" } } },
"output": { "type": "object", "properties": { "message": { "type": "string" } } }
}
]
}
bindings_v2.json¶
One HttpTrigger resource per function. Non-HttpTrigger resources (Storage, Queue, etc.) and non-function entries are preserved verbatim and never overwritten.
{
"$schema": "https://cloud.uipath.com/draft/2024-12/bindings",
"version": "2.0",
"resources": [
{
"resource": "HttpTrigger",
"key": "stable-uuid-…",
"id": "stable-uuid-…",
"value": {
"EntryPointUniqueId": {
"DefaultValue": "a1b2c3d4-…",
"IsExpression": false
}
},
"metadata": {
"BindingsVersion": "2.1",
"Name": "hello",
"Method": "POST",
"Slug": "/hello",
"CallingMode": "LongPolling",
"Description": "Returns a greeting message."
}
}
]
}
defineFunction → API Trigger field mapping¶
Each function file's default-exported defineFunction maps to one API Trigger in Orchestrator:
defineFunction field |
Orchestrator API Trigger field |
|---|---|
name |
Trigger name (display name in Orchestrator) |
method |
Verb (GET, POST, PUT, …) |
path |
Slug (appears in the trigger URL) |
description |
Description |
input schema |
Input JSON Schema (shown in Runtime Arguments) |
output schema |
Output JSON Schema |
| source file path | Entry point (content/functions/my-fn.ts) |
Calling mode is always Sync (long-polling). Account is always Run as HTTP Caller.
When you add, rename, or remove a function¶
| Change | What happens on next publish |
|---|---|
New defineFunction |
New entry-point + new binding → Orchestrator creates a new API Trigger |
Renamed name or path |
Existing binding drops, new one appears → Orchestrator deletes old trigger, creates new one |
Removed defineFunction |
Entry-point and binding removed → Orchestrator deletes the trigger |
Changed input/output schema |
Updated JSON Schema in entry-points.json → Orchestrator updates trigger Input/Output |
Lockfile¶
A project is locked with npm's package-lock.json. That lock ships in the .nupkg, and the production worker installs from it with bun. Run npm install after any package.json change, then pack.
On your machine the CLI holds every project to that lock. new installs with npm. serve, run, debug, pack, push and uip solution pack stop on a bun.lock, including one next to package-lock.json, since bun installs from bun.lock first: delete bun.lock and run npm install. pack, push and uip solution pack also stop when package-lock.json is missing or npm ci --dry-run reports that it differs from package.json. publish requires a lock in the package.
Install every dependency from a registry. pack, push and uip solution pack stop on a dependency that package-lock.json takes from a git repository, transitive ones included, and name it: replace it with a registry version, then pack again.
Publish¶
Uploads the .nupkg to an Orchestrator process feed. After upload, Orchestrator does not immediately sync triggers — you must update the Function Release manually (see below).
After publish: update the Function Release¶
Publishing uploads a new .nupkg version, but the Function Release in Orchestrator may still be pinned to the previous version. After every publish:
- Go to Orchestrator → Automations → Processes
- Find your package
- Update the release to the latest version
API note: The Orchestrator UI calls these "Processes" but the REST API endpoint is
/odata/Releases.
Orchestrator then re-reads the manifest and syncs triggers (adds new ones, removes deleted ones, updates changed schemas).
uip functions publish → nupkg uploaded
↓
Orchestrator: new version available
↓ (manual step today)
Update Function Release to latest version
↓
Triggers created / updated / deleted
Calling your function¶
Once the Function Release is updated, each function is reachable at its HTTP trigger URL.
Trigger URL¶
<api-host>: theapi.*subdomain — not the portal domain (see warning below)<org>/<tenant>: org and tenant identifiers — UUIDs are recommended for browser-callable URLs; slugs also work fromcurl<folder-key>: the Key of the folder the function is published into (a GUID). For the Personal-Workspace flow, this is the Personal Workspace folder's Key. It is not a per-trigger or per-tenant key — see the note below on how to discover it.<package-id>: yourpackage.jsonname(sanitized)<slug>: thepathfrom yourdefineFunction, without the leading slash (e.g.hello)
<package-id> and <slug> are two separate path segments (e.g. .../t/<folder-key>/my-functions/hello).
Always send Content-Type: application/json and a JSON body — send {} for a function that takes no input. A GET-verb function receives its input as query-string parameters instead of a body.
curl -X POST \
"https://api.uipath.com/<org>/<tenant>/orchestrator_/t/<folder-key>/my-functions/hello" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "Alice"}'
# → {"message":"Hello, Alice!"}
The portal domain maps to the API domain:
| Portal domain | API domain (use this) |
|---|---|
cloud.uipath.com |
api.uipath.com |
Portal domain causes CORS errors in the browser
The trigger URL shown in the Orchestrator UI uses the portal domain and org/tenant slugs. Calling that URL from a browser (coded app) produces a CORS error — the portal domain has no Access-Control-Allow-Origin header. The api.* subdomain does. Prefer UUIDs over slugs in the browser-callable URL. curl does not enforce CORS, so the portal URL works from the command line.
Discovering the folder key and slug
<folder-key> is the Key of the folder the function is published into. It is the same for every function in that folder — it is not generated per trigger. Discover it (and each function's slug) from the folder's HTTP triggers:
Each row exposes:
MethodandSlug— the function's HTTP verb and slugRelease.Name— the<package-id>ExternalReference— of the form<Method> <package-id>/<slug> <FOLDER-KEY>; the trailing GUID is the<folder-key>you put in the URL
Do not use the trigger's own Id as <folder-key> — that returns 404 {"errorCode": 1623, "message": "HTTP trigger not found..."}.
The older odata/ApiTriggers discovery query does not work: ApiTriggerDto has no ProcessKey, Key, or Url property, so ?$filter=ProcessKey eq '…'&$select=Key,Name,Url fails with 400 {"errorCode": 1000}.