# Read Shopify orders through the integration

```http
PUT https://secure.yoprint.com/v1/api/store/{team_slug}/setting/external_integration/{id}/proxy_request
```

- Status: internal: built for YoPrint's own apps, don't build on it
- API version: v1
- Operation ID: `v1_public_external_integration_proxy_request`
- Section: Team settings › [Integrations](https://developer.yoprint.com/reference/integrations.md)
- Web page: https://developer.yoprint.com/reference/integrations/v1-external-integration-proxy-request/
- Authentication: `Authorization: Bearer YOUR_API_KEY`

> **Internal.** Built for YoPrint's own apps, not for integrations. Don't build on it; use the other operations in this section.

Built for YoPrint's web app, to browse orders in a connected Shopify store before importing them. Only Shopify answers it, and only `method: fetch_orders` is allowed (403 `proxy_method_not_allowed` otherwise). Other integrations answer 422 `invalid_public_action`.

Because it lists every order in the store, it needs Manage Settings or permission to view all sales orders. The permission is checked first: a member without Manage Settings gets 403 `user_is_not_authorized` unless they can view all sales orders and send `fetch_orders` to a Shopify integration.

It reads from Shopify and changes nothing. The `{id}` is the integration's id from the list.

## Permission

The team owner, members with Manage Settings, and members with permission to view all sales orders (`view_all_order`).

## Side effects

- Calls Shopify's Admin API.

## Path parameters

- `team_slug` (string, required): Your team slug, shown as Team ID next to your API key in Profile. Example `your-team`.
- `id` (string, required): The Shopify integration. Its hash id from an earlier answer; there is no unique key for it. Example `aDFOUrmqetFJaN`.

## Request body

Content type `application/json`, required.

Fields:

- `method` (string, required): Always `"fetch_orders"`.
- `body` (object | null, optional): Paging, search and sorting for the order list.
  - `cursor` (string, optional): A cursor from the previous page's `pagination`.
  - `direction` (string, optional): One of: `"forward"`, `"backward"`. Default `"forward"`.
  - `per_page` (integer, optional): Default `20`. Minimum 1. Maximum 250.
  - `query` (string, optional): Shopify search text.
  - `saved_search_id` (string, optional): A Shopify saved search.
  - `sort_direction` (string, optional): One of: `"asc"`, `"desc"`.
  - `sort_key` (string, optional): One of: `"CREATED_AT"`, `"TOTAL_PRICE"`, `"CUSTOMER_NAME"`, `"FINANCIAL_STATUS"`, `"FULFILLMENT_STATUS"`, `"ORDER_NUMBER"`.
- `path` (string | null, optional): Not used.

### Example request

```bash
curl -X PUT 'https://secure.yoprint.com/v1/api/store/your-team/setting/external_integration/aDFOUrmqetFJaN/proxy_request' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "body": {
      "per_page": 20,
      "sort_direction": "desc",
      "sort_key": "CREATED_AT"
    },
    "method": "fetch_orders"
  }'
```

## Response

`200` Successful response.

Fields:

- `data` (object, required)
  - `orders` (array of objects, required)
    - Each item:
      - `can_sync` (boolean, optional)
      - `created_at` (string (date-time) | null, optional)
      - `currency_code` (string | null, optional)
      - `customer` (object | null, optional)
      - `email` (string | null, optional)
      - `financial_status` (string | null, optional)
      - `fulfillment_status` (string | null, optional)
      - `id` (string, optional): Shopify's order id.
      - `is_sync` (boolean, optional): Whether it is already in YoPrint.
      - `name` (string | null, optional): Shopify's order name, such as `#1001`.
      - `sync_blocked_reason` (string | null, optional)
      - `total_price` (string | null, optional): A decimal string, as Shopify sends it (`"125.00"`); parse it as a decimal.
      - `updated_at` (string (date-time) | null, optional)
      - `yoprint_order_id` (string | null, optional): The YoPrint sales order made from it, or null.
  - `pagination` (object, required)
    - `cursor` (string | null, optional)
    - `has_more_pages` (boolean, optional)
    - `has_previous_pages` (boolean, optional)
    - `next_cursor` (string | null, optional)
    - `previous_cursor` (string | null, optional)
- `status` (integer, required)
- `success` (boolean, required)

Example response:

```json
{
  "data": {
    "orders": [
      {
        "can_sync": true,
        "created_at": "2026-10-30T09:00:00Z",
        "currency_code": "USD",
        "customer": {
          "name": "Alex Rivera"
        },
        "email": "alex@example.com",
        "financial_status": "PAID",
        "fulfillment_status": "UNFULFILLED",
        "id": "gid://shopify/Order/1001",
        "is_sync": false,
        "name": "#1001",
        "sync_blocked_reason": null,
        "total_price": "125.00",
        "updated_at": "2026-10-30T09:05:00Z",
        "yoprint_order_id": null
      }
    ],
    "pagination": {
      "cursor": null,
      "has_more_pages": false,
      "has_previous_pages": false,
      "next_cursor": null,
      "previous_cursor": null
    }
  },
  "status": 200,
  "success": true
}
```

## Errors

- `400`
  - When: The Shopify integration is turned off: `error.code` `integration_disabled`. Fix: Turn it on with the `toggle` action.
- `401` The API key is missing or wrong (`unauthenticated`).
- `403` You are not allowed to do this. `api_access_not_in_plan`: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only `{"message": "Insufficient Permission"}`. Other refusals use the error envelope, with `unauthorized` or `user_is_not_authorized`.
  - When: You are not the owner and have no Manage Settings, and either you can't view all sales orders or the call is not `fetch_orders` on a Shopify integration. `error.code` `user_is_not_authorized`, "Your role does not allow this integration action. Ask your team owner to review your permissions." Fix: Ask the team owner to give your permission group view all sales orders, or Manage Settings.
  - When: `method` is not `fetch_orders`, sent by the owner or a member with Manage Settings: `error.code` `proxy_method_not_allowed`. Fix: Use `fetch_orders`.
- `404` Not found. `page_not_found`: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. `code: null`, with a message that starts "No query results for": there is no record with that id.
- `422` The request was refused and changed nothing. `validation_failed` lists what to fix in `error.fields`; other codes name a business rule, explained in `error.message`. A few checks answer with only `{"message": "..."}`. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer `connect_timeout` ("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.
  - When: The integration is not Shopify (`invalid_public_action`), or `method` is missing (`validation_failed`). Fix: Use the Shopify integration's id.
- `429`
  - When: Shopify's rate limit was hit: `error.code` `shopify_rate_limited`. Fix: Wait a moment and try again.
- `500` A business rule refused the request (see the operation's errors), or something failed inside YoPrint. Refusals use the error envelope with a code such as `action_not_allowed`; an unexpected failure answers `{"message": "Server Error"}`. Repeating a refusal gets the same answer; after an unexpected failure, read the record back before you retry a change.
  - When: Something else failed: `error.code` `shopify_proxy_error`. Fix: Try again later.
- `502`
  - When: Shopify answered with an error or could not be reached (`shopify_api_error`, `shopify_connection_error`). Fix: Try again later.

## Notes

- AI apps (MCP connections) can't call this operation: they get 403 `agent_operation_not_available`. Use a personal API key.
