> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-feature-feedback.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Register an agent

> Register an agent on the caller's organization member profile.

Idempotent on `url`: re-posting the same `url` updates the entry in place rather than creating a duplicate. New entries return `201`; updates return `200`.

**True one-call storefront experience.** A third-party app holding only a user's OAuth token can `POST /api/me/agents` once and have the entire bootstrap chain materialize:

- If the caller has zero org memberships, the server auto-creates an organization (corporate or personal workspace based on the user's email domain) and the response includes `org_auto_created: true`.

- If the caller's org has no member profile, the server auto-creates a private profile (display name = organization name, `is_public: false`) and the response includes `profile_auto_created: true`.

Both auto-bootstraps are best-effort fallbacks. To customize org name / company_type / revenue_tier, or to control profile slug / brand identity / tagline, call `POST /api/organizations` and `POST /api/me/member-profile` explicitly before registering the agent. Tier transitions never happen via this path — go through the billing flow.

`type` is required and declared by the caller — the server does not infer it. Server-side smuggle protection still cross-checks the declared type against the agent's capability snapshot when one exists; if the snapshot contradicts the declaration without classifying it, the stored value is `unknown` and the dashboard surfaces the conflict for the owner to resolve.

`visibility: "public"` requires a paid AAO tier (Professional, Builder, Member, or Leader) and a verified primary domain on the organization (set via the Linked Domains UI). Non-API-tier callers (Explorer or no tier) who request `public` will have the entry stored as `members_only` instead, and the response will include a `visibility_downgraded` warning describing the coercion.



## OpenAPI

````yaml /static/openapi/registry.yaml post /api/me/agents
openapi: 3.1.0
info:
  title: AgenticAdvertising.org Registry API
  description: >-
    REST API for the AgenticAdvertising.org registry. Resolve brands,

    discover properties, look up agents, and validate authorization in the

    AdCP ecosystem.


    Most endpoints are public and require no authentication. Endpoints marked

    with a lock icon accept either an organization API key or a user JWT

    obtained via the OAuth 2.1 flow — see
    [Authentication](https://agenticadvertising.org/docs/registry/index#authentication).


    **Base URL:** `https://agenticadvertising.org`
  version: 1.0.0
  contact:
    name: AgenticAdvertising.org
    url: https://agenticadvertising.org
servers:
  - url: https://agenticadvertising.org
    description: Production
security: []
tags:
  - name: Onboarding
    description: >-
      Explicitly bootstrap a third-party integration into the AAO registry. Most
      callers don't need this tag — `POST /api/me/agents` auto-creates the org
      (for fresh users) and the member profile (for first-time agent
      registration) without a separate round trip. Use `POST /api/organizations`
      only when you need to override the auto-derived org name / company_type /
      revenue_tier. Tier transitions happen via the billing flow only; the
      Stripe webhook is the sole writer of `organizations.membership_tier`.
  - name: Member Agents
    description: >-
      Register, list, update, and remove agents on the caller's organization
      member profile. Authenticated programmatic surface for CI / scripts that
      don't want to round-trip the full member profile.
  - name: Brand Resolution
    description: Resolve advertiser domains to canonical brand identities.
  - name: Property Resolution
    description: >-
      Resolve publisher domains to their property configurations and authorized
      agents.
  - name: Agent Discovery
    description: >-
      Browse the federated agent network, search agent inventory profiles,
      publisher index, and registry statistics.
  - name: Change Feed
    description: Poll cursor-based registry change events for local sync.
  - name: Lookups & Authorization
    description: >-
      Look up agents by domain or property, and validate ad-serving
      authorization.
  - name: Validation Tools
    description: >-
      Validate publisher adagents.json files and generate compliant
      configurations.
  - name: Community Mirrors
    description: >-
      Publish, fetch, list, and retire catalog-only adagents.json mirrors for
      platforms that have not adopted AdCP.
  - name: Search
    description: Cross-entity search across brands, publishers, agents, and properties.
  - name: Agent Probing
    description: >-
      Connect to live agents and inspect their capabilities, formats, and
      inventory.
  - name: Brand Discovery
    description: Discover and crawl brand.json files across domains.
  - name: Agent Compliance
    description: Agent compliance status, storyboard test results, and compliance history.
  - name: Policy Registry
    description: >-
      Browse, resolve, and contribute governance policies for campaign
      compliance.
paths:
  /api/me/agents:
    post:
      tags:
        - Member Agents
      summary: Register an agent
      description: >-
        Register an agent on the caller's organization member profile.


        Idempotent on `url`: re-posting the same `url` updates the entry in
        place rather than creating a duplicate. New entries return `201`;
        updates return `200`.


        **True one-call storefront experience.** A third-party app holding only
        a user's OAuth token can `POST /api/me/agents` once and have the entire
        bootstrap chain materialize:


        - If the caller has zero org memberships, the server auto-creates an
        organization (corporate or personal workspace based on the user's email
        domain) and the response includes `org_auto_created: true`.


        - If the caller's org has no member profile, the server auto-creates a
        private profile (display name = organization name, `is_public: false`)
        and the response includes `profile_auto_created: true`.


        Both auto-bootstraps are best-effort fallbacks. To customize org name /
        company_type / revenue_tier, or to control profile slug / brand identity
        / tagline, call `POST /api/organizations` and `POST
        /api/me/member-profile` explicitly before registering the agent. Tier
        transitions never happen via this path — go through the billing flow.


        `type` is required and declared by the caller — the server does not
        infer it. Server-side smuggle protection still cross-checks the declared
        type against the agent's capability snapshot when one exists; if the
        snapshot contradicts the declaration without classifying it, the stored
        value is `unknown` and the dashboard surfaces the conflict for the owner
        to resolve.


        `visibility: "public"` requires a paid AAO tier (Professional, Builder,
        Member, or Leader) and a verified primary domain on the organization
        (set via the Linked Domains UI). Non-API-tier callers (Explorer or no
        tier) who request `public` will have the entry stored as `members_only`
        instead, and the response will include a `visibility_downgraded` warning
        describing the coercion.
      operationId: registerMemberAgent
      parameters:
        - schema:
            type: string
            description: >-
              WorkOS organization id to act on. Defaults to the caller's primary
              organization. Use this from a multi-org session (or when shelling
              with a user JWT) to target a non-primary org. Verification goes
              through WorkOS membership lookup; non-members get `403`.
            example: org_01HXZAB123
          required: false
          description: >-
            WorkOS organization id to act on. Defaults to the caller's primary
            organization. Use this from a multi-org session (or when shelling
            with a user JWT) to target a non-primary org. Verification goes
            through WorkOS membership lookup; non-members get `403`.
          name: org
          in: query
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MemberAgentInput'
      responses:
        '200':
          description: Agent already registered at this `url`; entry updated in place.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemberAgentResponse'
        '201':
          description: >-
            Agent registered. When this is the first agent on a freshly created
            organization, the response includes `profile_auto_created: true`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemberAgentResponse'
        '400':
          description: >-
            Missing or invalid `url`, missing/invalid `type`, or the caller has
            memberships in other orgs but no primary org set — pass `?org=<id>`
            to target one explicitly. (Fresh users with no memberships at all
            hit the org auto-bootstrap path and do not see this error.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            `?org=` was supplied but the caller is not a member of that
            organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            Auto-bootstrap could not run (e.g. the organization has no name
            yet). Call `POST /api/me/member-profile` to create a profile
            explicitly, then retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - bearerAuth: []
        - oauth2: []
components:
  schemas:
    MemberAgentInput:
      type: object
      properties:
        url:
          type: string
          format: uri
          example: https://agent.example.com/mcp
        type:
          $ref: '#/components/schemas/MemberAgentTypeInput'
        name:
          type: string
        visibility:
          $ref: '#/components/schemas/MemberAgentVisibility'
        health_check_url:
          type: string
          format: uri
      required:
        - url
        - type
      description: >-
        Request body for `POST /api/me/agents`. `type` is required — the owner
        declares it; the server never infers.
    MemberAgentResponse:
      type: object
      properties:
        agent:
          $ref: '#/components/schemas/MemberAgent'
        warnings:
          type: array
          items:
            $ref: '#/components/schemas/MemberAgentVisibilityWarning'
        org_auto_created:
          type: boolean
          description: >-
            Set to `true` when this `POST` was the caller's first interaction
            with the registry and the server auto-created the organization
            (display name derived from the user's email domain for corporate
            emails, or `<First Last>'s Workspace` for free-email providers).
            Combined with `profile_auto_created`, this is the one-call
            storefront experience: a third-party app holding only an OAuth token
            gets the org, profile, and registered agent in a single request.
        profile_auto_created:
          type: boolean
          description: >-
            Set to `true` when this `POST` was the first agent registration on
            the caller's organization and the server auto-created a private
            member profile (display name = organization name, `is_public:
            false`). Absent on subsequent calls and on update-in-place. Surfaced
            so storefront-style integrations can show a "we set up your profile"
            hint without needing to detect the prior 404 → bootstrap → retry
            shape.
      required:
        - agent
    Error:
      type: object
      properties:
        error:
          type: string
      required:
        - error
    MemberAgentTypeInput:
      type: string
      enum:
        - brand
        - rights
        - measurement
        - governance
        - creative
        - sales
        - buying
        - signals
      description: >-
        Agent type the caller declares. Required on register; smuggle-protection
        still cross-checks against the capability snapshot when one exists. The
        server never infers `type` — the owner declares what kind of agent this
        is.
    MemberAgentVisibility:
      type: string
      enum:
        - private
        - members_only
        - public
      description: >-
        Visibility tier on the registry catalog. `private` = profile owner only;
        `members_only` = AAO API-tier members on operator lookup; `public` =
        listed in the public catalog and reflected in the org's `brand.json`
        (requires a paid AAO tier — Professional, Builder, Member, or Leader).
    MemberAgent:
      type: object
      properties:
        url:
          type: string
          format: uri
          example: https://agent.example.com/mcp
        visibility:
          $ref: '#/components/schemas/MemberAgentVisibility'
        type:
          $ref: '#/components/schemas/MemberAgentType'
        name:
          type: string
        health_check_url:
          type: string
          format: uri
          description: >-
            Optional fallback liveness URL used by the health probe when the
            protocol handshake fails.
      required:
        - url
        - visibility
        - type
      description: >-
        Agent entry stored on a member profile. `type` is required on read
        because every write surface declares it and the operator endpoint always
        emits it; a stored value of `unknown` is the smuggle-protection outcome
        (snapshot contradicted the declaration without classifying it) and is
        the only path that surfaces an agent without a real type.
    MemberAgentVisibilityWarning:
      type: object
      properties:
        code:
          type: string
          enum:
            - visibility_downgraded
        agent_url:
          type: string
        requested:
          type: string
          enum:
            - public
        applied:
          type: string
          enum:
            - members_only
        reason:
          type: string
          enum:
            - tier_required
        message:
          type: string
      required:
        - code
        - agent_url
        - requested
        - applied
        - reason
        - message
      description: Emitted when the tier gate downgrades a requested visibility.
    MemberAgentType:
      type: string
      enum:
        - brand
        - rights
        - measurement
        - governance
        - creative
        - sales
        - buying
        - signals
        - unknown
      description: >-
        Agent type as stored on the registry. Server-side smuggle protection
        compares the caller's declaration against the capability snapshot (when
        one exists) and may stamp `unknown` if the snapshot contradicts the
        declaration without classifying it. `unknown` is reserved for that
        server-side outcome; clients cannot submit it.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Bearer token in the `Authorization` header. Two token types are
        accepted:


        - **Organization API key** (`sk_...`) issued via the dashboard.
        Org-scoped, long-lived, for server-to-server use.

        - **User JWT** obtained via the OAuth 2.1 authorization code flow with
        PKCE. User-scoped, short-lived. Discover the authorization server at
        `/.well-known/oauth-authorization-server` and the protected-resource
        metadata at `/.well-known/oauth-protected-resource/api`.
    oauth2:
      type: oauth2
      description: >-
        OAuth 2.1 authorization code flow with PKCE. Users authenticate via
        AuthKit and clients receive a Bearer JWT that authorizes both the MCP
        endpoint and this REST API. Dynamic client registration is supported at
        `/register`.
      flows:
        authorizationCode:
          authorizationUrl: https://agenticadvertising.org/authorize
          tokenUrl: https://agenticadvertising.org/token
          refreshUrl: https://agenticadvertising.org/token
          scopes:
            openid: User identifier
            profile: User profile information
            email: User email address

````