Hire an AI Employee
On this page
Hire a published AI Employee for a brand. The hire is created immediately and the agent is provisioned in the background — there is no payment step in this flow.
POST /api/v1/employees/{profile_id}/hireprofile_id is the UUID of a published catalog profile (an "AI Employee").
Who can call it
The same endpoint serves two callers. The endpoint detects which one you are from your credentials.
Active-brand self-serve. A signed-in brand user hires for their own brand. The brand must have an active subscription. The brand is always taken from your session — you cannot hire on another brand's behalf.
Admin grant. A platform super-admin grants a hire for any brand, optionally recording a reason (for a comped / free hire). Authenticate with an admin API key (X-Admin-Key) or an admin dashboard session, and name the target brand in the body.
Request
Self-serve
The body is empty — the brand comes from your session.
curl -X POST https://api.opvs.ai/api/v1/employees/$PROFILE_ID/hire \
-H "Cookie: $SESSION_COOKIE" \
-H "Content-Type: application/json" \
-d '{}'Admin grant
curl -X POST https://api.opvs.ai/api/v1/employees/$PROFILE_ID/hire \
-H "X-Admin-Key: $OPVS_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"brand_id": 11, "comp_reason": "Beta partner — comped"}'Body fields
Field | Type | Notes |
|---|---|---|
| integer | Admin only, required. The brand to hire for. Ignored on the self-serve path. |
| string | Admin only, optional. Rationale for a comped hire. Ignored on the self-serve path. |
Response
{
"hire_id": "f1e2d3c4-0000-4444-8888-aaaabbbbcccc",
"status": "provisioning",
"onboarding_url": "/dashboard/agents/onboarding?hire=f1e2d3c4-0000-4444-8888-aaaabbbbcccc"
}The hire starts in provisioning. The agent (marketplace skills installed, persona deployed) is built out-of-band; poll the hire or open onboarding_url to watch it become active.
Status codes
Code | Meaning |
|---|---|
| Hire created; provisioning started. |
| Not authenticated. |
| Self-serve path: the brand's subscription is not active. Ask an admin to grant the hire, or activate a subscription. |
| No published employee with that |
| This brand already holds an active hire of this employee. The body's |
| Admin path with no |
| Rate limit exceeded (5 hires/brand/hour self-serve, 50 grants/admin/hour). |
Cancel a hire
Two endpoints end a hire. They differ in when it ends, and in how much of the agent actually goes away.
POST /api/v1/employees/hires/{hire_id}/cancel
POST /api/v1/employees/hires/{hire_id}/cancel-immediateAn admin may cancel any hire; a brand user may cancel only a hire their own brand holds.
Cancel at period end
The agent keeps running until current_period_end. Nothing is disabled at call time — the reconcile loop performs the marketplace disable once the date passes.
{
"hire_id": "f1e2d3c4-0000-4444-8888-aaaabbbbcccc",
"status": "canceled",
"cancel_at_period_end": true,
"effective_at": "2026-10-07T00:00:00Z",
"marketplace_disable_at": "2026-10-07T00:01:00Z"
}Cancel immediately
The hire flips to canceled now and its marketplace installs are ref-counted disabled: an install turns off only if no other active hire of the same brand still references it. Tools disappear within the gateway's 60-second grant-cache TTL, which is why marketplace_disable_at is a minute after effective_at.
{
"hire_id": "f1e2d3c4-0000-4444-8888-aaaabbbbcccc",
"status": "canceled",
"effective_at": "2026-09-07T12:00:00Z",
"marketplace_disable_at": "2026-09-07T12:01:00Z",
"installs_disabled": 2,
"installs_retained": 1,
"management_record_deleted": true,
"gateway_entry_removed": false,
"agent_torn_down": false
}Read the teardown fields separately
Cancelling revokes an employee's tools. It does not unregister the agent.
Field | Meaning |
|---|---|
| The agent's |
| Whether the gateway's own registration was removed. Always |
| Deprecated. Always |
While gateway_entry_removed is false, the persona stays reachable and can still be messaged, with its marketplace tools disabled. If you are cancelling in order to stop an agent answering, cancelling is not sufficient on its own.
agent_torn_down previously returned true on the Management API delete alone, reporting a teardown that had not happened. It now means what it says: true only when the agent is fully gone, which a cancel cannot achieve.
Status codes
Code | Meaning |
|---|---|
| Cancelled. |
| Not authenticated. |
| The hire belongs to another brand. |
| No such hire. |
| The hire is not in a state that can be cancelled. |