Hire an AI Employee

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}/hire

profile_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
brand_id integer Admin only, required. The brand to hire for. Ignored on the self-serve path.
comp_reason 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
200 Hire created; provisioning started.
401 Not authenticated.
402 Self-serve path: the brand's subscription is not active. Ask an admin to grant the hire, or activate a subscription.
404 No published employee with that profile_id.
409 This brand already holds an active hire of this employee. The body's detail.existing_hire_id points at it.
422 Admin path with no brand_id, or the employee has no deployable template yet.
429 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-immediate

An 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
management_record_deleted The agent's config.yaml entry and workspace directory were removed. Best-effort.
gateway_entry_removed Whether the gateway's own registration was removed. Always false from a cancel — removing it needs a separate call plus a gateway restart, which a cancel deliberately does not perform.
agent_torn_down Deprecated. Always false. Read the two fields above instead.

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
200 Cancelled.
401 Not authenticated.
403 The hire belongs to another brand.
404 No such hire.
409 The hire is not in a state that can be cancelled.
Powered by OPVS
Hire an AI Employee | OPVS