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

# Register an agent target (atomic prove-then-persist)

> Fires a live round-trip and persists the target ONLY if the probe succeeds; a failed probe persists nothing and returns a categorized error (unreachable / auth_failed / parse_error). Static auth (none/bearer/api_key/basic) over http or websocket. The response never echoes the config, credential, or reply. The returned model_id is the handle for POST /api/v1/run. List first via GET /api/v1/model — creates are not deduplicated.



## OpenAPI

````yaml https://api.enokilabs.ai/openapi.json post /api/v1/model
openapi: 3.1.0
info:
  title: Enoki External API
  description: >-
    Programmatic API for CI/CD integration. Authenticate with `Authorization:
    Bearer egk_...`.
  version: 0.1.0
servers: []
security: []
paths:
  /api/v1/model:
    post:
      tags:
        - integration
      summary: Register an agent target (atomic prove-then-persist)
      description: >-
        Fires a live round-trip and persists the target ONLY if the probe
        succeeds; a failed probe persists nothing and returns a categorized
        error (unreachable / auth_failed / parse_error). Static auth
        (none/bearer/api_key/basic) over http or websocket. The response never
        echoes the config, credential, or reply. The returned model_id is the
        handle for POST /api/v1/run. List first via GET /api/v1/model — creates
        are not deduplicated.
      operationId: api_create_target_api_v1_model_post
      parameters:
        - name: Authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Bearer token with API key
            title: Authorization
          description: Bearer token with API key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApiCreateTargetRequest'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiCreateTargetResponse'
        '400':
          description: Endpoint URL rejected (scheme or private/internal address)
        '422':
          description: >-
            Two distinct shapes share this status. A **probe failure** returns
            `detail` as an **object** (`error_category` + a redacted message,
            shown below). A **request-validation** error returns the standard
            FastAPI `detail` as a **list** of per-field errors. Clients must
            branch on the type of `detail` (object vs list) rather than assume
            the validation shape.
          content:
            application/json:
              example:
                detail:
                  error: probe_failed
                  error_category: unreachable
                  message: Could not reach the target endpoint.
components:
  schemas:
    ApiCreateTargetRequest:
      properties:
        name:
          type: string
          maxLength: 200
          minLength: 1
          title: Name
          description: Display name for the target.
        environment:
          type: string
          enum:
            - prod
            - staging
            - dev
          title: Environment
          default: staging
        auth_type:
          type: string
          enum:
            - none
            - bearer
            - api_key
            - basic
          title: Auth Type
          description: >-
            bearer='Authorization: Bearer <cred>', api_key='x-api-key: <cred>',
            basic=HTTP Basic with the credential as 'user:password'. No
            enterprise auth.
          default: none
        credential:
          anyOf:
            - type: string
              minLength: 5
            - type: 'null'
          title: Credential
          description: >-
            Required for bearer/api_key/basic; omit for none. Stored encrypted,
            never returned.
        config:
          $ref: '#/components/schemas/ApiAgentConfig'
          description: >-
            Endpoint transport/parsing config (endpoint_url, response_field
            dot-path, transport, ...). Use request_timeout (<=180); ws_timeout
            is ignored here.
      type: object
      required:
        - name
        - config
      title: ApiCreateTargetRequest
      description: Request body for ``POST /api/v1/model`` (register an agent target).
    ApiCreateTargetResponse:
      properties:
        model_id:
          type: string
          title: Model Id
          description: Inventory model id — use directly as model_id in POST /api/v1/run.
        connected:
          type: boolean
          const: true
          title: Connected
          description: 'Always true: the target is persisted only after a successful probe.'
      type: object
      required:
        - model_id
        - connected
      title: ApiCreateTargetResponse
      description: |-
        Response for ``POST /api/v1/model`` (201).

        Lean by contract: the inventory id + the connection verdict only. Never
        echoes the config (it may hold a customer-embedded header secret), the
        credential, or any part of the target's reply.
    ApiAgentConfig:
      properties:
        endpoint_url:
          type: string
          title: Endpoint Url
        request_field:
          type: string
          title: Request Field
          default: message
        response_field:
          type: string
          title: Response Field
          default: response
        session_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Session Field
          default: session_id
        session_response_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Session Response Field
        session_response_header_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Session Response Header Field
        session_id_numeric:
          type: boolean
          title: Session Id Numeric
          default: false
        transport:
          type: string
          enum:
            - http
            - websocket
          title: Transport
          default: http
        http_stream_format:
          type: string
          enum:
            - sync
            - jsonl
            - sse
          title: Http Stream Format
          default: sync
        chunk_combination:
          type: string
          enum:
            - concatenate
            - replace
          title: Chunk Combination
          default: concatenate
        chunk_skip_roles:
          items:
            type: string
          type: array
          title: Chunk Skip Roles
        extra_http_headers:
          anyOf:
            - additionalProperties:
                type: string
              type: object
            - type: 'null'
          title: Extra Http Headers
        request_body_template:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Request Body Template
        ws_auth_method:
          anyOf:
            - type: string
              enum:
                - query_param
                - header
                - post_connect
            - type: 'null'
          title: Ws Auth Method
        ws_auth_endpoint:
          type: 'null'
          title: Ws Auth Endpoint
        ws_url_endpoint:
          type: 'null'
          title: Ws Url Endpoint
        ws_request_extra_fields:
          anyOf:
            - additionalProperties:
                anyOf:
                  - type: string
                  - type: integer
                  - type: number
                  - type: boolean
              type: object
            - type: 'null'
          title: Ws Request Extra Fields
        ws_event_type_field:
          type: string
          title: Ws Event Type Field
          default: type
        ws_done_event_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Ws Done Event Type
        ws_result_extract_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Ws Result Extract Field
        ws_stream_extract_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Ws Stream Extract Field
        request_timeout:
          type: number
          maximum: 180
          exclusiveMinimum: 0
          title: Request Timeout
          default: 180
      type: object
      required:
        - endpoint_url
      title: ApiAgentConfig
      description: >-
        Snake_case wire form of :class:`AgentConfig` for the external create
        path.


        Subclasses the domain model so new fields need no edit here; the v1

        subset is enforced by type. The external API is snake_case (unlike the

        camelCase dashboard :class:`AgentConfigSchema`), and the domain model is

        natively snake_case, so no alias generator is needed — the body keys are

        the field names.


        v1 restrictions, all enforced by narrowing the field type so an excluded

        value is a 422 with OpenAPI-visible allowed values:


        - ``presigned_url`` ws auth is excluded, and its pre-auth URL fields
          (``ws_auth_endpoint`` / ``ws_url_endpoint``) are pinned to ``None`` — an
          absolute value there would ``urljoin`` a credential-bearing pre-auth POST
          to a host the entry-point SSRF guard never validated.
        - ``request_timeout`` is capped at 180s so an inline probe cannot hold
        an
          HTTP worker open past the platform request ceiling; the domain default
          (180) stays valid. The legacy ``ws_timeout`` validation alias is
          deliberately dropped (the subclass override replaces the parent field),
          so only the canonical ``request_timeout`` key is accepted — a posted
          ``ws_timeout`` is ignored (``extra`` is not forbidden but unknown keys are
          dropped); ``ws_timeout`` exists only for already-persisted rows.

````