# Detect datasets for a Shopify store

`GET https://stylor.ai/api/v1/datasets/detect`

- Authentication: private API key, sent as `Authorization: Bearer sgpt-sk-…::…`
- Rate-limit resource: `api.v1.datasets.detect`
- Demo key: not accepted
- Web page: https://stylor.ai/guides/rest/v1/detect-datasets

Finds the active datasets that are fed by a given Shopify store. It is
built for storefront integrations (such as a theme extension) that know
the shop's `myshopify.com` domain but not which dataset to point the
widget at.

## How matching works

1. `.myshopify.com` is stripped from the domain to get the shop slug
   (`my-store.myshopify.com` → `my-store`), case-insensitively.
2. Your organization's **active** Shopify data sources whose endpoint
   contains that slug are collected.
3. Their parent datasets are returned — but only those in `active`
   status.

A store with no matching source, or whose datasets are all draft or
archived, yields `detected: false` and an empty list rather than an
error.

## Good to know

- Because matching is a substring test on the slug, a short slug can
  match more than one store (`shop` matches `my-shop` and `shop-two`).
  Use the full domain.
- Only `datasetId`, `name` and the four store fields of `config` are
  returned per dataset.

## Example request

```bash
curl -X GET "https://stylor.ai/api/v1/datasets/detect?shopDomain=my-store.myshopify.com" \
  -H "Authorization: Bearer $STYLOR_API_KEY"
```

## Query parameters

- `shopDomain` (string, required): The store's Shopify domain, for example `my-store.myshopify.com`. Trimmed and lower-cased before matching. [example `"my-store.myshopify.com"`]

## Responses

### 200

The datasets that match, if any.

Content type `application/json`:

- `detected` (boolean, required): `true` when at least one active dataset matched.
- `datasets` (array<DetectedDataset>, required): Matching active datasets. Empty when `detected` is `false`.
  - `datasetId` (string (uuid), required): Unique id of the dataset.
  - `name` (string, required): Display name.
  - `config` (object, required): The four store fields of the dataset's configuration. Any that were never set are omitted.
    - `storeDomain` (string): Bare domain of the store.
    - `storeUrl` (string): The storefront URL.
    - `storeName` (string): Display name of the store.
    - `storeId` (string): Your identifier for the store.

Example:

```json
{
  "detected": true,
  "datasets": [
    {
      "datasetId": "c9b3c6c0-9b0f-4f42-bf3f-2b7a6b1b9d31",
      "name": "Spring 2026",
      "config": {
        "storeDomain": "example-boutique.com",
        "storeUrl": "https://example-boutique.com",
        "storeName": "Example Boutique",
        "storeId": "58712345678"
      }
    }
  ]
}
```

## Errors

Every error is a JSON object with an `error` string. Match on the status code; the message is written for people.

| Status | Message | When |
| --- | --- | --- |
| 422 | shopDomain is required and must be a string. | The `shopDomain` query parameter is absent or empty. |
| 422 | shopDomain cannot be empty. | `shopDomain` is blank after trimming. |

### Shared authentication, quota and rate-limit errors

| Status | Message | When |
| --- | --- | --- |
| 401 | API key missing. | The `Authorization` header is absent, is not `Bearer <key>`, or the key does not have three dash-separated segments. |
| 401 | Authentication failed: public key is invalid or not recognized. | A public-key endpoint was called with a key that does not exist. |
| 401 | Authentication failed: private key provided instead of a public key. | A public-key endpoint was called with an `sgpt-sk-…` key. |
| 401 | Authentication failed: token is not recognized. | A private-key endpoint was called with a key whose lookup segment does not exist. |
| 401 | Authentication failed: private key is invalid. | A private-key endpoint was called with a key whose secret does not match. |
| 401 | Authentication failed: public key provided instead of a private key. | A private-key endpoint was called with an `sgpt-pk-…` key. |
| 401 | Authentication failed: bearer token format is invalid. | A private key was sent without its `::` lookup segment. |
| 401 | Authentication failed: API key could not be read. Regenerate the key. | The key's embedded organization data could not be decrypted or parsed. |
| 403 | Demo mode is not available for private-key routes. Demos are only supported with public API keys. | The demo key was sent to a private-key endpoint. |
| 403 | Demo mode is not supported on this API route. Check the documentation for available demo endpoints. | The demo key was sent to a public-key endpoint that opts out of demo mode. |
| 403 | No active subscription for this organization. | The organization that owns the key has no active subscription. |
| 403 | No quota found for organization "<organizationId>". | The organization has no quota record for the current billing period. |
| 403 | No entitlement for "<resource>". | The plan's quota template has no entry for this endpoint. |
| 403 | Access denied to "<resource>". | The plan's quota template turns this endpoint off. |
| 429 | Monthly quota exceeded for "<resource>" (<quota>/<quota> used). | The billing-period quota for this endpoint is exhausted. `Retry-After` gives the seconds until the period resets. |
| 429 | RPM limit exceeded for "<resource>" (<used>/<limit> used). | More than the allowed requests per minute were sent. `Retry-After` is 60. |
| 500 | Internal server error. | An unexpected failure on the server. The message is always this string; details are logged, never returned. Quota consumed by the request is refunded, as it is for every 5xx response. |
