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

# Buy residential data

> Buy whole GB of residential IP data from your Orgo credits, at $3 per GB. Retries with the same Idempotency-Key never buy twice.

Buys residential data from the account's Orgo credits, at \$3 per GB. It is the only call that spends on residential data: turning a computer's residential IP on never buys. Data is added at once, isn't refunded once added, and doesn't expire while your account exists. See [Residential IP](https://docs.orgo.ai/guides/browser-networking.md#residential-ip).

> [!WARNING]
>
> This spends credits. An agent should ask its person first.

Read the price with [Get residential data](https://docs.orgo.ai/api-reference/account/residential-data.md), then send it as `expected_price_cents`. If the price has moved, the answer is `409` with code `PRICE_CHANGED` and the new `price_cents`, and nothing is spent.

```bash theme={null}
curl -X POST https://www.orgo.ai/api/billing/residential-data/buy \
  -H "Authorization: Bearer $ORGO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"gb": 1, "expected_price_cents": 300}'
```

## Who can buy

The data belongs to the workspace owner, and every computer in the owner's workspaces draws on it. Buy with the owner's sign-in, or a key for the whole account with full access or Billing write.

* The account needs a paid plan or credit it bought (`403` `PLAN_REQUIRED`), and a Linux computer outside Bops (`403` `RESIDENTIAL_NO_COMPUTER`).
* A key for one workspace or one computer answers `403` `ACCOUNT_KEY_REQUIRED`. An MCP sign-in answers `403` `RESIDENTIAL_BUY_NEEDS_BILLING`. A share-link guest answers `403` `GUEST_RESTRICTED`.
* `desktop_id` is optional. When sent, only that computer's workspace owner may buy: anyone else gets `403` `ACCOUNT_OWNER_REQUIRED`.
* When the credits don't cover it, the answer is `402` `INSUFFICIENT_CREDITS` with `price_cents` and `available_cents`, and nothing is spent.

## Retries never buy twice

Send a new UUID as `Idempotency-Key` for each purchase. A retry with the same key answers what the first call came to, whatever has changed since:

| Answer | Meaning |
| - | - |
| `200` | Added and charged. `purchase.status` is `added`. |
| `202` `RESIDENTIAL_PURCHASE_PENDING` | The network hasn't confirmed it yet. The credits are held, not spent. Retry with the same key, or read it in [Get residential data](https://docs.orgo.ai/api-reference/account/residential-data.md). |
| `503` `RESIDENTIAL_DATA_UNAVAILABLE` | Not added and not charged. |
| `500` | The purchase couldn't be read. Retry with the same key, never a new one. |

`409` `RESIDENTIAL_PURCHASE_IN_PROGRESS` means another purchase for the account is still finishing. Try again in a minute.

## Auto-buy

Auto-buy buys 1 GB when the account's data falls under 0.25 GB, up to a monthly limit, after the month's included data is used. It starts after the account's first purchase by hand, which accepts the Residential IPs terms: until then `terms_accepted` is false and auto-buy buys nothing. Only a person signed in to Orgo turns it on, in **Settings → Plan & billing**. No key can.


## OpenAPI

````yaml POST /billing/residential-data/buy
openapi: 3.1.0
info:
  title: Orgo API
  description: >-
    Launch cloud computers that AI agents can control and interact with. Create
    workspaces, provision computers, and control them programmatically.
  version: 2.0.0
  contact:
    name: Orgo Support
    email: contact@orgo.ai
    url: https://orgo.ai
servers:
  - url: https://www.orgo.ai/api
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Support
    description: >-
      Orgo’s support agent, for programs: ask how to do something in Orgo and
      get an answer with full URLs and copyable commands.
  - name: Account
    description: >-
      Account capacity: how many computers an account may run, and adding or
      giving back more. Residential data: what the account has left for
      residential IPs, and buying more from credits.
  - name: Agent accounts
    description: >-
      Accounts an AI agent makes for itself, and the claim link a person uses to
      take one over.
  - name: Clients
    description: >-
      Run Orgo for your clients from your own app: a workspace and scoped key
      each, billed to you or to them.
  - name: Workspaces
    description: Organize computers into named workspaces
  - name: Computers
    description: Provision and manage virtual computers
  - name: Public URLs
    description: Share an app running on a computer at an https address on orgo.dev.
  - name: Computer Lifecycle
    description: Start, stop, and restart computers
  - name: Computer Actions
    description: Control mouse, keyboard, and execute commands
  - name: Screens
    description: >-
      More than one desktop on a single computer. Each screen is its own X
      server with its own cursor and window manager, so an agent working on one
      cannot disturb another.
  - name: Files
    description: Upload and download files
  - name: Templates
    description: Author, build, and launch reproducible computers from templates
  - name: Chat
    description: Run an agent on a computer through OpenAI-compatible chat completions.
  - name: Workflows
    description: >-
      Routines that run the same way every time: a start, then steps. Make them
      from plain words or lines, check them, run them and follow their runs (in
      preview).
paths:
  /billing/residential-data/buy:
    post:
      tags:
        - Account
      summary: Buy residential data
      description: >-
        Spends the account’s Orgo credits, the only call that does: turning a
        computer on never buys. Ask your human first. The workspace owner’s data
        is what that workspace’s computers use, and it counts down across all of
        them. Data isn’t refunded once added. Some sites can’t be reached this
        way.


        A session, or a key with full access or Billing write that covers the
        whole account. Send the price of 1 GB you read from `GET
        /api/billing/residential-data` as `expected_price_cents`; if it has
        moved the answer is `409` `PRICE_CHANGED` and nothing is spent. A retry
        with the same `Idempotency-Key` answers what the first call came to,
        whatever has changed since: `200` added, `202` still open with the
        credits held, `503` not added and not charged.
      operationId: buyResidentialData
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          description: >-
            A new UUID for each purchase (8 to 255 printable characters). A
            retry with it never buys twice.
          schema:
            type: string
            minLength: 8
            maxLength: 255
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - gb
                - expected_price_cents
              properties:
                gb:
                  type: integer
                  minimum: 1
                  description: >-
                    Whole GB to buy. One purchase has a most; past it the answer
                    is `400` `invalid_gb`, and its `error` names the range.
                expected_price_cents:
                  type: integer
                  description: >-
                    The price of 1 GB you agreed to, in cents, as `price_cents`
                    in `GET /api/billing/residential-data` read it.
                desktop_id:
                  type: string
                  format: uuid
                  description: >-
                    Optional. The computer this is for. Only its workspace owner
                    may buy for it: anyone else gets `403`
                    `ACCOUNT_OWNER_REQUIRED`.
            example:
              gb: 1
              expected_price_cents: 300
      responses:
        '200':
          description: Added and charged.
          content:
            application/json:
              schema:
                type: object
                required:
                  - purchase
                properties:
                  purchase:
                    $ref: '#/components/schemas/ResidentialDataPurchase'
              example:
                purchase:
                  id: 5f0c2b8e-3a1d-4c7e-9b2f-8d6a4e1c0b93
                  gb: 1
                  price_cents: 300
                  status: added
                  auto: false
                  created_at: '2026-11-10T14:07:12.000Z'
        '202':
          description: >-
            The network hasn’t confirmed it yet
            (`RESIDENTIAL_PURCHASE_PENDING`). The credits are held, not spent.
            Retry with the same key, or read it in `GET
            /api/billing/residential-data`.
          content:
            application/json:
              schema:
                type: object
                required:
                  - code
                  - message
                  - purchase
                properties:
                  code:
                    type: string
                    enum:
                      - RESIDENTIAL_PURCHASE_PENDING
                  message:
                    type: string
                  purchase:
                    $ref: '#/components/schemas/ResidentialDataPurchase'
                  retryable:
                    type: boolean
                  next:
                    type: object
                    description: The call that fixes it.
                    required:
                      - method
                      - url
                      - why
                    properties:
                      method:
                        type: string
                        enum:
                          - GET
                          - POST
                      url:
                        type: string
                        format: uri
                      body:
                        type: object
                        description: What to send, when the call needs a body.
                      why:
                        type: string
                        description: >-
                          What the call does, for an agent deciding whether to
                          make it.
                  docs_url:
                    type: string
                    format: uri
              example:
                code: RESIDENTIAL_PURCHASE_PENDING
                message: >-
                  The network hasn't confirmed it yet. Your credits are held,
                  not spent. It shows here once it does.
                purchase:
                  id: 5f0c2b8e-3a1d-4c7e-9b2f-8d6a4e1c0b93
                  gb: 1
                  price_cents: 300
                  status: pending
                  auto: false
                  created_at: '2026-11-10T14:07:12.000Z'
                retryable: true
                next:
                  method: GET
                  url: https://www.orgo.ai/api/billing/residential-data
                  why: Read whether the purchase has landed.
                docs_url: https://www.orgo.ai/orgo.md
        '400':
          description: >-
            No `Idempotency-Key` (`idempotency_key_required`), a bad one
            (`invalid_idempotency_key`), or `gb` out of range (`invalid_gb`).
            Nothing was spent.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                no-key:
                  summary: No Idempotency-Key
                  value:
                    error: >-
                      Send an Idempotency-Key header, so a retry can never buy
                      twice.
                    code: idempotency_key_required
                bad-key:
                  summary: Bad Idempotency-Key
                  value:
                    error: >-
                      Idempotency-Key must be 8 to 255 printable characters,
                      such as a UUID.
                    code: invalid_idempotency_key
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          description: >-
            The credits don’t cover it (`INSUFFICIENT_CREDITS`), with
            `price_cents` and `available_cents`. Nothing was spent. It also
            carries `retryable`, `docs_url`, `next` (the call that adds credit)
            and `add_credit_url`.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                  - code
                properties:
                  error:
                    type: string
                  code:
                    type: string
                    enum:
                      - INSUFFICIENT_CREDITS
                  retryable:
                    type: boolean
                    description: Whether the same request may work later as it is.
                  next:
                    type: object
                    description: The call that fixes it.
                    required:
                      - method
                      - url
                      - why
                    properties:
                      method:
                        type: string
                        enum:
                          - GET
                          - POST
                      url:
                        type: string
                        format: uri
                      body:
                        type: object
                        description: What to send, when the call needs a body.
                      why:
                        type: string
                        description: >-
                          What the call does, for an agent deciding whether to
                          make it.
                  docs_url:
                    type: string
                    format: uri
                  price_cents:
                    type: integer
                    description: What the purchase costs, in cents.
                  available_cents:
                    type: integer
                    description: The account’s credits, in cents.
                  add_credit_url:
                    type: string
                    format: uri
                    description: The page a person opens to add credit.
              example:
                error: >-
                  1 GB is $3.00 and your credits cover $1.20. Add credits, then
                  buy again.
                code: INSUFFICIENT_CREDITS
                price_cents: 300
                available_cents: 120
                retryable: false
                next:
                  method: POST
                  url: https://www.orgo.ai/api/credits/checkout
                  body:
                    amount_cents: 1000
                  why: Get a Checkout link for your human to pay, then retry.
                docs_url: https://www.orgo.ai/orgo.md
                add_credit_url: https://www.orgo.ai/settings/billing#credits
        '403':
          description: >-
            Nothing was spent. Not a paying account (`PLAN_REQUIRED`: it needs a
            paid plan or credit it bought). No Linux computer outside Bops
            (`RESIDENTIAL_NO_COMPUTER`). A key for a workspace or a computer
            (`ACCOUNT_KEY_REQUIRED`). An MCP sign-in, or a key without Billing
            write (`RESIDENTIAL_BUY_NEEDS_BILLING`, or `key_permission` from the
            key check). A computer of someone else’s workspace in `desktop_id`
            (`ACCOUNT_OWNER_REQUIRED`). An unclaimed agent account
            (`agent_account_unclaimed`). A share-link guest
            (`GUEST_RESTRICTED`). Each but `key_permission`,
            `agent_account_unclaimed` and `GUEST_RESTRICTED` also carries
            `retryable` and `docs_url`, and most carry `next`.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                  - code
                properties:
                  error:
                    type: string
                  code:
                    type: string
                    enum:
                      - PLAN_REQUIRED
                      - RESIDENTIAL_NO_COMPUTER
                      - ACCOUNT_KEY_REQUIRED
                      - RESIDENTIAL_BUY_NEEDS_BILLING
                      - ACCOUNT_OWNER_REQUIRED
                      - agent_account_unclaimed
                      - key_permission
                      - GUEST_RESTRICTED
                  retryable:
                    type: boolean
                    description: Whether the same request may work later as it is.
                  next:
                    type: object
                    description: The call that fixes it.
                    required:
                      - method
                      - url
                      - why
                    properties:
                      method:
                        type: string
                        enum:
                          - GET
                          - POST
                      url:
                        type: string
                        format: uri
                      body:
                        type: object
                        description: What to send, when the call needs a body.
                      why:
                        type: string
                        description: >-
                          What the call does, for an agent deciding whether to
                          make it.
                  docs_url:
                    type: string
                    format: uri
              examples:
                plan-required:
                  summary: Not a paying account
                  value:
                    error: >-
                      Residential IPs are for paying accounts. Pick a plan or
                      add credit first.
                    code: PLAN_REQUIRED
                    retryable: false
                    next:
                      method: GET
                      url: https://www.orgo.ai/pricing.md
                      why: See which plan includes this.
                    docs_url: https://www.orgo.ai/pricing.md
                no-computer:
                  summary: No Linux computer
                  value:
                    error: Residential data works on Linux computers. Add one first.
                    code: RESIDENTIAL_NO_COMPUTER
                    retryable: false
                    next:
                      method: POST
                      url: https://www.orgo.ai/api/computers
                      why: Add a Linux computer, then buy again.
                    docs_url: https://www.orgo.ai/orgo.md
                account-key:
                  summary: A key for a workspace or a computer
                  value:
                    error: Buy data with your own sign-in or account key.
                    code: ACCOUNT_KEY_REQUIRED
                    retryable: false
                    next:
                      method: GET
                      url: https://www.orgo.ai/auth.md
                      why: Use your own sign-in or an account key, then retry.
                    docs_url: https://www.orgo.ai/auth.md
                needs-billing:
                  summary: MCP sign-in or a key without Billing write
                  value:
                    error: >-
                      Buying data spends your credits. Use a key with Billing
                      write access, or Orgo itself.
                    code: RESIDENTIAL_BUY_NEEDS_BILLING
                    retryable: false
                    next:
                      method: GET
                      url: https://www.orgo.ai/auth.md
                      why: >-
                        Ask your human for an API key with Billing write access,
                        then retry with it.
                    docs_url: https://www.orgo.ai/auth.md
                not-owner:
                  summary: Someone else’s computer
                  value:
                    error: Only the workspace owner can buy data for this computer.
                    code: ACCOUNT_OWNER_REQUIRED
                    retryable: false
                    docs_url: https://www.orgo.ai/orgo.md
                guest:
                  summary: A share-link guest
                  value:
                    error: Sign up to create your own workspace.
                    code: GUEST_RESTRICTED
        '409':
          description: >-
            Nothing was spent. The price moved (`PRICE_CHANGED`, with
            `price_cents`, the price of 1 GB now): read it, then buy again with
            it. Or a purchase for this account is still finishing
            (`RESIDENTIAL_PURCHASE_IN_PROGRESS`): try again in a minute.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                  - code
                properties:
                  error:
                    type: string
                  code:
                    type: string
                    enum:
                      - PRICE_CHANGED
                      - RESIDENTIAL_PURCHASE_IN_PROGRESS
                  retryable:
                    type: boolean
                    description: Whether the same request may work later as it is.
                  next:
                    type: object
                    description: The call that fixes it.
                    required:
                      - method
                      - url
                      - why
                    properties:
                      method:
                        type: string
                        enum:
                          - GET
                          - POST
                      url:
                        type: string
                        format: uri
                      body:
                        type: object
                        description: What to send, when the call needs a body.
                      why:
                        type: string
                        description: >-
                          What the call does, for an agent deciding whether to
                          make it.
                  docs_url:
                    type: string
                    format: uri
                  price_cents:
                    type: integer
                    description: 'With `PRICE_CHANGED`: the price of 1 GB now, in cents.'
              examples:
                price-changed:
                  summary: The price moved
                  value:
                    error: The price is now $3.00. Check it, then buy again.
                    code: PRICE_CHANGED
                    price_cents: 300
                    retryable: false
                    next:
                      method: GET
                      url: https://www.orgo.ai/api/billing/residential-data
                      why: Read the price, then buy again with it.
                    docs_url: https://www.orgo.ai/orgo.md
                in-progress:
                  summary: A purchase is still finishing
                  value:
                    error: >-
                      A purchase for this account is still finishing. Try again
                      in a minute.
                    code: RESIDENTIAL_PURCHASE_IN_PROGRESS
                    retryable: true
                    next:
                      method: GET
                      url: https://www.orgo.ai/api/billing/residential-data
                      why: Read whether the purchase has landed.
                    docs_url: https://www.orgo.ai/orgo.md
        '429':
          description: >-
            The account has made all the purchases it may today
            (`rate_limited`). `retry_after` and `Retry-After` say how many
            seconds to wait. Nothing was spent.
          headers:
            Retry-After:
              description: Seconds to wait.
              schema:
                type: integer
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                  - code
                  - retry_after
                properties:
                  error:
                    type: string
                  code:
                    type: string
                    enum:
                      - rate_limited
                  retry_after:
                    type: integer
                    description: Seconds to wait.
              example:
                error: >-
                  This account has bought all the data it can today. Try again
                  later.
                code: rate_limited
                retry_after: 3600
        '500':
          description: >-
            The purchase’s state couldn’t be read. It may have been charged:
            retry with the same `Idempotency-Key`, never a new one.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: >-
                  Could not read this purchase. Try again with the same
                  Idempotency-Key.
        '503':
          description: >-
            Data can’t be added right now (`RESIDENTIAL_DATA_UNAVAILABLE`). Not
            added and not charged. Try again later.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                  - code
                properties:
                  error:
                    type: string
                  code:
                    type: string
                    enum:
                      - RESIDENTIAL_DATA_UNAVAILABLE
                  retryable:
                    type: boolean
                    description: Whether the same request may work later as it is.
                  next:
                    type: object
                    description: The call that fixes it.
                    required:
                      - method
                      - url
                      - why
                    properties:
                      method:
                        type: string
                        enum:
                          - GET
                          - POST
                      url:
                        type: string
                        format: uri
                      body:
                        type: object
                        description: What to send, when the call needs a body.
                      why:
                        type: string
                        description: >-
                          What the call does, for an agent deciding whether to
                          make it.
                  docs_url:
                    type: string
                    format: uri
              example:
                error: >-
                  Residential data can't be added right now. You were not
                  charged.
                code: RESIDENTIAL_DATA_UNAVAILABLE
                retryable: true
                docs_url: https://www.orgo.ai/orgo.md
components:
  schemas:
    ResidentialDataPurchase:
      type: object
      required:
        - id
        - gb
        - price_cents
        - status
        - created_at
      properties:
        id:
          type: string
          format: uuid
        gb:
          type: integer
        price_cents:
          type: integer
          description: What it cost, in cents.
        status:
          type: string
          enum:
            - pending
            - added
            - returned
          description: >-
            `pending`: the credits are held, not spent. `added`: charged.
            `returned`: not added, and the credits went back.
        auto:
          type: boolean
          description: Bought by auto-buy, not by hand.
        created_at:
          type: string
          format: date-time
    Error:
      type: object
      description: >-
        The base error body. Every failure carries `error`; individual endpoints
        add the fields named in the schemas below.
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable message.
          example: Access denied
        code:
          type: string
          description: >-
            Machine-readable reason. Present on the failures that define one,
            absent otherwise.
  responses:
    Unauthorized:
      description: 'No usable credential. Send `Authorization: Bearer $ORGO_API_KEY`.'
      content:
        application/json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Error'
              - type: object
                properties:
                  docs:
                    type: string
                    format: uri
                    description: 'How to sign in: `https://www.orgo.ai/auth.md`.'
          examples:
            invalid-key:
              summary: The key is not one of yours
              value:
                error: Invalid API key
                docs: https://www.orgo.ai/auth.md
            no-credential:
              summary: No key and no session
              value:
                error: Authentication required
                docs: https://www.orgo.ai/auth.md
      headers:
        WWW-Authenticate:
          description: '`Bearer realm="Orgo API"`.'
          schema:
            type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key authentication. Get your key at orgo.ai/workspaces

````

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