# Acme Store API

> Manage products, orders and customers of an Acme storefront.

The **Acme Store API** lets you manage products, orders and customers of an Acme storefront.

All requests are made over HTTPS and return JSON. Authenticate by sending a bearer token in the
`Authorization` header — see [Authentication](#authentication).

| Status | Meaning |
| --- | --- |
| `2xx` | Success |
| `4xx` | Client error, check the `error` field |
| `5xx` | Server error, please retry |

## Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

## Variables (Production)

| Name | Value |
| --- | --- |
| `base_url` | `https://api.acme.dev/v1` |
| `api_token` | `<redacted>` |
| `store_id` | `store_42` |

## Endpoints

- [Authentication](/reference/authentication.md): Obtain and refresh access tokens.
  - [Log in](/reference/authentication/log-in.md): Exchange user credentials for an access token.
  - [Refresh token](/reference/authentication/refresh-token.md): Get a new access token using a refresh token (OAuth 2 style form body).
- [Products](/reference/products.md): Products are the items sold in your store.
  - [List products](/reference/products/list-products.md): Returns a paginated list of products, newest first.
  - [Get a product](/reference/products/get-a-product.md): Retrieve a single product by its id.
  - [Create a product](/reference/products/create-a-product.md): Create a new product.
  - [Update a product](/reference/products/update-a-product.md): Partially update a product.
  - [Delete a product](/reference/products/delete-a-product.md): Permanently delete a product.
  - [Images](/reference/products/images.md): Upload and manage product images.
    - [Upload an image](/reference/products/images/upload-an-image.md): Upload a product image (PNG or JPEG, max 5 MB).
- [Catalog](/reference/catalog.md): Browse the product catalog by category.
  - [Categories](/reference/catalog/categories.md): Top-level product categories.
    - [List categories](/reference/catalog/categories/list-categories.md): Returns all top-level categories.
    - [Subcategories](/reference/catalog/categories/subcategories.md): Categories within a category.
      - [List subcategories](/reference/catalog/categories/subcategories/list-subcategories.md): Returns the subcategories of a category.
      - [Attributes](/reference/catalog/categories/subcategories/attributes.md): Filterable attributes of a subcategory (size, color, …).
        - [List attribute values](/reference/catalog/categories/subcategories/attributes/list-attribute-values.md): Returns the values of every filterable attribute in a subcategory.
- [Orders](/reference/orders.md): Orders placed by customers.
  - [List orders](/reference/orders/list-orders.md): List orders, optionally filtered by status.
  - [Create an order](/reference/orders/create-an-order.md): Place an order on behalf of a customer.
  - [Export orders (XML)](/reference/orders/export-orders-xml.md): Legacy XML export.
- [GraphQL](/reference/graphql.md): A GraphQL endpoint is available for flexible queries.
  - [Search products](/reference/graphql/search-products.md): Full-text product search with GraphQL.
- [Realtime](/reference/realtime.md): Streaming APIs over WebSockets and gRPC.
  - [Order updates](/reference/realtime/order-updates.md): Subscribe to real-time order events.
  - [Get stock level](/reference/realtime/get-stock-level.md): Query live inventory via gRPC.
- [Health check](/reference/health-check.md): Returns ok when the API is up.

---

## Authentication

Obtain and refresh access tokens. These endpoints don't require authentication.

---

### Log in

Section: Authentication

```
POST https://api.acme.dev/v1/auth/login
```

Exchange user credentials for an access token.

The token expires after **1 hour**; use [Refresh token](#authentication-refresh-token) to get a new one.

#### Authentication

None

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |
| `Content-Type` | `application/json` |

#### Body

Content type: `application/json`

```json
{
  "email": "jane@acme.dev",
  "password": "{{password}}",
  "remember": true
}
```

#### Example responses

##### 200 OK

```json
{
  "accessToken": "eyJhbGciOi...",
  "refreshToken": "rt_8f2k...",
  "expiresIn": 3600
}
```

##### 401 Unauthorized

```json
{
  "error": "invalid_credentials",
  "message": "Email or password is incorrect."
}
```

#### Examples

##### cURL

```bash
curl -X POST https://api.acme.dev/v1/auth/login \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "email": "jane@acme.dev",
  "password": "{{password}}",
  "remember": true
}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/auth/login", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "email": "jane@acme.dev",
    "password": "{{password}}",
    "remember": true
  }),
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/auth/login"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
}
payload = {
    "email": "jane@acme.dev",
    "password": "{{password}}",
    "remember": True,
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "email": "jane@acme.dev",
  "password": "{{password}}",
  "remember": true
}`)

	req, err := http.NewRequest("POST", "https://api.acme.dev/v1/auth/login", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Refresh token

Section: Authentication

```
POST https://api.acme.dev/v1/auth/token
```

Get a new access token using a refresh token (OAuth 2 style form body).

#### Authentication

None

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Body

Content type: `application/x-www-form-urlencoded`

| Field | Value |
| --- | --- |
| `grant_type` | `refresh_token` |
| `refresh_token` | `{{refresh_token}}` |

#### Examples

##### cURL

```bash
curl -X POST https://api.acme.dev/v1/auth/token \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode grant_type=refresh_token \
  --data-urlencode 'refresh_token={{refresh_token}}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/auth/token", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Content-Type": "application/x-www-form-urlencoded",
  },
  body: new URLSearchParams({
    "grant_type": "refresh_token",
    "refresh_token": "{{refresh_token}}",
  }),
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/auth/token"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Content-Type": "application/x-www-form-urlencoded",
}
payload = {
    "grant_type": "refresh_token",
    "refresh_token": "{{refresh_token}}",
}

response = requests.post(url, headers=headers, data=payload)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader("grant_type=refresh_token&refresh_token=%7B%7Brefresh_token%7D%7D")

	req, err := http.NewRequest("POST", "https://api.acme.dev/v1/auth/token", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

## Products

Products are the items sold in your store.

> Prices are always expressed in the smallest currency unit (e.g. cents).

---

### List products

Section: Products

```
GET https://api.acme.dev/v1/stores/store_42/products?page=1&limit=20&sort=-created_at
```

Returns a paginated list of products, newest first.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Query parameters

| Name | Value |
| --- | --- |
| `page` | `1` |
| `limit` | `20` |
| `search` (optional) | `shoes` |
| `sort` | `-created_at` |

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Example responses

##### Response

```json
{
  "data": [
    {
      "id": "prod_123",
      "name": "Running shoes",
      "price": 8999,
      "currency": "USD"
    },
    {
      "id": "prod_124",
      "name": "Trail socks",
      "price": 1299,
      "currency": "USD"
    }
  ],
  "page": 1,
  "hasMore": true
}
```

#### Examples

##### cURL

```bash
curl 'https://api.acme.dev/v1/stores/store_42/products?page=1&limit=20&sort=-created_at' \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/stores/store_42/products?page=1&limit=20&sort=-created_at", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/stores/store_42/products?page=1&limit=20&sort=-created_at"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/stores/store_42/products?page=1&limit=20&sort=-created_at", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Get a product

Section: Products

```
GET https://api.acme.dev/v1/products/prod_123
```

Retrieve a single product by its id.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Path parameters

| Name | Value |
| --- | --- |
| `id` | `prod_123` |

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Example responses

##### 200 OK

```json
{
  "id": "prod_123",
  "name": "Running shoes",
  "price": 8999,
  "currency": "USD",
  "inStock": true
}
```

##### 404 Not Found

```json
{
  "error": "not_found",
  "message": "No product with id prod_999."
}
```

#### Examples

##### cURL

```bash
curl https://api.acme.dev/v1/products/prod_123 \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/products/prod_123", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/products/prod_123"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/products/prod_123", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Create a product

Section: Products

```
POST https://api.acme.dev/v1/products
```

Create a new product.

```json
{ "id": "prod_124", "status": "draft" }
```

The response contains the created product.

The API validates the payload and returns `422` when a field is invalid.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |
| `Content-Type` | `application/json` |
| `Idempotency-Key` | `{{uuid.v4}}` |

#### Body

Content type: `application/json`

```json
{
  "name": "Running shoes",
  "price": 8999,
  "currency": "USD",
  "tags": [
    "sport",
    "shoes"
  ],
  "inStock": true,
  "dimensions": {
    "weight": 0.8,
    "unit": "kg"
  }
}
```

#### Example responses

##### 201 Created

```json
{
  "id": "prod_125",
  "name": "Running shoes",
  "status": "draft"
}
```

##### 422 Unprocessable Content

```json
{
  "error": "validation_failed",
  "fields": {
    "price": "must be a positive integer"
  }
}
```

#### Examples

##### cURL

```bash
curl -X POST https://api.acme.dev/v1/products \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: {{uuid.v4}}' \
  -H 'Authorization: Bearer {{api_token}}' \
  --data-raw '{
  "name": "Running shoes",
  "price": 8999,
  "currency": "USD",
  "tags": [
    "sport",
    "shoes"
  ],
  "inStock": true,
  "dimensions": {
    "weight": 0.8,
    "unit": "kg"
  }
}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/products", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Content-Type": "application/json",
    "Idempotency-Key": "{{uuid.v4}}",
    "Authorization": "Bearer {{api_token}}",
  },
  body: JSON.stringify({
    "name": "Running shoes",
    "price": 8999,
    "currency": "USD",
    "tags": [
      "sport",
      "shoes"
    ],
    "inStock": true,
    "dimensions": {
      "weight": 0.8,
      "unit": "kg"
    }
  }),
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/products"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Idempotency-Key": "{{uuid.v4}}",
    "Authorization": "Bearer {{api_token}}",
}
payload = {
    "name": "Running shoes",
    "price": 8999,
    "currency": "USD",
    "tags": [
        "sport",
        "shoes",
    ],
    "inStock": True,
    "dimensions": {
        "weight": 0.8,
        "unit": "kg",
    },
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "name": "Running shoes",
  "price": 8999,
  "currency": "USD",
  "tags": [
    "sport",
    "shoes"
  ],
  "inStock": true,
  "dimensions": {
    "weight": 0.8,
    "unit": "kg"
  }
}`)

	req, err := http.NewRequest("POST", "https://api.acme.dev/v1/products", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Idempotency-Key", "{{uuid.v4}}")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Update a product

Section: Products

```
PATCH https://api.acme.dev/v1/products/prod_123
```

Partially update a product. Only the fields you send are changed.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Path parameters

| Name | Value |
| --- | --- |
| `id` | `prod_123` |

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Body

Content type: `application/json`

```json
{
  "price": 7999
}
```

#### Examples

##### cURL

```bash
curl -X PATCH https://api.acme.dev/v1/products/prod_123 \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "price": 7999
}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/products/prod_123", {
  method: "PATCH",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "price": 7999
  }),
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/products/prod_123"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}
payload = {
    "price": 7999,
}

response = requests.patch(url, headers=headers, json=payload)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "price": 7999
}`)

	req, err := http.NewRequest("PATCH", "https://api.acme.dev/v1/products/prod_123", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Delete a product

Section: Products

```
DELETE https://api.acme.dev/v1/products/prod_123
```

Permanently delete a product. This cannot be undone.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Path parameters

| Name | Value |
| --- | --- |
| `id` | `prod_123` |

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Example responses

##### 204 No Content

No response body.

##### 409 Conflict

```json
{
  "error": "conflict",
  "message": "Product has open orders."
}
```

#### Examples

##### cURL

```bash
curl -X DELETE https://api.acme.dev/v1/products/prod_123 \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/products/prod_123", {
  method: "DELETE",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/products/prod_123"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

response = requests.delete(url, headers=headers)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.acme.dev/v1/products/prod_123", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Images

Upload and manage product images.

---

#### Upload an image

Section: Products › Images

```
POST https://api.acme.dev/v1/products/prod_123/images
```

Upload a product image (PNG or JPEG, max 5 MB).

##### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

##### Path parameters

| Name | Value |
| --- | --- |
| `id` | `prod_123` |

##### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

##### Body

Content type: `multipart/form-data`

| Field | Value |
| --- | --- |
| `alt` | `Side view` |
| `file` | `@./shoe.png` |

##### Examples

###### cURL

```bash
curl -X POST https://api.acme.dev/v1/products/prod_123/images \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}' \
  -F 'alt=Side view' \
  -F 'file=@./shoe.png;type=image/png'
```

###### JavaScript

```javascript
const form = new FormData();
form.append("alt", "Side view");
form.append("file", fileInput.files[0]); // ./shoe.png

const response = await fetch("https://api.acme.dev/v1/products/prod_123/images", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
  body: form,
});

const data = await response.json();
console.log(data);
```

###### Python

```python
import requests

url = "https://api.acme.dev/v1/products/prod_123/images"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}
payload = {
    "alt": "Side view",
}
files = {
    "file": open("./shoe.png", "rb"),
}

response = requests.post(url, headers=headers, data=payload, files=files)
print(response.json())
```

###### Go

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	writer.WriteField("alt", "Side view")
	file, _ := os.Open("./shoe.png")
	defer file.Close()
	part, _ := writer.CreateFormFile("file", "shoe.png")
	io.Copy(part, file)
	writer.Close()

	req, err := http.NewRequest("POST", "https://api.acme.dev/v1/products/prod_123/images", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")
	req.Header.Set("Content-Type", writer.FormDataContentType())

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

## Catalog

Browse the product catalog by category. Folders can be nested as deeply as you like.

---

### Categories

Top-level product categories.

---

#### List categories

Section: Catalog › Categories

```
GET https://api.acme.dev/v1/catalog/categories
```

Returns all top-level categories.

##### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

##### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

##### Example responses

###### 200 OK

```json
{
  "data": [
    {
      "id": "cat_shoes",
      "name": "Shoes"
    },
    {
      "id": "cat_apparel",
      "name": "Apparel"
    }
  ]
}
```

##### Examples

###### cURL

```bash
curl https://api.acme.dev/v1/catalog/categories \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'
```

###### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/catalog/categories", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
});

const data = await response.json();
console.log(data);
```

###### Python

```python
import requests

url = "https://api.acme.dev/v1/catalog/categories"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

###### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/catalog/categories", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

#### Subcategories

Categories within a category.

---

#### List subcategories

Section: Catalog › Categories › Subcategories

```
GET https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories
```

Returns the subcategories of a category.

##### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

##### Path parameters

| Name | Value |
| --- | --- |
| `category` | `cat_shoes` |

##### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

##### Example responses

###### 200 OK

```json
{
  "data": [
    {
      "id": "sub_running",
      "name": "Running"
    },
    {
      "id": "sub_trail",
      "name": "Trail"
    }
  ]
}
```

##### Examples

###### cURL

```bash
curl https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'
```

###### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
});

const data = await response.json();
console.log(data);
```

###### Python

```python
import requests

url = "https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

###### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

#### Attributes

Filterable attributes of a subcategory (size, color, …).

---

#### List attribute values

Section: Catalog › Categories › Subcategories › Attributes

```
GET https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories/sub_running/attributes
```

Returns the values of every filterable attribute in a subcategory.

##### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

##### Path parameters

| Name | Value |
| --- | --- |
| `category` | `cat_shoes` |
| `subcategory` | `sub_running` |

##### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

##### Example responses

###### 200 OK

```json
{
  "size": [
    "38",
    "39",
    "40",
    "41",
    "42"
  ],
  "color": [
    "black",
    "white",
    "volt"
  ]
}
```

###### 404 Not Found

```json
{
  "error": "not_found",
  "message": "Unknown subcategory."
}
```

##### Examples

###### cURL

```bash
curl https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories/sub_running/attributes \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'
```

###### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories/sub_running/attributes", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
  },
});

const data = await response.json();
console.log(data);
```

###### Python

```python
import requests

url = "https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories/sub_running/attributes"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

###### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/catalog/categories/cat_shoes/subcategories/sub_running/attributes", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

## Orders

Orders placed by customers. Requires an API key with the `orders:read` scope.

---

### List orders

Section: Orders

```
GET https://api.acme.dev/v1/orders?status=paid
```

List orders, optionally filtered by status.

#### Authentication

API Key — `X-API-Key` in header (inherited from folder "Orders")

#### Query parameters

| Name | Value |
| --- | --- |
| `status` | `paid` |

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |
| `Acme-Version` | `{{orders_version}}` |

#### Examples

##### cURL

```bash
curl 'https://api.acme.dev/v1/orders?status=paid' \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Acme-Version: 2025-01' \
  -H 'X-API-Key: {{orders_api_key}}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/orders?status=paid", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Acme-Version": "2025-01",
    "X-API-Key": "{{orders_api_key}}",
  },
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/orders?status=paid"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Acme-Version": "2025-01",
    "X-API-Key": "{{orders_api_key}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/orders?status=paid", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Acme-Version", "2025-01")
	req.Header.Set("X-API-Key", "{{orders_api_key}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Create an order

Section: Orders

```
POST https://api.acme.dev/v1/orders
```

Place an order on behalf of a customer.

#### Authentication

Basic Auth

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |
| `Acme-Version` | `{{orders_version}}` |

#### Body

Content type: `application/json`

```json
{
  "customerId": "cus_9",
  "items": [
    {
      "productId": "prod_123",
      "quantity": 2
    }
  ]
}
```

#### Examples

##### cURL

```bash
curl -X POST https://api.acme.dev/v1/orders \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Acme-Version: 2025-01' \
  -H 'Content-Type: application/json' \
  -u 'merchant:{{merchant_password}}' \
  --data-raw '{
  "customerId": "cus_9",
  "items": [
    {
      "productId": "prod_123",
      "quantity": 2
    }
  ]
}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/orders", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Acme-Version": "2025-01",
    "Content-Type": "application/json",
    Authorization: `Basic ${btoa("merchant:{{merchant_password}}")}`,
  },
  body: JSON.stringify({
    "customerId": "cus_9",
    "items": [
      {
        "productId": "prod_123",
        "quantity": 2
      }
    ]
  }),
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/orders"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Acme-Version": "2025-01",
}
payload = {
    "customerId": "cus_9",
    "items": [
        {
            "productId": "prod_123",
            "quantity": 2,
        },
    ],
}

response = requests.post(url, headers=headers, json=payload, auth=("merchant", "{{merchant_password}}"))
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "customerId": "cus_9",
  "items": [
    {
      "productId": "prod_123",
      "quantity": 2
    }
  ]
}`)

	req, err := http.NewRequest("POST", "https://api.acme.dev/v1/orders", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Acme-Version", "2025-01")
	req.Header.Set("Content-Type", "application/json")
	req.SetBasicAuth("merchant", "{{merchant_password}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

### Export orders (XML)

Section: Orders

```
GET https://api.acme.dev/v1/orders/export.xml
```

Legacy XML export.

#### Authentication

API Key — `X-API-Key` in header (inherited from folder "Orders")

#### Headers

| Name | Value |
| --- | --- |
| `User-Agent` | `acme-docs/1.0` |
| `Acme-Version` | `{{orders_version}}` |
| `Accept` | `application/xml` |

#### Example responses

##### 200 OK

```xml
<?xml version="1.0"?>
<orders>
  <order id="ord_1" status="paid" total="17998"/>
</orders>
```

#### Examples

##### cURL

```bash
curl https://api.acme.dev/v1/orders/export.xml \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Acme-Version: 2025-01' \
  -H 'Accept: application/xml' \
  -H 'X-API-Key: {{orders_api_key}}'
```

##### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/orders/export.xml", {
  headers: {
    "User-Agent": "acme-docs/1.0",
    "Acme-Version": "2025-01",
    "Accept": "application/xml",
    "X-API-Key": "{{orders_api_key}}",
  },
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/orders/export.xml"
headers = {
    "User-Agent": "acme-docs/1.0",
    "Acme-Version": "2025-01",
    "Accept": "application/xml",
    "X-API-Key": "{{orders_api_key}}",
}

response = requests.get(url, headers=headers)
print(response.json())
```

##### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/orders/export.xml", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Acme-Version", "2025-01")
	req.Header.Set("Accept", "application/xml")
	req.Header.Set("X-API-Key", "{{orders_api_key}}")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

## GraphQL

A GraphQL endpoint is available for flexible queries.

---

### Search products

Section: GraphQL

```
POST https://api.acme.dev/v1/graphql
```

Full-text product search with GraphQL.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Body

```graphql
query Search($term: String!) {
  products(search: $term, first: 5) {
    id
    name
    price
  }
}
```

Variables:

```json
{
  "term": "shoes"
}
```

#### Examples

##### cURL

```bash
curl -X POST https://api.acme.dev/v1/graphql \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "query": "query Search($term: String!) { products(search: $term, first: 5) { id name price } }",
  "variables": {
    "term": "shoes"
  }
}'
```

##### JavaScript

```javascript
const query = /* GraphQL */ `
  query Search($term: String!) {
    products(search: $term, first: 5) {
      id
      name
      price
    }
  }
`;

const response = await fetch("https://api.acme.dev/v1/graphql", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query,
    variables: {
      "term": "shoes"
    },
  }),
});

const data = await response.json();
console.log(data);
```

##### Python

```python
import requests

url = "https://api.acme.dev/v1/graphql"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
    "Authorization": "Bearer {{api_token}}",
}

query = """
query Search($term: String!) {
  products(search: $term, first: 5) {
    id
    name
    price
  }
}
"""

payload = {
    "query": query,
    "variables": {
        "term": "shoes",
    },
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())
```

##### Go

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

func main() {
	query := `
		query Search($term: String!) {
		  products(search: $term, first: 5) {
		    id
		    name
		    price
		  }
		}
	`
	variables := json.RawMessage(`{
		"term": "shoes"
	}`)

	payload, _ := json.Marshal(map[string]any{
		"query":     query,
		"variables": variables,
	})

	req, err := http.NewRequest("POST", "https://api.acme.dev/v1/graphql", bytes.NewReader(payload))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")
	req.Header.Set("Authorization", "Bearer {{api_token}}")
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```

---

## Realtime

Streaming APIs over WebSockets and gRPC.

---

### Order updates

Section: Realtime

```
WebSocket wss://stream.acme.dev/orders?store=store_42
```

Subscribe to real-time order events.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Query parameters

| Name | Value |
| --- | --- |
| `store` | `{{store_id}}` |

#### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

#### Message

```json
{"subscribe": "orders.*"}
```

#### Examples

##### JavaScript

```javascript
// Note: browsers don't support custom WebSocket headers. In Node.js, use the `ws` package:
// new WebSocket(url, { headers: {"Accept":"application/json","User-Agent":"acme-docs/1.0","Authorization":"Bearer {{api_token}}"} })
const socket = new WebSocket("wss://stream.acme.dev/orders?store=store_42");

socket.addEventListener("open", () => {
  socket.send("{\"subscribe\": \"orders.*\"}");
});

socket.addEventListener("message", (event) => {
  console.log(event.data);
});
```

##### wscat

```bash
wscat -c 'wss://stream.acme.dev/orders?store=store_42' \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0' \
  -H 'Authorization: Bearer {{api_token}}'

# Then send:
# {"subscribe": "orders.*"}
```

---

### Get stock level

Section: Realtime

```
gRPC http://grpc.acme.dev:50051 acme.inventory.v1.Inventory/GetStock
```

Query live inventory via gRPC.

#### Authentication

Bearer Token — `Authorization: Bearer <token>` (inherited from workspace "Acme Store API")

#### Metadata

| Name | Value |
| --- | --- |
| `x-store-id` | `{{store_id}}` |

#### Message

```json
{
  "productId": "prod_123"
}
```

#### Examples

##### grpcurl

```bash
grpcurl \
  -plaintext \
  -H 'x-store-id: store_42' \
  -H 'authorization: Bearer {{api_token}}' \
  -d '{
  "productId": "prod_123"
}' \
  grpc.acme.dev:50051 \
  acme.inventory.v1.Inventory/GetStock
```

---

## Health check

```
GET https://api.acme.dev/v1/health
```

Returns `ok` when the API is up. No authentication required.

### Authentication

None

### Headers

| Name | Value |
| --- | --- |
| `Accept` | `application/json` |
| `User-Agent` | `acme-docs/1.0` |

### Example responses

#### 200 OK

```text
ok
```

#### 503 Service Unavailable

```json
{
  "status": "degraded",
  "checks": {
    "database": "down"
  }
}
```

### Examples

#### cURL

```bash
curl https://api.acme.dev/v1/health \
  -H 'Accept: application/json' \
  -H 'User-Agent: acme-docs/1.0'
```

#### JavaScript

```javascript
const response = await fetch("https://api.acme.dev/v1/health", {
  headers: {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
  },
});

const data = await response.json();
console.log(data);
```

#### Python

```python
import requests

url = "https://api.acme.dev/v1/health"
headers = {
    "Accept": "application/json",
    "User-Agent": "acme-docs/1.0",
}

response = requests.get(url, headers=headers)
print(response.json())
```

#### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.acme.dev/v1/health", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", "acme-docs/1.0")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
```
