# Start a bulk upload

`POST /api/bobsync/products-bulk`

**Base URLs:**

- Sandbox: `https://api.tools.qa.bobshop.co.za`
- Production: `https://api.tools.bobshop.co.za`

**Authentication:** Bearer token required (see the Authentication page).

## Example request

```bash
curl -X POST 'https://api.tools.qa.bobshop.co.za/api/bobsync/products-bulk' \
  -H "content-type: application/json" \
  -H "Authorization: Bearer <API_KEY>" \
  -d '{
  "channel_id": 1,
  "url": "https://bobshop-tools-backend-qa-infra-bulk-uploads.s3.af-south-1.amazonaws.com/example.json?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=TEST%2Faf-south-1%2Fs3%2Faws4_request&X-Amz-Date=20240628T092547Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&x-id=PutObject&X-Amz-Signature=TESTSIGNATURE"
}'
```

Queue a previously uploaded bulk file for processing.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `channel_id` | integer | yes | The API channel your token belongs to. It is the `channel_id` in every order webhook, and support can give it to you before your first order. |
| `url` | string | yes | The URL from [Get a bulk upload URL](bulk_upload_url.md) that you uploaded the file to. |

One bulk upload runs at a time per channel. Poll [Check bulk upload status](bulk_upload_status.md) until
`is_running` is `false` before starting another. Starting a run resets the
counters and the error list.

## Failures

| Status | Body | Meaning |
| --- | --- | --- |
| `400` | `invalid channel_id` | `channel_id` missing or not positive. |
| `400` | `invalid url` | `url` was empty. |
| `400` | `a bulk upload is already running` | A run is already in progress for this channel. |
| `400` | `could not get channel` | The channel could not be found. |
| `400` | `could not queue bulk upload` | The run could not be queued on our side. Call [Cancel a bulk upload](bulk_upload_cancel.md), then retry. Without the cancel, a retry gets `a bulk upload is already running` for up to an hour. |
| `403` | `user 123 does not have access to channel 456` | The channel does not belong to you. |

## Response

`200` with the run's status record, `is_running` set to `true`.

```json
{
    "errors": null,
    "import_count": 0,
    "import_success_count": 0,
    "is_running": true
}
```
