# Sales Data

The Sales `GET` endpoint is paginated, so please refer to the [Pagination](/apis/pagination.md) documentation prior to usage.

As with all Claret API endpoints, the Sales APIs require token authentication. For instructions on how to retrieve and pass through the authentication token, please refer to the [Authentication](/apis/authentication.md) documentation.

{% hint style="info" %}
All API documentation herein contains a `{tenant}` section of the URL path. These should always be replaced with the name of the actual tenant making the API call (i.e., `demo`, `zymoeno`, etc.)
{% endhint %}

### GET Sales

Sales data is available to retrieve at our RESTful `GET` endpoint, and the structure of that data is somewhat customizable via the arguments described below.

<mark style="color:blue;">`GET`</mark> `https://plan.claret.app/{tenant}/api/v1/sales`

Retrieve paginated historical, forecast or transactional sales data.

#### Query Parameters

| Name                                               | Type                  | Description                                                                                                                                                                                                                        |
| -------------------------------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| sale\_type\_name<mark style="color:red;">\*</mark> | string                | The `name` of the Sale Type for the Sale records being retrieved (i.e., "History", "Forecast", etc.)                                                                                                                               |
| start\_date<mark style="color:red;">\*</mark>      | date string           | <p>The start date of the query pull. Based on the sell\_date.</p><p><strong>Format: YYYY-MM-DD</strong></p>                                                                                                                        |
| duration<mark style="color:red;">\*</mark>         | integer               | Integer value representing the number of days from the start date that the query should pull data for.                                                                                                                             |
| include\_flattened\_hierarchy                      | tiny integer (1 or 0) | When set to `1` (true), the flattened hierarchy levels for each of the `Item`s and `CustomerGroup`s will be provided in the payload.                                                                                               |
| current\_index<mark style="color:red;">\*</mark>   | integer               | For data loads larger than 1000 records, this parameter will not be required on the initial request, but must be included for each additional request. Please see the [Pagination](/apis/pagination.md) documentation for details. |
| pagination\_count                                  | integer               | For use with paginated data. This optional parameter can be set to a numeric value denoting how many records to retrieve in each paginated batch. Please see the [Pagination](/apis/pagination.md) documentation for details.      |

{% tabs %}
{% tab title="200: OK Successful Response" %}
The following examples contain the data structure for responses with and without the `include_flattened_hierarchy` flag

```json
-- include_flattened_hierarchy was NOT included in the request for this response:
- Actual request from zymoeno tenant: 
-- https://plan.claret.app/zymoeno/api/v1/sales?start_date=2022-06-01&duration=600&sale_type_name=Forecast
 
{
    "success_message": "Successfully retrieved 298 Sales records matching `sale_type_id`='3' and `sell_date`>='2022-06-01' and `sell_date`<='2024-01-22'",
    "sales": [
        {
            "id": 12310,
            "sell_date": "2022-06-01",
            "quantity": 0,
            "created_at": "2021-09-28T16:51:44.000000Z",
            "updated_at": "2022-04-15T16:03:35.000000Z",
            "item_name": "117",
            "customer_group_name": "Palm Tree Distribution",
            "timing_interval_span": "month",
            "sale_type_name": "Forecast",
            "uom_abbr": "9LE"
        },
        {
            "id": 12334,
            "sell_date": "2022-06-01",
            "quantity": 196.195,
            "created_at": "2021-09-28T16:51:44.000000Z",
            "updated_at": "2022-04-15T16:03:35.000000Z",
            "item_name": "118",
            "customer_group_name": "Palm Tree Distribution",
            "timing_interval_span": "month",
            "sale_type_name": "Forecast",
            "uom_abbr": "9LE"
        },
       ... [additional records] ...
        {
            "id": 23274,
            "sell_date": "2022-12-01",
            "quantity": 135,
            "created_at": "2022-12-21T00:35:13.000000Z",
            "updated_at": "2022-12-21T00:35:13.000000Z",
            "item_name": "124",
            "customer_group_name": "Alamo Wholesalers",
            "timing_interval_span": "month",
            "sale_type_name": "Forecast",
            "uom_abbr": "9LE"
        }
    ],
    "total": 298,
    "from": 1,
    "to": 298,
    "per_page": 1000,
    "previous_data_count": 0,
    "data_count_remaining": 0,
    "current_index": 0,
    "next_index": null,
    "success_count": 298
}

-- include_flattened_hierarchy=1 WAS included in the request for this response:
- Actual request from zymoeno tenant:
-- https://plan.claret.app/zymoeno/api/v1/sales?start_date=2022-06-01&duration=600&sale_type_name=Forecast&include_flattened_hierarchy=1

{
    "success_message": "Successfully retrieved 298 Sales records matching `sale_type_id`='3' and `sell_date`>='2022-06-01' and `sell_date`<='2024-01-22'",
    "sales": [
        {
            "id": 12310,
            "item_name": "117",
            "customer_group_name": "Palm Tree Distribution",
            "timing_interval_span": "month",
            "uom": "9LE Case",
            "uom_abbr": "9LE",
            "sale_type_name": "Forecast",
            "sell_date": "2022-06-01",
            "quantity": 0,
            "created_at": "2021-09-28T16:51:44.000000Z",
            "updated_at": "2022-04-15T16:03:35.000000Z",
            "brand_group": "Premium group",
            "brand": "Clairemont brand",
            "item": "117",
            "item_description": "CLM Central Coast Sangiovese 12 x 750ml",
            "division": "East div",
            "state": "Florida",
            "distributor": "Palm Tree Distribution",
            "distributor_description": "PTD"
        },
        {
            "id": 12334,
            "item_name": "118",
            "customer_group_name": "Palm Tree Distribution",
            "timing_interval_span": "month",
            "uom": "9LE Case",
            "uom_abbr": "9LE",
            "sale_type_name": "Forecast",
            "sell_date": "2022-06-01",
            "quantity": 196.195,
            "created_at": "2021-09-28T16:51:44.000000Z",
            "updated_at": "2022-04-15T16:03:35.000000Z",
            "brand_group": "Premium group",
            "brand": "Clairemont brand",
            "item": "118",
            "item_description": "CLM Central Coast White Blend 12 x 750ml",
            "division": "East div",
            "state": "Florida",
            "distributor": "Palm Tree Distribution",
            "distributor_description": "PTD"
        },
     ... [additional records] ...
        {
            "id": 23274,
            "item_name": "124",
            "customer_group_name": "Alamo Wholesalers",
            "timing_interval_span": "month",
            "uom": "9LE Case",
            "uom_abbr": "9LE",
            "sale_type_name": "Forecast",
            "sell_date": "2022-12-01",
            "quantity": 135,
            "created_at": "2022-12-21T00:35:13.000000Z",
            "updated_at": "2022-12-21T00:35:13.000000Z",
            "brand_group": "Premium group",
            "brand": "ZAM brand",
            "item": "124",
            "item_description": "ZAM Lodi Zinfandel 12 x 750ml",
            "division": "West div",
            "state": "Texas",
            "distributor": "Alamo Wholesalers",
            "distributor_description": "AW"
        }
    ],
    "total": 298,
    "from": 1,
    "to": 298,
    "per_page": 1000,
    "previous_data_count": 0,
    "data_count_remaining": 0,
    "current_index": 0,
    "next_index": null,
    "success_count": 298
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Failed Validation" %}
If the arguments provided fail internal validation, a `422` response will be returned

Here, we have included a non-existent Sale Type as an argument. However, the same structured response will be sent back if required arguments are missing.

```json
- Actual request from zymoeno tenant:
-- https://plan.claret.app/zymoeno/api/v1/sales?start_date=2022-06-01&duration=600&sale_type_name=NotARealSaleType
{
    "message": "The arguments provided have failed validation. Please check your request and try again.",
    "content": {
        "errors": [
            {
                "error_message": "The selected sale type name is invalid.",
                "row": {
                    "start_date": "2022-06-01",
                    "duration": "600",
                    "sale_type_name": "NotARealSaleType"
                }
            }
        ],
        "error_count": 1,
        "valid": [],
        "valid_count": 0
    }
}
```

{% endtab %}
{% endtabs %}

### POST Sales

Sales data can be posted to Claret using the `POST` endpoint outlined below. This endpoint supports both JSON payloads and CSV file uploads, and processes data asynchronously via the Imports2 pipeline.

<mark style="color:green;">`POST`</mark> `https://plan.claret.app/{tenant}/api/v1/sales`

The `POST` endpoint accepts an `arguments` object and a `payload` array of Sales records (JSON) or a CSV file upload.

{% hint style="info" %}
All responses are asynchronous. The endpoint returns a `job_log_id` that can be used with the [Job Status](/apis/public-apis/job-status.md) endpoint to monitor progress and retrieve results.
{% endhint %}

#### Arguments

| Name                                                          | Type    | Description                                                                                                                                    |
| ------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| allow\_record\_creation<mark style="color:red;">\*</mark>     | boolean | When `true`, missing Item\@CustomerGroup combinations will be automatically created during import.                                             |
| allow\_record\_update<mark style="color:red;">\*</mark>       | boolean | When `true`, existing sales records matching the composite key will be updated (upsert). When `false`, matching records are treated as errors. |
| should\_continue\_on\_error<mark style="color:red;">\*</mark> | boolean | When `true`, valid rows will be imported and invalid rows reported as errors. When `false`, the entire import fails if any row is invalid.     |

#### Payload Fields (per row)

| Name                                                    | Type        | Description                                                               |
| ------------------------------------------------------- | ----------- | ------------------------------------------------------------------------- |
| sale\_type\_name<mark style="color:red;">\*</mark>      | string      | The name of the Sale Type (e.g., "History", "Forecast").                  |
| item\_name<mark style="color:red;">\*</mark>            | string      | The name of the Item. Must exist in the system.                           |
| customer\_group\_name<mark style="color:red;">\*</mark> | string      | The name of the Customer Group. Must exist in the system.                 |
| sell\_date<mark style="color:red;">\*</mark>            | date string | The sell date in **YYYY-MM-DD** format.                                   |
| timing\_interval<mark style="color:red;">\*</mark>      | string      | The timing interval span (e.g., "day", "week", "month", "year").          |
| quantity<mark style="color:red;">\*</mark>              | numeric     | The quantity value. 0 is accepted; negative numbers will fail validation. |
| uom<mark style="color:red;">\*</mark>                   | string      | The unit of measure name or abbreviation (e.g., "9LE Case", "Ton").       |

#### Upsert Composite Key

When `allow_record_update` is `true`, existing records are matched on:

* `item_customer_group_id` (resolved from `item_name` + `customer_group_name`)
* `sell_date`
* `timing_interval_id` (resolved from `timing_interval`)
* `sale_type_id` (resolved from `sale_type_name`)

If a match is found, `quantity` and `uom` are updated. If no match is found, a new record is created.

#### Option 1: JSON Payload

Send sales data as a JSON array in the `payload` field.

```bash
curl -X POST "https://plan.claret.app/{tenant}/api/v1/sales" \
  -H "Authorization: Bearer {your-token}" \
  -H "X-Requested-With: XMLHttpRequest" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "allow_record_creation": true,
      "allow_record_update": true,
      "should_continue_on_error": true
    },
    "payload": [
      {
        "sale_type_name": "History",
        "item_name": "118",
        "customer_group_name": "Palm Tree Distribution",
        "sell_date": "2025-01-15",
        "timing_interval": "month",
        "quantity": 150,
        "uom": "9LE Case"
      }
    ]
  }'
```

#### Option 2: CSV File Upload

Upload a CSV file via multipart/form-data. The CSV must include headers matching the required payload fields.

```bash
curl -X POST "https://plan.claret.app/{tenant}/api/v1/sales" \
  -H "Authorization: Bearer {your-token}" \
  -H "X-Requested-With: XMLHttpRequest" \
  -F "file=@sales_data.csv" \
  -F 'arguments={"allow_record_creation": true, "allow_record_update": true, "should_continue_on_error": true}'
```

**CSV format:**

```csv
sale_type_name,item_name,customer_group_name,sell_date,timing_interval,quantity,uom
History,118,Palm Tree Distribution,2025-01-15,month,150,9LE Case
History,119,Alamo Wholesalers,2025-01-15,month,200,9LE Case
```

{% tabs %}
{% tab title="202: Accepted (CSV) / 200: OK (JSON)" %}

```json
{
  "message": "Data import process started successfully. Check job status for updates.",
  "job_log_id": 12345,
  "job_status_link": "https://plan.claret.app/{tenant}/settings/application-maintenance/job-management/imports/logs/12345"
}
```

Use the `job_log_id` with the [Job Status](/apis/public-apis/job-status.md) endpoint to monitor progress:

```bash
curl -X GET "https://plan.claret.app/{tenant}/api/v1/imports/status/12345" \
  -H "Authorization: Bearer {your-token}"
```

{% endtab %}

{% tab title="422: Unprocessable Entity" %}
Returned when required arguments are missing or validation fails.

```json
{
  "message": "Payload arguments are invalid"
}
```

{% endtab %}

{% tab title="401: Unauthorized" %}

```json
{
  "message": "Unauthenticated."
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.claret.app/apis/public-apis/sales-data.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
