# Integration setup

Use this guide for the decisions shared by every integration. Endpoint schemas
and less common cases are covered in the [API Reference](/api) and linked
guides.

## 1. Create an API key

API keys are available and managed at
[account.legitgrails.com/settings/integrations](https://account.legitgrails.com/settings/integrations).
Create a Test or Live key for your integration and give it only the scopes your
service needs. The key determines the environment; both environments use the
same base URL:

```text
https://api.legitgrails.com/v1/integrations
```

| Scope | Use it for |
| --- | --- |
| `orders:write` | Catalog reads, photo uploads, order creation, and requested-photo submissions |
| `orders:read` | Catalog reads, order lists, and order details |
| `balance:read` | Credit balance reads |
| `webhooks:manage` | Webhook endpoint management |
| `audit:read` | Account audit-event reads |

An order-processing service usually needs `orders:write` and `orders:read`.
Keep keys in a server-side secret manager; never expose them in browser or
mobile code.

## 2. Authenticate

Send the API key as a bearer token on every request:

```http
Authorization: Bearer YOUR_API_KEY
```

Make an authenticated catalog request:

```bash
curl --fail-with-body --silent --show-error \
  "https://api.legitgrails.com/v1/integrations/catalog/categories" \
  --header "Authorization: Bearer $LEGITGRAILS_API_KEY"
```

See [Authentication](/authentication) for environment rules, rotation, and
authentication errors.

## 3. Resolve catalog codes

Resolve the current order context instead of hard-coding names or photo
requirements:

1. Select a `category_code` from `GET /catalog/categories`.
2. Select a compatible `brand_code` from `GET /catalog/brands`.
3. If needed, select a `model_code` from `GET /catalog/models`.
4. Select an available `answer_time` from `GET /catalog/answer_times`.
5. Load `GET /catalog/photo_indexes` with the selected category, brand, and
   optional model.

Send the numeric `code` of an answer time whose `available` value is `true`.
See [Catalog](/catalog) for query parameters, localization, and pagination.

## 4. Prepare photos

`POST /orders` accepts photo URLs issued by `POST /photos`. For each catalog
photo index:

- include a photo when `required` is `true`;
- use its exact `code` as `photos[].index_code`;
- stay within `photo_limit`; and
- keep the URL reachable while the order is processed.

Upload images to `POST /photos`, check each result's `status`, and use URLs only
from `uploaded` results. File types, upload limits, and the requested-photo flow
are documented in [Photos](/photos).

## 5. Create an order

Send one item per `POST /orders` request and persist the returned `id`. You can
also supply `external_id` to correlate the order with your own records.

With a Test key, include `mock_outcome` as `authentic`, `fake`,
`unable-to-verify`, or `update-photos`. The order is created immediately in the
corresponding simulated state. Omit `mock_outcome` when using a Live key.

Order creation can return `402` when the account lacks credits. The
[Quickstart](/quickstart) shows a complete request, and [Orders](/orders) covers
the available request and response fields.

## 6. Track orders

Read `GET /orders/{id}` using the returned order ID until the order is finished:

| Status | Action |
| --- | --- |
| `queued` or `processing` | Poll again later. |
| `update-photos` | Resolve every current `photos_to_resubmit` entry, then keep tracking. |
| `completed` | Process `outcome` and any optional result fields. |
| `error` | Stop polling and investigate or contact support with the order ID. |

An order can request photos more than once, so always use the latest order
detail. `GET /orders` can reconcile active work in batches. The `error` state
does not produce an `order-outcome` webhook, so polling or scheduled
reconciliation must detect it.

Webhooks provide `order-outcome` and `update-photos` notifications. Keep polling
or scheduled reconciliation to recover missed deliveries. Authenticate HMAC or
OAuth2 deliveries and process duplicate delivery IDs idempotently; see
[Webhooks](/webhooks).

## Live readiness checklist

- Replace the Test API key with a Live API key, remove `mock_outcome`, and keep
  the same base URL.
- Keep keys server-side, minimally scoped, and out of logs.
- Refresh catalog codes, available answer times, and photo requirements.
- Persist the LegitGrails order `id`.
- Handle `402`, `429`, and other HTTP errors, retaining their `request_id`; see
  [Rate limits](/rate-limits) for the current per-category limits.
- Support repeated `update-photos` rounds.
- Authenticate and deduplicate webhooks, with polling reconciliation for missed
  events.

Review the [API Reference](/api) before enabling live traffic.
