IAB Tech Lab Negotiation API

Multi-round price negotiation

Operations 3

POST /proposals/{proposal_id}/counter Counter Proposal #
GET /proposals/{proposal_id}/negotiation Get Negotiation Status #
POST /api/v1/negotiations/messages Post Negotiation Message #

Documentation

Specifications

Schemas & Data

📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-deal.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-order.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-product.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-negotiation.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-proposal.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-mediakit.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-agent.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-line.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-account.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-organization.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-creative.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-creativeapproval.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-assignment.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-changerequest.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-consentcontext.json
📊
JSONSchema
https://raw.githubusercontent.com/api-evangelist/iab-tech-lab/refs/heads/main/json-schema/iab-tech-lab-agentic-primitive-decisionrecord.json

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/iab-tech-lab-negotiation-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

iab-tech-lab-negotiation-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Ad Seller System Negotiation API
  description: IAB OpenDirect 2.1 compliant seller agent for programmatic advertising. Supports product discovery, tiered pricing, proposal evaluation, multi-round negotiation, deal execution, order management, and change requests.
  contact:
    name: IAB Tech Lab
    url: https://iabtechlab.com/
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
  version: 1.0.0
tags:
- name: Negotiation
  description: Multi-round price negotiation
paths:
  /proposals/{proposal_id}/counter:
    post:
      tags:
      - Negotiation
      summary: Counter Proposal
      description: 'Submit a counter-offer in an ongoing negotiation.


        Loads or creates a NegotiationHistory, evaluates the buyer''s offer,

        persists the updated history, and emits a NEGOTIATION_ROUND event.


        EP-5.2: this endpoint previously applied NO trust-tier ceiling — a

        buyer could self-assert ADVERTISER pricing by populating

        advertiser_id. The claimed tier is now verified against the agent

        registry (agent_url) or the API key; unverifiable claims floor.'
      operationId: counter_proposal_proposals__proposal_id__counter_post
      parameters:
      - name: proposal_id
        in: path
        required: true
        schema:
          type: string
          title: Proposal Id
      - name: authorization
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Authorization
      - name: X-Api-Key
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: X-Api-Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CounterOfferRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /proposals/{proposal_id}/negotiation:
    get:
      tags:
      - Negotiation
      summary: Get Negotiation Status
      description: Get full negotiation history for a proposal.
      operationId: get_negotiation_status_proposals__proposal_id__negotiation_get
      parameters:
      - name: proposal_id
        in: path
        required: true
        schema:
          type: string
          title: Proposal Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/negotiations/messages:
    post:
      tags:
      - Negotiation
      summary: Post Negotiation Message
      description: 'Canonical negotiation surface — accepts the shared NegotiationMessage.


        The seller now validates the SAME message the buyer emits: a required

        ``action`` enum (accept/counter/reject/final_offer) plus ``buyer_price``

        as :class:`Money`. A well-formed counter no longer 422s (the historical

        bug). Priced actions (counter/final_offer) run the seller''s untouched

        negotiation engine; accept/reject are recorded as terminal rounds off

        the existing history.'
      operationId: post_negotiation_message_api_v1_negotiations_messages_post
      parameters:
      - name: authorization
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Authorization
      - name: X-Api-Key
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: X-Api-Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NegotiationMessage'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NegotiationRoundResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
    NegotiationMessage:
      properties:
        idempotency_key:
          type: string
          minLength: 1
          title: Idempotency Key
          description: Requester-minted opaque key (UUID recommended). Same key -> same response, no duplicate side effects (FD-12). Reusing a key with a different body is an idempotency_conflict error.
        action:
          $ref: '#/components/schemas/NegotiationAction'
          description: 'REQUIRED move discriminator: ''accept'', ''counter'', ''reject'' (walk-away), or ''final_offer''. No default — the action-less bare-price payload that caused the historical 422 does not validate.'
        negotiation_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Negotiation Id
          description: Seller-issued id of the negotiation to continue; None opens a new negotiation on proposal_id/quote_id.
        proposal_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Proposal Id
          description: Proposal under negotiation, if proposal-led.
        quote_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Quote Id
          description: Quote under negotiation, if quote-led.
        round_number:
          anyOf:
          - type: integer
            minimum: 1.0
          - type: 'null'
          title: Round Number
          description: The round the sender believes it is answering, for optimistic concurrency; a mismatch is a 'contention' error. The seller's numbering is authoritative.
        buyer_price:
          anyOf:
          - $ref: '#/components/schemas/Money'
          - type: 'null'
          description: The buyer's price this round (exact micros; FD-11). REQUIRED for 'counter'/'final_offer'; optional echo on 'accept'; omitted on 'reject'.
        buyer_identity:
          anyOf:
          - $ref: '#/components/schemas/BuyerIdentity'
          - type: 'null'
        rationale:
          type: string
          title: Rationale
          description: Optional human-readable rationale.
          default: ''
      type: object
      required:
      - idempotency_key
      - action
      title: NegotiationMessage
      description: 'A buyer negotiation move (money-mutating: FD-12).


        Exactly one negotiation context is required: ``negotiation_id`` to

        continue, or ``proposal_id``/``quote_id`` to open (the seller mints

        ``negotiation_id`` on open).'
    NegotiationRound:
      properties:
        round_number:
          type: integer
          minimum: 1.0
          title: Round Number
        buyer_price:
          $ref: '#/components/schemas/Money'
          description: What the buyer offered this round.
        seller_price:
          $ref: '#/components/schemas/Money'
          description: What the seller countered (or accepted at) this round.
        action:
          $ref: '#/components/schemas/NegotiationAction'
        concession_pct:
          type: number
          title: Concession Pct
          description: Seller concession this round (0-1).
          default: 0.0
        cumulative_concession_pct:
          type: number
          title: Cumulative Concession Pct
          description: Total seller concession so far (0-1).
          default: 0.0
        rationale:
          type: string
          title: Rationale
          default: ''
        timestamp:
          type: string
          format: date-time
          title: Timestamp
      type: object
      required:
      - round_number
      - buyer_price
      - seller_price
      - action
      title: NegotiationRound
      description: A single offer/counter round in a negotiation.
    Money:
      properties:
        amount_micros:
          type: integer
          title: Amount Micros
          description: Amount in micros; 1,000,000 micros = 1 currency unit.
        currency:
          type: string
          pattern: ^[A-Z]{3}$
          title: Currency
          description: ISO 4217 alpha-3 currency code.
          default: USD
      type: object
      required:
      - amount_micros
      title: Money
      description: 'Exact money amount in integer micros (flagged decision FD-11).


        ``1_000_000`` micros = 1 currency unit — the ad-industry convention

        (Google Ad Manager, among others, prices in micros). Float is BANNED on

        the wire for money: IEEE 754 floating point is non-deterministic for

        money math (``0.1 + 0.2 != 0.3``, and repeated CPM — cost per mille —

        arithmetic accumulates error), and the two source repos used ``float``

        end-to-end; that defect must not be fossilized into the spec. Every

        price, rate, budget, and offer in the shared contract is a ``Money``.


        ``amount_micros`` is a strict integer: float inputs are rejected at

        validation time rather than silently truncated.'
    NegotiationRoundResponse:
      properties:
        negotiation_id:
          type: string
          title: Negotiation Id
          description: Seller-issued negotiation identifier.
        status:
          $ref: '#/components/schemas/NegotiationStatus'
          description: '''active'' or terminal (''accepted''/''rejected''/''expired''); terminal negotiations refuse further messages (negotiation_closed).'
        round:
          $ref: '#/components/schemas/NegotiationRound'
        rounds_remaining:
          anyOf:
          - type: integer
            minimum: 0.0
          - type: 'null'
          title: Rounds Remaining
          description: Rounds left before the seller walks away, if disclosed.
      type: object
      required:
      - negotiation_id
      - status
      - round
      title: NegotiationRoundResponse
      description: 'The seller''s answer to a :class:`NegotiationMessage`.


        Embeds the shared

        :class:`~iab_agentic_primitives.primitives.NegotiationRound` primitive

        — the same record appended to the Negotiation history — so the two

        sides cannot disagree about what a round contains. ``round.action`` is

        the SELLER''s move (accept/counter/reject/final_offer); when

        ``status`` is terminal the round is the last one.'
    NegotiationAction:
      type: string
      enum:
      - accept
      - counter
      - reject
      - final_offer
      title: NegotiationAction
      description: Action taken in a negotiation round.
    BuyerIdentity:
      properties:
        seat_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Seat Id
          description: DSP seat identifier.
        seat_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Seat Name
          description: DSP platform display name.
        dsp_platform:
          anyOf:
          - type: string
          - type: 'null'
          title: Dsp Platform
          description: DSP platform slug (e.g. 'ttd', 'dv360').
        agency_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Agency Id
        agency_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Agency Name
        agency_holding_company:
          anyOf:
          - type: string
          - type: 'null'
          title: Agency Holding Company
        advertiser_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Advertiser Id
        advertiser_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Advertiser Name
        advertiser_industry:
          anyOf:
          - type: string
          - type: 'null'
          title: Advertiser Industry
        campaign_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Campaign Id
          description: Optional campaign scope for campaign-specific deals.
        campaign_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Campaign Name
      type: object
      title: BuyerIdentity
      description: 'Buyer identity revealed progressively to unlock better pricing.


        Superset of the buyer repo''s ``BuyerIdentity`` and the seller repo''s

        ``BuyerIdentity``/``QuoteBuyerIdentity``; every field is optional so a

        partially revealed identity is always representable. The tier derived

        from these fields is capped server-side by the registry-verified trust

        status of the calling agent — it is never self-asserted.'
    CounterOfferRequest:
      properties:
        buyer_price:
          type: number
          title: Buyer Price
        buyer_tier:
          type: string
          title: Buyer Tier
          default: public
        agency_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Agency Id
        advertiser_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Advertiser Id
        agent_url:
          anyOf:
          - type: string
          - type: 'null'
          title: Agent Url
      type: object
      required:
      - buyer_price
      title: CounterOfferRequest
      description: Request to submit a counter-offer in a negotiation.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    NegotiationStatus:
      type: string
      enum:
      - active
      - accepted
      - rejected
      - expired
      title: NegotiationStatus
      description: Status of a negotiation (typed; was a raw string in the seller repo).