> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.ordergroove.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.ordergroove.com/_mcp/server.

# List

GET https://restapi.ordergroove.com/products/

Returns a list of all merchant's products that are autoship enabled and not discontinued.

Reference: https://developer.ordergroove.com/reference/rest-rpc-api/products/list

## Authentication

- `x-api-key` header (required) — Application API Scope — server-to-server, sent in the `x-api-key` header. See [Authentication](/api-reference/authentication).
- `authorization` header (required) — Storefront API Scope — client-side, scoped to one customer, sent as a signature in the `authorization` header. See [Authentication](/api-reference/authentication).

## Request

### Query parameters

- `search` (string, optional) — A single string value used to search for products. The value in this parameter will be matched against product’s name, sku, or external_product_id, depending on the field specified in the "fields" parameter. e.g. /products?search=12345&fields=sku
- `fields` (string, optional) — Specifies which field (name, sku, or external_product_id) the "search" parameter value should be matched against. name – Matches the search value against the product’s name. sku – Matches the search value against the product’s SKU. external_product_id – Matches the search value against the product’s external product ID. e.g. /products?search=12345&fields=sku
- `id_or_name` (string, optional) — Case insensitive partial match for Product ID or Name
- `autoship_enabled` (string, optional) — By default the endpoint will only return products that are autoship enabled, but you can change the behavior by passing "all" to return all products regardless of their autoship status. You can also pass "false" to only return products that are NOT autoship enabled
- `allow_discontinued` (string, optional) — By default the endpoint returns non-discontinued products, but you can change the behavior by passing "true" to also include discontinued products. You can also pass "strict" to only list the discontinued products
- `group_name` (string, optional) — Product group's name
- `group_type` (string, optional) — Product group's type
- `autoship_by_default` (boolean, optional)
- `live` (boolean, optional) — Account status: active = True
- `external_product_ids[]` (string, optional) — Product ID (could be passed multiple times in the query string to match multiple products). Note there is "[]" at the end of this field that is required
- `product_type` (enum, optional) — Product Type
  - Allowed values: `"standard"`, `"rotating"`, `"static price bundle"`, `"dynamic price bundle"`
- `include_product_selection_rules` (boolean, optional, default: false) — For rotating products this param returns a product_selection_rules list with all selection_list_elements
- `include_product_free_trials` (boolean, optional, default: false) — When set to true, a product_free_trial_configurations list is included for each product with its free trial configurations

## Response

### 200

200

- `count` (integer, optional, default: 0)
- `next` (string, optional)
- `previous` (string, optional, nullable)
- `results` (list of ProductsGetResponsesContentApplicationJsonSchemaResultsItems, optional)

## Errors

### 403 Forbidden Error

403

- `detail` (string, optional)

### 404 Not Found Error

404

- `detail` (string, optional)

## Types

### ProductsGetResponsesContentApplicationJsonSchemaResultsItems

- `merchant` (string, optional)
- `groups` (list of ProductsGetResponsesContentApplicationJsonSchemaResultsItemsGroupsItems, optional)
- `name` (string, optional)
- `price` (string, optional)
- `image_url` (string, optional)
- `detail_url` (string, optional)
- `external_product_id` (string, optional)
- `sku` (string, optional)
- `autoship_enabled` (boolean, optional, default: true)
- `premier_enabled` (integer, optional, default: 0)
- `created` (string, optional)
- `last_update` (string, optional)
- `live` (boolean, optional, default: true)
- `discontinued` (boolean, optional, default: true)
- `extra_data` (any, optional)
- `product_type` (string, optional)
- `autoship_by_default` (boolean, optional, default: true)
- `every` (any, optional)
- `every_period` (any, optional)
- `offer_profile` (any, optional)
- `incentive_group` (any, optional)
- `product_free_trial_configurations` (list of FreeTrialConfiguration, optional) — Only included when include_product_free_trials=true is passed. Free trial configurations for the product; empty if none exist.

### ProductsGetResponsesContentApplicationJsonSchemaResultsItemsGroupsItems

- `name` (string, optional)
- `group_type` (string, optional)

### FreeTrialConfiguration

- `public_id` (string, required) — Free trial configuration public id
- `duration_in_days` (integer, required) — Number of days the free trial will last
- `created` (string, required)
- `last_updated` (string, required)

## Examples

**Response**

```json
{
  "count": 1,
  "next": "https://restapi.ordergroove.com/products/?page=2",
  "previous": null,
  "results": [
    {
      "merchant": "519f1f120e3411ef984b1e8a267ce85a",
      "groups": [
        {
          "name": "subscription",
          "group_type": "eligibility"
        }
      ],
      "name": "Medium Roast Coffee Bag",
      "price": "10.00",
      "image_url": "image-url",
      "detail_url": "product-url",
      "external_product_id": "48398751432995",
      "sku": "48398751432995",
      "autoship_enabled": true,
      "premier_enabled": 0,
      "created": "2024-05-09 15:20:09",
      "last_update": "2024-05-13 08:56:36",
      "live": true,
      "discontinued": false,
      "product_type": "standard",
      "autoship_by_default": true,
      "product_free_trial_configurations": [
        {
          "public_id": "da33bef203a34a958dbdf259837ea882",
          "duration_in_days": 9,
          "created": "2025-09-19 15:21:49",
          "last_updated": "2025-09-19 15:21:49"
        }
      ]
    },
    {
      "merchant": "519f1f120e3411ef984b1e8a267ce85a",
      "groups": [
        {
          "name": "prepaid",
          "group_type": "eligibility"
        },
        {
          "name": "subscription",
          "group_type": "eligibility"
        }
      ],
      "name": "Coffee Bag Subscription Club",
      "price": "10.00",
      "image_url": "image-url",
      "detail_url": "product-url",
      "external_product_id": "48398725906723",
      "sku": "48398725906723",
      "autoship_enabled": true,
      "premier_enabled": 0,
      "created": "2024-05-09 15:14:36",
      "last_update": "2024-05-13 08:56:36",
      "live": true,
      "discontinued": false,
      "product_type": "rotating",
      "autoship_by_default": true,
      "product_free_trial_configurations": []
    }
  ]
}
```

**SDK Code**

```python Result
import requests

url = "https://restapi.ordergroove.com/products/"

headers = {"x-api-key": "<apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript Result
const url = 'https://restapi.ordergroove.com/products/';
const options = {method: 'GET', headers: {'x-api-key': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Result
package main

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

func main() {

	url := "https://restapi.ordergroove.com/products/"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("x-api-key", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Result
require 'uri'
require 'net/http'

url = URI("https://restapi.ordergroove.com/products/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

```java Result
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://restapi.ordergroove.com/products/")
  .header("x-api-key", "<apiKey>")
  .asString();
```

```php Result
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://restapi.ordergroove.com/products/', [
  'headers' => [
    'x-api-key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp Result
using RestSharp;

var client = new RestClient("https://restapi.ordergroove.com/products/");
var request = new RestRequest(Method.GET);
request.AddHeader("x-api-key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

```swift Result
import Foundation

let headers = ["x-api-key": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://restapi.ordergroove.com/products/")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```