argus-town Negotiated pricing API

The Negotiated pricing API from argus-town — 1 operation(s) for negotiated pricing.

Operations 3

PUT /v1/negotiated_pricing/{provider} Set negotiated pricing #
GET /v1/negotiated_pricing/{provider} Get negotiated pricing #
DELETE /v1/negotiated_pricing/{provider} Reset to list pricing #

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/argus-town:argus-town-negotiated-pricing-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

argus-town-negotiated-pricing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Argus Negotiated pricing API
  version: '1'
  description: 'Argus API v1: spend, balances and rate-limit headroom across the APIs you pay for.

    Authenticate reads with an `api` key as `Authorization: Bearer `. Every key sees one project.

    Operations marked `x-access: session` are for the signed-in web app; API keys get `session_required`.

    Operations marked `x-web: true` also accept the web app''s session, which API clients never use.

    Operations with `x-mcp-key-types` are also MCP tools of the same name at `POST https://mcp.argus.town`, for keys of those types.

    Send events with a source secret (`Authorization: Bearer argus_src_...` plus `Argus-Source`) or HMAC headers. A source credential can write events and read nothing; an API key cannot write events.

    Responses are bare resources with an `object` tag; lists are `{object: "list", data, has_more, next_cursor}`.

    Errors are `{error: {type, code, message, param, doc_url, next_step, request_id}}` with real HTTP statuses.

    Unknown query parameters are rejected. Ids are prefixed (`conn_...`); bare ids are accepted on input.

    Within v1 changes are additive: ignore fields you do not recognise.'
servers:
- url: https://api.argus.town
tags:
- name: Negotiated pricing
paths:
  /v1/negotiated_pricing/{provider}:
    put:
      operationId: negotiated_pricing_put
      tags:
      - Negotiated pricing
      summary: Set negotiated pricing
      description: 'Record what your deal with a provider costs, so spend is priced at your rates instead of list price. `rates` are set one per `sku` and `unit` (rates you do not list are kept); `plan` replaces the negotiated subscription, and fields you omit from it are cleared. Every entry is validated and one bad entry rejects the request with `param` naming it: nothing is skipped silently. Events from the last 7 days that were left unpriced are repriced. `provider` is any provider slug your events use, catalog or not. At most 500 rates and 100 plans per project. List rates are read-only (`GET /v1/negotiated_pricing/{provider}?expand[]=list_rates`); resetting to list price is done in the app.'
      security:
      - bearerAuth: []
      x-access: api_key
      x-web: true
      x-mcp-key-types:
      - api
      parameters:
      - name: provider
        in: path
        required: true
        description: Provider slug, for example `openrouter`.
        schema:
          type: string
      - name: Idempotency-Key
        in: header
        required: false
        description: '1 to 255 printable ASCII characters. A retry with the same key and body replays the first response (`Idempotent-Replayed: true`) for 24 hours; the same key with a different body is a 409, and so is a duplicate that arrives while the first request is still running.'
        schema:
          type: string
      requestBody:
        required: true
        description: Rates, a plan, or both.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NegotiatedPricingBody'
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NegotiatedPricing'
              examples:
                one rate:
                  summary: one rate
                  value:
                    object: negotiated_pricing
                    provider: openrouter
                    rates:
                    - sku: gpt-4o
                      unit: input_tokens
                      nano_usd_per_unit: 2000
                    plan: null
                    updated_at: '2026-10-01T09:30:00.000Z'
        '400':
          description: 'Error. Codes: invalid_request_body, invalid_parameter, invalid_idempotency_key, unknown_parameter, missing_parameter.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                malformed rate:
                  summary: malformed rate
                  value:
                    error:
                      type: invalid_request
                      code: invalid_parameter
                      message: 'Invalid value for "rates[0].nano_usd_per_unit": Expected a number between 0 and 1000000000000, actual -1'
                      param: rates[0].nano_usd_per_unit
                      doc_url: https://argus.town/docs/errors#invalid_parameter
                      request_id: null
        '401':
          description: 'Error. Codes: missing_credentials, invalid_api_key, session_expired.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '403':
          description: 'Error. Codes: key_type_not_allowed, session_required, csrf_check_failed.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '404':
          description: 'Error. Codes: provider_not_found.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '409':
          description: 'Error. Codes: idempotency_key_reused, quota_exceeded, idempotency_key_in_progress.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '413':
          description: 'Error. Codes: payload_too_large.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '429':
          description: 'Error. Codes: rate_limit_exceeded.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
        '500':
          description: 'Error. Codes: internal_error.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
      x-argus-examples:
      - name: one rate
        request:
          method: PUT
          path: /v1/negotiated_pricing/openrouter
          body:
            rates:
            - sku: gpt-4o
              unit: input_tokens
              nano_usd_per_unit: 2000
        status: 200
      - name: malformed rate
        request:
          method: PUT
          path: /v1/negotiated_pricing/openrouter
          body:
            rates:
            - sku: gpt-4o
              unit: input_tokens
              nano_usd_per_unit: -1
        status: 400
    get:
      operationId: negotiated_pricing_get
      tags:
      - Negotiated pricing
      summary: Get negotiated pricing
      description: The project's own rates and subscription for a provider; empty `rates` and a null `plan` when nothing is negotiated. `expand[]=list_rates` adds Argus's list rates, which negotiated rates replace one for one.
      security:
      - bearerAuth: []
      x-access: api_key
      x-web: true
      x-mcp-key-types:
      - api
      parameters:
      - name: provider
        in: path
        required: true
        description: Provider slug, for example `openrouter`.
        schema:
          type: string
      - name: expand[]
        in: query
        required: false
        description: 'Fields to include. One or more of: list_rates.'
        schema:
          type: array
          items:
            type: string
            enum:
            - list_rates
        style: form
        explode: true
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NegotiatedPricing'
              examples:
                negotiated:
                  summary: negotiated
                  value:
                    object: negotiated_pricing
                    provider: openrouter
                    rates:
                    - sku: gpt-4o
                      unit: input_tokens
                      nano_usd_per_unit: 2000
                    plan: null
                    updated_at: '2026-10-01T09:30:00.000Z'
        '400':
          description: 'Error. Codes: invalid_parameter, unknown_parameter, missing_parameter.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '401':
          description: 'Error. Codes: missing_credentials, invalid_api_key, session_expired.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '403':
          description: 'Error. Codes: key_type_not_allowed, session_required, csrf_check_failed.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '404':
          description: 'Error. Codes: provider_not_found.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '429':
          description: 'Error. Codes: rate_limit_exceeded.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
        '500':
          description: 'Error. Codes: internal_error.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
      x-argus-examples:
      - name: negotiated
        request:
          method: GET
          path: /v1/negotiated_pricing/openrouter
        status: 200
    delete:
      operationId: negotiated_pricing_delete
      tags:
      - Negotiated pricing
      summary: Reset to list pricing
      description: 'Remove every negotiated rate and the negotiated plan for a provider, or with `sku` and `unit` just that one rate (the plan stays). Session only: an API key is refused with `session_required`. A project with nothing negotiated, or no rate for that `sku` and `unit`, gets a 404.'
      security:
      - sessionCookie: []
      x-access: session
      parameters:
      - name: provider
        in: path
        required: true
        description: Provider slug, for example `openrouter`.
        schema:
          type: string
      - name: sku
        in: query
        required: false
        description: Reset only this rate; needs `unit`.
        schema:
          $ref: '#/components/schemas/NonEmptyString'
      - name: unit
        in: query
        required: false
        description: The unit of the rate to reset; needs `sku`.
        schema:
          $ref: '#/components/schemas/NonEmptyString'
      responses:
        '204':
          description: Success. No content.
        '400':
          description: 'Error. Codes: invalid_parameter, unknown_parameter.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '403':
          description: 'Error. Codes: session_required.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                api key refused:
                  summary: api key refused
                  value:
                    error:
                      type: permission_error
                      code: session_required
                      message: This action needs a signed-in session in the Argus app. API keys cannot perform it.
                      param: null
                      doc_url: https://argus.town/docs/errors#session_required
                      next_step:
                        hint: Do this from the Argus app, signed in as a member of the project.
                        href: https://argus.town/settings
                      request_id: null
        '404':
          description: 'Error. Codes: provider_not_found, negotiated_pricing_not_found.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
        '429':
          description: 'Error. Codes: rate_limit_exceeded.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
        '500':
          description: 'Error. Codes: internal_error.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples: {}
      x-argus-examples:
      - name: api key refused
        request:
          method: DELETE
          path: /v1/negotiated_pricing/openrouter
        status: 403
        credential: api_key
      - name: reset
        request:
          method: DELETE
          path: /v1/negotiated_pricing/openrouter
        status: 204
components:
  schemas:
    NextStep:
      type: object
      required:
      - hint
      properties:
        hint:
          type: string
        method:
          type: string
        href:
          type: string
      additionalProperties: true
    NegotiatedPricing:
      type: object
      required:
      - object
      - provider
      - rates
      - plan
      - updated_at
      properties:
        object:
          type: string
          enum:
          - negotiated_pricing
        provider:
          type: string
        rates:
          type: array
          items:
            $ref: '#/components/schemas/NegotiatedRate'
        plan:
          anyOf:
          - $ref: '#/components/schemas/NegotiatedPlan'
          - type: 'null'
        updated_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
        list_rates:
          type: array
          items:
            $ref: '#/components/schemas/ListRate'
          description: Argus's list rate for each `sku` and `unit` the provider is priced by, so you can see what a negotiated rate replaces. Present only with `expand[]=list_rates`.
      additionalProperties: true
    ListRate:
      type: object
      required:
      - sku
      - unit
      - nano_usd_per_unit
      - source
      properties:
        sku:
          type: string
          description: a string at most 120 character(s) long
          title: maxLength(120)
          minLength: 1
          maxLength: 120
        unit:
          type: string
          description: a string at most 60 character(s) long
          title: maxLength(60)
          minLength: 1
          maxLength: 60
        nano_usd_per_unit:
          type: integer
          description: a number between 0 and 1000000000000
          title: between(0, 1000000000000)
          minimum: 0
          maximum: 1000000000000
        source:
          type: string
      additionalProperties: true
    NegotiatedPlan:
      type: object
      required:
      - price_usd_micros
      - included_amount
      - included_meter_id
      - overage_nano_usd_per_unit
      properties:
        price_usd_micros:
          anyOf:
          - type: integer
            description: a number between 0 and 1000000000000
            title: between(0, 1000000000000)
            minimum: 0
            maximum: 1000000000000
          - type: 'null'
        included_amount:
          anyOf:
          - type: integer
            description: a number between 0 and 1000000000000000
            title: between(0, 1000000000000000)
            minimum: 0
            maximum: 1000000000000000
          - type: 'null'
        included_meter_id:
          anyOf:
          - type: string
            description: a string at most 120 character(s) long
            title: maxLength(120)
            minLength: 1
            maxLength: 120
          - type: 'null'
        overage_nano_usd_per_unit:
          anyOf:
          - type: integer
            description: a number between 0 and 1000000000000
            title: between(0, 1000000000000)
            minimum: 0
            maximum: 1000000000000
          - type: 'null'
      additionalProperties: true
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - type
          - code
          - message
          - param
          - doc_url
          - request_id
          properties:
            type:
              type: string
              enum:
              - invalid_request
              - authentication_error
              - permission_error
              - not_found
              - conflict
              - rate_limited
              - plan_limit
              - upstream_error
              - api_error
            code:
              type: string
              enum:
              - unknown_parameter
              - invalid_parameter
              - invalid_cursor
              - method_not_allowed
              - missing_credentials
              - invalid_api_key
              - invalid_request_body
              - missing_parameter
              - invalid_idempotency_key
              - payload_too_large
              - too_many_events
              - no_valid_events
              - missing_source_credentials
              - invalid_source_credentials
              - timestamp_stale
              - idempotency_key_reused
              - idempotency_key_in_progress
              - too_many_auth_failures
              - origin_not_allowed
              - key_type_not_allowed
              - not_found
              - provider_not_found
              - connection_not_found
              - sync_not_found
              - connect_link_not_found
              - alert_rule_not_found
              - negotiated_pricing_not_found
              - provider_not_connectable
              - credential_invalid
              - provider_unreachable
              - label_conflict
              - connection_not_pollable
              - quota_exceeded
              - session_required
              - session_expired
              - csrf_check_failed
              - rate_limit_exceeded
              - internal_error
            message:
              type: string
            param:
              anyOf:
              - type: string
              - type: 'null'
            doc_url:
              type: string
            next_step:
              $ref: '#/components/schemas/NextStep'
            details:
              type: object
              required: []
              properties: {}
              additionalProperties:
                $id: /schemas/unknown
                title: unknown
            request_id:
              anyOf:
              - type: string
              - type: 'null'
          additionalProperties: true
      additionalProperties: true
    NegotiatedPricingBody:
      type: object
      required: []
      properties:
        rates:
          type: array
          items:
            $ref: '#/components/schemas/NegotiatedRate'
          description: Rates to set, one per `sku` and `unit`; rates already set and not listed are kept. One bad entry rejects the whole request.
          title: maxItems(100)
          minItems: 1
          maxItems: 100
        plan:
          $ref: '#/components/schemas/NegotiatedPlanInput'
      additionalProperties: true
    NegotiatedPlanInput:
      type: object
      required: []
      properties:
        price_usd_micros:
          type: integer
          description: a number between 0 and 1000000000000
          title: between(0, 1000000000000)
          minimum: 0
          maximum: 1000000000000
        included_amount:
          type: integer
          description: a number between 0 and 1000000000000000
          title: between(0, 1000000000000000)
          minimum: 0
          maximum: 1000000000000000
        included_meter_id:
          type: string
          description: a string at most 120 character(s) long
          title: maxLength(120)
          minLength: 1
          maxLength: 120
        overage_nano_usd_per_unit:
          type: integer
          description: a number between 0 and 1000000000000
          title: between(0, 1000000000000)
          minimum: 0
          maximum: 1000000000000
      additionalProperties: true
      description: The negotiated subscription. Fields you omit are cleared.
    NegotiatedRate:
      type: object
      required:
      - sku
      - unit
      - nano_usd_per_unit
      properties:
        sku:
          type: string
          description: a string at most 120 character(s) long
          title: maxLength(120)
          minLength: 1
          maxLength: 120
        unit:
          type: string
          description: a string at most 60 character(s) long
          title: maxLength(60)
          minLength: 1
          maxLength: 60
        nano_usd_per_unit:
          type: integer
          description: a number between 0 and 1000000000000
          title: between(0, 1000000000000)
          minimum: 0
          maximum: 1000000000000
      additionalProperties: true
    NonEmptyString:
      type: string
      description: a non empty string
      title: nonEmptyString
      minLength: 1
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An `api` key.
    sessionCookie:
      type: apiKey
      in: cookie
      name: argus_session
      description: The signed-in web app session. Operations that need it refuse every API key with `session_required`.
    sourceSecret:
      type: http
      scheme: bearer
      description: 'A source secret (`argus_src_...`), sent with the `Argus-Source` header. Write-only: it can send events and read nothing.'
    sourceSignature:
      type: apiKey
      in: header
      name: X-Argus-Signature
      description: Hex HMAC-SHA256 of the timestamp, a dot and the raw body, keyed with the source secret, sent with `X-Argus-Source` and `X-Argus-Timestamp` (epoch ms, within 5 minutes).
x-error-codes:
  unknown_parameter:
    type: invalid_request
    status: 400
    description: The request has a query parameter this endpoint does not accept.
  invalid_parameter:
    type: invalid_request
    status: 400
    description: A parameter has a value this endpoint cannot use. `param` names it.
  invalid_cursor:
    type: invalid_request
    status: 400
    description: The cursor is malformed or does not belong to this list. Start again without it.
  method_not_allowed:
    type: invalid_request
    status: 405
    description: The path exists but not for this HTTP method. The Allow header lists the methods.
  missing_credentials:
    type: authentication_error
    status: 401
    description: No Authorization header was sent.
  invalid_api_key:
    type: authentication_error
    status: 401
    description: The key is unknown, revoked, or not an API key.
  invalid_request_body:
    type: invalid_request
    status: 400
    description: The body is not a JSON object (or, on `/v1/events`, not an event or an `events` array), or it is empty where fields are required.
  missing_parameter:
    type: invalid_request
    status: 400
    description: A required body field or header is missing. `param` names it.
  invalid_idempotency_key:
    type: invalid_request
    status: 400
    description: The Idempotency-Key header must be 1 to 255 printable ASCII characters.
  payload_too_large:
    type: invalid_request
    status: 413
    description: The body is over 1,000,000 bytes. Split the batch.
  too_many_events:
    type: invalid_request
    status: 413
    description: A batch holds at most 1,000 events. Split it.
  no_valid_events:
    type: invalid_request
    status: 422
    description: Every event in the batch was rejected, so nothing was queued. Send the same body to `POST /v1/events/validate` for each event's reason.
  missing_source_credentials:
    type: authentication_error
    status: 401
    description: 'No source credential was sent. Use `Authorization: Bearer <source secret>` with `Argus-Source: <source id>`, or the HMAC headers `X-Argus-Source`, `X-Argus-Timestamp` and `X-Argus-Signature`.'
  invalid_source_credentials:
    type: authentication_error
    status: 401
    description: The source is unknown or revoked, or the bearer secret or HMAC signature is wrong (sign the timestamp, a dot and the raw body, hex HMAC-SHA256). The cases are not distinguished.
  timestamp_stale:
    type: authentication_error
    status: 401
    description: The signed timestamp (epoch milliseconds) is more than 5 minutes from server time.
  idempotency_key_reused:
    type: conflict
    status: 409
    description: This Idempotency-Key was already used with a different request body or source. Use a new key for a new request.
  idempotency_key_in_progress:
    type: conflict
    status: 409
    description: A request with this Idempotency-Key is still running. Retry with the same key after a moment; it replays the response once the first request finishes.
  too_many_auth_failures:
    type: rate_limited
    status: 429
    description: Too many failed authentication attempts from this address. Wait `Retry-After` seconds. Valid credentials keep working from an address over budget, except that a credential the server has not seen recently gets only a small number of lookups per window, tracked per server instance; a client sharing an address with an attacker can be briefly locked out.
  origin_not_allowed:
    type: permission_error
    status: 403
    description: A browser Origin that is not allow-listed called the MCP server. Non-browser clients send no Origin.
  key_type_not_allowed:
    type: permission_error
    status: 403
    description: This key's type cannot call this endpoint.
  not_found:
    type: not_found
    status: 404
    description: No such endpoint.
  provider_not_found:
    type: not_found
    status: 404
    description: No provider has this slug.
  connection_not_found:
    type: not_found
    status: 404
    description: No connection with this id in the key's project. When a request body names the connection (`param` says where) the status is 422.
  sync_not_found:
    type: not_found
    status: 404
    description: No sync with this id in the key's project.
  connect_link_not_found:
    type: not_found
    status: 404
    description: No connect link with this id in the key's project.
  alert_rule_not_found:
    type: not_found
    status: 404
    description: No alert rule with this id in the key's project.
  negotiated_pricing_not_found:
    type: not_found
    status: 404
    description: The project has no negotiated pricing for this provider.
  provider_not_connectable:
    type: invalid_request
    status: 422
    description: The provider is unknown or Argus cannot poll it with a credential (telemetry only).
  credential_invalid:
    type: invalid_request
    status: 422
    description: The provider rejected the credential. `message` carries the provider's reason; the credential is never echoed.
  provider_unreachable:
    type: upstream_error
    status: 502
    description: Argus could not reach the provider to check the credential. Retry.
  label_conflict:
    type: conflict
    status: 409
    description: Another connection to this provider already has this label. Update that connection instead, or choose another label.
  connection_not_pollable:
    type: conflict
    status: 409
    description: The connection has no credential to poll with (telemetry only) or is suspended, so there is nothing to sync.
  quota_exceeded:
    type: plan_limit
    status: 409
    description: The project reached a limit on this kind of resource. `details` holds `resource`, `limit` and `used`.
  session_required:
    type: permission_error
    status: 403
    description: This operation needs a signed-in session in the Argus app; API keys cannot perform it.
  session_expired:
    type: authentication_error
    status: 401
    description: The web app's session is missing, expired or signed out. Only the signed-in web app sees it.
  csrf_check_failed:
    type: permission_error
    status: 403
    description: 'A web-app write did not come from the app itself: it lacks `x-argus-csrf`, or its `Origin` or `Sec-Fetch-Site` is not the app''s. API keys never see it.'
  rate_limit_exceeded:
    type: rate_limited
    status: 429
    description: The key exceeded its request budget. Wait `Retry-After` seconds.
  internal_error:
    type: api_error
    status: 500
    description: Something failed on our side. Retry; quote `request_id` if it persists.