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

# Say your side is ready to deal

> Stamps your company's side once; the other party is told when both have said so. A second press changes nothing and answers 200 with where both sides stand. Requires `introductions:write` and, by side, the `deal.invoice` (seller) or `deal.pay` (buyer) right — trader, authorized signatory or owner. `Idempotency-Key` is required; no body.




## OpenAPI

````yaml https://api.gpuoutlet.ai/v1/openapi.yaml post /introductions/{id}/ready
openapi: 3.1.0
info:
  title: GPU Outlet Partner API
  version: 2.0.0
  description: >
    Programmatic access to the GPU Outlet introduction marketplace: state what
    capacity your company needs, read the opportunities offered to you, follow
    the introductions you are party to, and consult Radar.


    **Authentication.** Every endpoint except this document requires
    `Authorization: Bearer gpk_…`. Mint a key in your dashboard under Settings →
    API keys. The key is shown once, at creation, and is not recoverable — we
    store only its hash.


    **Company context.** A key belongs to a person; the company and the role the
    call acts with are that person's company membership, exactly as in the
    dashboard. A key whose owner is in no company gets `company_required`; a
    role short of the action gets `forbidden_role`. Nothing in a request body
    can name a company.


    **Scopes.** Each endpoint names the scope it needs. A key carries the scopes
    it was minted with and cannot grow one later; a key without the required
    scope gets `insufficient_scope` with `required_scope` in the error.


    **Idempotency.** Every `POST`, `PUT` and `PATCH` under Requests,
    Opportunities and Introductions **requires** `Idempotency-Key`. Generate one
    per intent (a UUID is fine) and reuse it verbatim on every retry of that
    same request: you get the original response back, marked
    `Idempotency-Replayed: true`, and nothing is written twice. The same key
    with a different body is `idempotency_key_reused`; a key whose first attempt
    is still running is `idempotency_key_in_flight` with `Retry-After`. Keys are
    remembered for 24 hours. Radar writes accept the header and echo it but do
    not require it.


    **Rate limits.** Every response carries `RateLimit-Limit`,
    `RateLimit-Remaining` and `RateLimit-Reset`; a 429 adds `Retry-After`.
    Writes have a smaller bucket of their own on top. Limits are enforced per
    API server instance and are approximate — treat `RateLimit-Remaining` as
    advisory, and back off on 429 rather than predicting it.


    **Compatibility.** We may add endpoints, add response fields, add optional
    query parameters, and add values to response enums at any time. Your client
    **must ignore fields it does not recognise.** Removing or renaming a field,
    changing a type, or tightening validation requires a new major version.


    **UI only.** The steps with legal effect stay in the dashboard, behind a
    second factor a key cannot present: accepting an opportunity and revealing
    the buyer, existing-relationship claims, deal reports and receipts, deal and
    success-fee invoices, and signing agreements. This API reads what those
    steps produced; it does not perform them.


    **What we do not publish.** Before a reveal, an opportunity carries the
    buyer's demand and nothing about the buyer — no name, no country, no id.
    Internal identifiers of people are never on the wire. Do not build on
    inferring either.
servers:
  - url: https://api.gpuoutlet.ai/v1
security:
  - bearerAuth: []
tags:
  - name: Account
    description: Facts about the calling key.
  - name: Radar
    description: >
      Curated nodes of reserved capacity — what a signed-in buyer sees on the
      Radar page, and what a seller has proposed to it.
  - name: Requests
    description: >
      Your company's demand. A request is what the operator matches sellers
      against; sellers see an anonymised copy of it as an opportunity.
  - name: Opportunities
    description: >
      The seller's inbox — demand matched to your listing, anonymised until you
      accept it in the dashboard. Declining needs no second factor and is here.
  - name: Introductions
    description: >
      What both parties read after a reveal, and the one move either may make
      without a person present — "we are ready".
paths:
  /introductions/{id}/ready:
    post:
      tags:
        - Introductions
      summary: Say your side is ready to deal
      description: >
        Stamps your company's side once; the other party is told when both have
        said so. A second press changes nothing and answers 200 with where both
        sides stand. Requires `introductions:write` and, by side, the
        `deal.invoice` (seller) or `deal.pay` (buyer) right — trader, authorized
        signatory or owner. `Idempotency-Key` is required; no body.
      operationId: markIntroductionReady
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/IdempotencyKey'
      responses:
        '200':
          description: Your side was already stamped; nothing changed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Readiness'
        '201':
          description: Your side was stamped now
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Readiness'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: '`introduction_not_found`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >
            `introduction_not_active` — released, expired or closed (`current`
            says which); or an idempotency conflict.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 255
        pattern: ^[\x20-\x7E]+$
      description: >
        Unique per intent. Retries of the same intent must reuse it verbatim; a
        new intent needs a new one. Remembered for 24 hours.
  schemas:
    Readiness:
      type: object
      required:
        - sellerReadyAt
        - buyerReadyAt
      properties:
        sellerReadyAt:
          type:
            - string
            - 'null'
          format: date-time
        buyerReadyAt:
          type:
            - string
            - 'null'
          format: date-time
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
            - doc_url
            - request_id
          properties:
            type:
              type: string
              enum:
                - invalid_request_error
                - authentication_error
                - permission_error
                - rate_limit_error
                - api_error
            code:
              type: string
              description: Stable machine-readable code
            message:
              type: string
            param:
              type: string
              description: The offending parameter, when applicable
            doc_url:
              type: string
              format: uri
            request_id:
              type: string
              description: >-
                Quote this when contacting support — it locates the exact
                request
            required_scope:
              type: string
              description: 'On `insufficient_scope`: the scope this endpoint needs'
            retry_after_seconds:
              type: integer
              description: >-
                On a rate-limit error or `idempotency_key_in_flight`: seconds to
                wait
            current:
              type: string
              description: >
                On `request_not_editable`, `opportunity_not_pending` and
                `introduction_not_active`: the status the resource is in.
            problems:
              type: array
              items:
                type: string
              description: >-
                On `request_invalid`: every field at fault (`gpu_model`, `term`,
                …)
  responses:
    BadRequest:
      description: >-
        `invalid_request` — a parameter was invalid (`param` names it) — or
        `idempotency_key_required`
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing, malformed, unknown, revoked or expired key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: >
        The key is valid but not allowed to do this: `insufficient_scope` (with
        `required_scope`), `company_required`, `forbidden_role`,
        `api_keys_disabled`, or `banned`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Rate limit or daily quota spent
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'An API key from your dashboard, sent as `Authorization: Bearer gpk_…`.'

````

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