---
title: "Create an order"
method: POST
path: "/api/v1/orders"
tags: ["Orders"]
---

# Create an order

`POST /api/v1/orders`

## Request

- Base URL: `https://hproxy.com`
- URL: `https://hproxy.com/api/v1/orders`
- Auth: API key in header `X-API-Key`

Buy a product. By default this is a wallet prepay: it debits your balance and returns immediately, or fails with `402` if the balance is short (it never silently charges a card you didn't pick). Set `method` to `"card"` or `"crypto"` to get a hosted `payUrl` back instead. Always send an `Idempotency-Key` so a retry never double-charges; on a reseller key an order without one is refused.

The body takes **only the five fields below**. Anything else, including a top-level `country`, is refused with `400 unknown_field` before anything is charged. What goes in it depends on the product's `delivery` on [GET /products](/docs/proxy-api/products).

**Residential and other gateway products** (`delivery` is `lines`): send `product_id` and `quantity`, nothing else. There is no country in the order. You choose the country for each line when you [generate lines](/docs/proxy-api/plans#generate) from the plan, so one plan serves every country. A package size is the `quantity` (1 GB is `1`, 10 GB is `10`), never a separate product id, and it is a whole number from the product's `minQuantity`.

**Dedicated IPs** (`delivery` is `addresses`: IPv4, IPv6, ISP and mobile IPs): `quantity` counts IPs, and the targeting goes inside `fulfillment_meta`, for example `{"country": "DEU", "period_days": 30}`.

## Request body

- object
  - `product_id` string, required: A product id from GET /products, e.g. "residential-lite".
  - `quantity` integer, required: A whole number; a fraction is refused. GB for residential and other per-GB products, or number of IPs for dedicated products, between the product's `minQuantity` and `maxQuantity`. For renewals: the number of ids.
  - `method` string: "wallet" (default), "card" or "crypto". card/crypto return a payUrl.
  - `fulfillment_meta` object: Dedicated IPs: country (alpha-3, e.g. "DEU"), period_days, and operator_id on mobile. For a RENEWAL of dedicated proxies: {"kind": "extension", "ids": ["…"], "period_days": 30} (ids from GET /proxies, ownership-checked server-side). Leave it out for residential and other per-GB products: you choose their country per line at POST /plans/{id}/generate.
  - `expected_amount_cents` integer: The total you showed the buyer (the `amountCents` of your quote). If the price moved in between, the order is refused with `409 price_changed` carrying the new `amountCents`, and nothing is charged. Omit it to be charged the price at the moment of the order.

## Response `200`

Success

- object

## Other responses

- `400`: Invalid input. The body names the field and the accepted set.
- `401`: Missing or invalid API key.
- `429`: Rate limited. Retry after the delay in the response.

---

[API](https://skmtc.dev/hproxy/apis/hproxy-api.md) · [All operations](https://skmtc.dev/hproxy/apis/hproxy-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hproxy/apis/hproxy-api/revisions/9f6898fe76e2?raw)
