# Search QuickBooks, or sync records to it

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

- Status: internal: built for YoPrint's own apps, don't build on it
- API version: v1
- Operation ID: `v1_public_external_integration_public_action`
- Section: Team settings › [Integrations](https://developer.yoprint.com/reference/integrations.md)
- Web page: https://developer.yoprint.com/reference/integrations/v1-external-integration-public-action/
- 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, which uses it to link YoPrint records to QuickBooks Online and to push them there. Only QuickBooks Online answers it; other integrations answer 422 `invalid_public_action`. Send an `action`:

- `query_customer`, `query_vendor`: up to 20 QuickBooks records whose display name contains `query`. `query_invoice`, `query_bill`, `query_purchase_order`: up to 20 whose document number contains it. Records come as QuickBooks returns them.
- `sync_order` and `sync_purchase_order`: queue a sync to QuickBooks of 1 to 100 sales orders or purchase orders, by their ids in `objects`. The answer is `data: null`; the sync runs afterwards, on exactly the records YoPrint checked.

Each action checks a permission before anything else, so a member without Manage Settings who lacks it gets 403 `user_is_not_authorized` (see Permission). The `{id}` is the integration's id from the list.

## Permission

The team owner and members with Manage Settings can run every action. Other members need, per action: `query_customer`, permission to view all customers (`view_all_customer`); `query_vendor`, permission to view vendors (`view_vendor`); `sync_order`, permission to view all sales orders (`view_all_order`) or their own (`view_self_order`), and every order in `objects` must be one they can view (their own: created by them or assigned to them); `sync_purchase_order`, the same with purchase orders (`view_all_po`, `view_self_po`). `query_invoice`, `query_bill` and `query_purchase_order` need Manage Settings.

## Side effects

- Calls QuickBooks Online. The `sync_` actions queue writes of your records to QuickBooks.

## 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 QuickBooks Online integration. Its hash id from an earlier answer; there is no unique key for it. Example `QF3K07jFrQ1P1B`.

## Request body

Content type `application/json`, required.

Fields:

- `action` (string, required): One of: `"query_customer"`, `"query_vendor"`, `"query_invoice"`, `"query_bill"`, `"query_purchase_order"`, `"sync_order"`, `"sync_purchase_order"`.
- `objects` (array of strings or integers, optional): For the `sync_` actions: 1 to 100 sales order or purchase order ids, as this API returns them. Don't send document numbers such as `1001`: a whole number, or a string of digits only, is read as YoPrint's internal record number and can name a different record.
- `query` (string, optional): For the `query_` actions: text the display name contains.

### Example request

```bash
curl -X PUT 'https://secure.yoprint.com/v1/api/store/your-team/setting/external_integration/QF3K07jFrQ1P1B/public_action' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "action": "query_customer",
    "query": "Northwind"
  }'
```

Another example: Sync two sales orders:

```bash
curl -X PUT 'https://secure.yoprint.com/v1/api/store/your-team/setting/external_integration/QF3K07jFrQ1P1B/public_action' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "action": "sync_order",
    "objects": [
      "zGZRXNGeh5cs6M",
      "VDG1ZqxwDQCaZ0"
    ]
  }'
```

## Response

`200` Successful response.

> **Warning: a 200 answer can still be a refusal.** Check `success` (and the fields named below) as well as the HTTP status.
> - The owner or a member with Manage Settings sends an `action` that is missing or not one of the seven: HTTP 200 with an empty body (not JSON), and nothing happens. Fix: Send an `action` from the list.

Fields:

- `data` (array of objects | null, required): For a `query_` action, up to 20 QuickBooks records as QuickBooks returns them. For a `sync_` action, null.
- `status` (integer, required)
- `success` (boolean, required)

Example response:

```json
{
  "data": [
    {
      "DisplayName": "Northwind Apparel",
      "Id": "58"
    }
  ],
  "status": 200,
  "success": true
}
```

## Errors

- `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, have no Manage Settings, and lack the permission the action needs (or can't view one of the records in `objects`). Members without Manage Settings get this for other integrations and for an `action` that is missing or unknown, too. `error.code` `user_is_not_authorized`, "Your role does not allow this integration action. Ask your team owner to review your permissions." (for a sales order you can't view, the message names sales order permissions). Nothing is synced. Fix: Ask the team owner to give your permission group the permission the action needs, or leave out records you can't view.
- `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: `sync_order` or `sync_purchase_order`: an entry in `objects` is not one of your team's ids or a positive whole number: `error.code` `unreadable_records`, "Some selected records could not be read. Reload the page and try again." Nothing is synced. Fix: Send the ids this API returns.
  - When: The integration is not QuickBooks Online (`invalid_public_action`), or `objects` is empty or has more than 100 ids (`validation_error`). Fix: Use the QuickBooks integration's id and 1 to 100 records.
  - When: A Shopify order can't be synced to QuickBooks (`validation_error`). Fix: Leave Shopify orders out.
  - When: `query` is not a string, or `objects` is not a list on a `query_` action (`validation_failed`); or the integration is retired or not in your plan. Fix: Send `query` as text and `objects` as a list of ids.

## Notes

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