> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ergoly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Assign a client to a worker

> Creates that pair's client-tier ework and, in the same call, optionally maps channels and binds people to it. The routing rows are durable when this returns; `activation` says whether the agent behind them came up. A channel or a person already bound to a different Client is refused rather than re-pointed. Channels the bot could not join are reported in `joinFailures` and do not fail the call.

**Binding brings up a client-tier ework — a sandbox and an agent. It costs money and spends one of your organization's daily provisioning slots.**



## OpenAPI

````yaml /openapi.json post /api/v1/workers/{id}/clients
openapi: 3.1.0
info:
  title: Ergoly platform API
  version: 1.0.0
  description: >-
    Read and change one organization's own Ergoly environment. Every route is
    scoped to the organization the presented credential resolves to; there is no
    parameter that widens it. The human-readable reference is served from the
    same namespace at `/api/v1/docs`, behind the same credential.


    The namespace's front door is `GET /api/v1`, and it is deliberately absent
    from `paths` below. It answers without a credential — what this API is, how
    an organization admin mints a key, and where the reference lives — so it is
    the way in to this contract rather than a part of it: it has no scope, takes
    no parameters, and there is nothing about it for a generated client to call.
    Every `unauthorized` refusal carries that same URL as `error.docs`.
servers:
  - url: https://control.ergoly.ai
security:
  - orgApiKey: []
tags:
  - name: auth
    description: How to present a key, what it is scoped to, and what a 401 means.
  - name: organization
    description: Which organization your credential resolves to.
  - name: workers
    description: The Slack apps and bot identities in your organization.
  - name: eworks
    description: The runtime instances under a Worker — one core, one per bound Client.
  - name: clients
    description: The customers a Worker can be scoped to, and how to bind one.
  - name: channels
    description: Which Slack rooms a Worker answers in, and who it answers as.
  - name: tasks
    description: >-
      Tasks handed between Workers and people, scheduled jobs, their targets,
      and their run history.
  - name: jobs
    description: How a provisioning run is going — the other half of every 202.
  - name: memory
    description: Read and write the memory tiers an ework mounts.
  - name: connections
    description: The credentials your agents use, and the hosts they are injected on.
  - name: webhooks
    description: Inbound URLs an outside system can POST to, each of which starts a turn.
  - name: activity
    description: Your organization's audit feed.
  - name: usage
    description: Cost, turn outcomes and a per-day pulse over a window you choose.
  - name: errors
    description: The closed set of refusal codes, and what to do about each.
paths:
  /api/v1/workers/{id}/clients:
    post:
      tags:
        - clients
      summary: Assign a client to a worker
      description: >-
        Creates that pair's client-tier ework and, in the same call, optionally
        maps channels and binds people to it. The routing rows are durable when
        this returns; `activation` says whether the agent behind them came up. A
        channel or a person already bound to a different Client is refused
        rather than re-pointed. Channels the bot could not join are reported in
        `joinFailures` and do not fail the call.


        **Binding brings up a client-tier ework — a sandbox and an agent. It
        costs money and spends one of your organization's daily provisioning
        slots.**
      operationId: bindClientToWorker
      parameters:
        - name: id
          in: path
          required: true
          description: >-
            The Worker id. A malformed id answers 404, exactly as another
            organization's well-formed id does.
          schema:
            type: string
            description: >-
              The Worker id. A malformed id answers 404, exactly as another
              organization's well-formed id does.
        - name: Idempotency-Key
          in: header
          required: false
          description: >-
            Any unique string. A retry under the same key is answered from the
            first attempt's record, with `X-Idempotent-Replay: true`. The same
            key with a different body is a conflict.
          schema:
            type: string
            description: Any unique string.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                clientId:
                  type: string
                  description: >-
                    The Client to bind. Resolved under your organization, so
                    another tenant's id is a 404.
                channels:
                  type: array
                  items:
                    type: string
                    description: A Slack channel id (`C…`) to route to this Client.
                  description: Channels to map to this Client. The bot joins each one.
                people:
                  type: array
                  items:
                    type: string
                    description: A Slack user id (`U…`).
                  description: People whose DMs should reach this Client's ework.
              required:
                - clientId
              additionalProperties: false
            example:
              clientId: c1a2b3c4-d5e6-4f70-8912-3a4b5c6d7e8f
              channels:
                - C0A1B2C3D4E
              people:
                - U0A1B2C3D4F
      responses:
        '202':
          description: Success.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/BoundClient'
                required:
                  - data
                additionalProperties: false
              example:
                data:
                  eworkId: 3b7e1c44-2d59-4f0a-9c81-5e6d7a8b9c01
                  clientId: c1a2b3c4-d5e6-4f70-8912-3a4b5c6d7e8f
                  channelsBound: 1
                  peopleBound: 2
                  activation:
                    status: succeeded
                  joinedChannels:
                    - C0A1B2C3D4E
                  joinFailures: []
        '400':
          description: '`invalid_request`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: '`unauthorized`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: '`not_found`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: '`conflict`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: '`quota_exceeded`, `rate_limited`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuotaError'
      security:
        - orgApiKey:
            - workers:write
components:
  schemas:
    BoundClient:
      type: object
      properties:
        eworkId:
          type: string
          description: The client-tier ework for this pair.
        clientId:
          type: string
          description: The Client that was bound.
        channelsBound:
          type: integer
          description: How many channel mappings were written.
        peopleBound:
          type: integer
          description: How many people were bound to this Client.
        activation:
          type: object
          description: >-
            The routing row is durable when this call returns; the agent may
            still be coming up. This says which.
          properties:
            status:
              type: string
              enum:
                - succeeded
                - failed
                - skipped
              description: What became of the activation.
            reason:
              type: string
              description: >-
                Why, when it did not simply succeed: `already_provisioned` |
                `worker_not_active` | `already_running` | `activation_failed`.
                Absent on a clean success.
          required:
            - status
          additionalProperties: false
        joinedChannels:
          type: array
          items:
            type: string
            description: A channel id the bot joined.
          description: Channels the bot joined.
        joinFailures:
          type: array
          items:
            type: object
            properties:
              channel:
                type: string
                description: The channel it could not join.
              code:
                type: string
                description: >-
                  Slack's own machine code (`missing_scope`, `is_archived`, …),
                  or `join_failed`.
            required:
              - channel
              - code
            additionalProperties: false
          description: >-
            Channels the bot could not join. A join failure does not fail the
            bind.
      required:
        - eworkId
        - clientId
        - channelsBound
        - peopleBound
        - activation
        - joinedChannels
        - joinFailures
      additionalProperties: false
    Error:
      type: object
      description: The one error shape. Every refusal in this namespace has it.
      properties:
        error:
          type: object
          description: The refusal.
          properties:
            code:
              type: string
              enum:
                - unauthorized
                - not_found
                - invalid_request
                - conflict
                - quota_exceeded
                - rate_limited
                - upstream_error
                - gone
              description: The machine-stable half. Branch on this, never on `message`.
            message:
              type: string
              description: Prose for a human reading a terminal.
            docs:
              type: string
              description: >-
                Where to learn how to authenticate. Present on `unauthorized`
                and on nothing else — it is the one refusal a caller can reach
                with no credential at all, so it is the one that has to say
                where the way in is.
          required:
            - code
            - message
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    QuotaError:
      type: object
      description: >-
        A `quota_exceeded` body. `Retry-After` carries the same wait as a
        header.
      properties:
        error:
          type: object
          description: The refusal, with the numbers a caller needs to back off correctly.
          properties:
            code:
              type: string
              enum:
                - quota_exceeded
              description: Always `quota_exceeded`.
            message:
              type: string
              description: Prose for a human reading a terminal.
            limit:
              type: integer
              description: The ceiling that was hit, in provisioning runs per rolling day.
            resetsAt:
              type: string
              format: date-time
              description: >-
                When the oldest counted run falls out of the window. A lower
                bound — retry then and you may get a fresher answer.
          required:
            - code
            - message
            - limit
            - resetsAt
          additionalProperties: false
      required:
        - error
      additionalProperties: false
  securitySchemes:
    orgApiKey:
      type: http
      scheme: bearer
      description: >-
        An organization-scoped API key, minted in control under Settings → API
        keys. Every failure to authenticate answers one identical 401: "Provide
        a valid organization-scoped API key or an active session." Each
        operation names the one scope it is filed under,
        `<resource>:<read|write>`, where the resource is the first path segment
        after `/api/v1/`; a key minted today carries all 22 of them. Scopes are
        RECORDED — on the key and on every audit row — and are not yet enforced:
        no request is refused for want of one.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.