Predictive Inventory Management Service
The Predictive Inventory Management Service enables API callers to generate stock replenishment proposals based on historical data which includes supplier orders and customer orders.
From a business perspective, replenishment proposals are relevant for distribution businesses that order stock from suppliers, on one hand, and honour orders from customers, on the other hand.
Access info
| Endpoint | https://predictive-inventory-management-api.socrate.io/graphql |
| MCP endpoint | https://predictive-inventory-management-api.socrate.io/mcp |
| Required access keys | Tenant-level service access key |
| Pricing | Check the available purchase options. |
| Notes | To call the service, the access key must be provided in the x-api-key header of the HTTP request. If you are using the GraphQL console, you can view the service’s documentation and schema only after entering an access key. Make sure that the scope of the key allows access to the queries and mutations that you require. For example, to grant the key access to all queries and mutations, the key’s scope must be set to predictive-inventory-management-api:query:* predictive-inventory-management-api:mutation:*. |
Usage
Prerequisites
- The organization(s) for which reporting is done must exist in the SBS system. You can add new organizations either from the Organizations UI or programmatically from the Organizations Service.
- Several CSV files are required as input to the Predictive Inventory Management service. It is assumed that you are generating them from your ERP or similar system. For the structure of the input files, see Appendix 1: Input structure.
Generating a replenishment proposal
To generate a replenishment proposal:
- Obtain from your ERP system the input CSV files to be used as input. For the structure of each file, see Appendix 1: Input structure.
- Create a new replenishment proposal by calling the
createReplenishmentProposalmutation. You must supply as input argument, at the minimum, the target month, in the format YYYY-MM. As a result, a new replenishment proposal object is created, and the response contains the unique proposal ID. You will need to work with this ID in subsequent steps to further process the proposal and monitor its status. - Add all the input CSV files to the proposal. See Preparing input files.
- Run the
computeReplenishmentProposalmutation. This triggers a computation that takes place from several minutes to several hours, depending on the size of input CSV files.
The outcome of computing a proposal, including any possible errors, is reported in the Process object when querying the respective proposal. If the computation was successful, the process includes one or more of the following attributes:
- productCentricResult - This is the default result and it is always present. It contains, among other attributes, the name and download URL of the output file, with computation results grouped by product. For the structure of the output file, see Appendix 2: Output structure.
- customerCentricResult - This result is present if the proposal was created with the input parameter
splitByCustomer= true. The result has the same structure as above, except that data inside the output file are grouped by customer. - industryCentricResult - This result is present if the proposal was created with the input parameter
splitByIndustry= true. The result has the same structure as above, except that data inside the output file are grouped by industry code. - optimalServiceLevels - This result is present if the proposal was created with the input parameter
computeAnalysisData= true. For the structure of the file, see Appendix 2: Output structure.
Preparing input files
After you have created a replenishment proposal, you can add all the CSV input files to it.
For each input CSV file, the steps are as follows:
- Run the
prepareFilemutation, for example:
mutation prepareFile($replenishmentProposalId:ID!, $input:PrepareFileInput!) {
prepareFile(replenishmentProposalId:$replenishmentProposalId, input:$input) {
id
fileType
name
contentLength
uploadUrl
downloadUrl
createdAt
}
}
{
"replenishmentProposalId": "YOUR_REPLENISHMENT_PROPOSAL_ID",
"input": {
"fileType": "CustomerOrders",
"name": "customer-orders.csv"
}
}
In the response, you get the file’s upload URL at which you can upload the actual file.
- In the programming language of your API, make an HTTP
PUTrequest to upload the file content to the upload URL. This step is similar to how you would create a file and then upload its content in the File Management Service, as described in the Tutorial: Create a file.
Note that you can add multiple files of the same type for the same replenishment proposal. For example, you can add several input CSV files of type “CustomerOrders”. If multiple files of the same type exist, SBS will aggregate and compute data found in all respective files.
After adding all the CSV files, you can check if they are indeed attached to the replenishment proposal by running the replenishmentProposal query, for example:
query ReplenishmentProposal ($id:ID! $fileId:ID, $processId:ID) {
replenishmentProposal(id:$id) {
id
organizationId
files(id: $fileId) {
id fileType name contentLength uploadUrl downloadUrl createdAt
}
createdAt
}
}
{
"id": "YOUR_REPLENISHMENT_PROPOSAL_ID"
}
If your replenishment proposal looks good so far, you can proceed to running the computeReplenishmentProposal mutation, for example:
mutation ComputeReplenishmentProposal ($id:ID!) {
computeReplenishmentProposal(id:$id) {
id
status
dataRange { from to }
targetMonth
errorMessages
createdAt
}
}
{
"id": "YOUR_REPLENISHMENT_PROPOSAL_ID"
}
Dealing with large input files
As mentioned above, when you add a file to the replenishment proposal, there are two steps involved:
- Run
prepareFileand obtain the upload URL. - In the programming language of your API, make an HTTP
PUTrequest to upload the file content to the upload URL.
For the second step, note, however, that the maximum file size that you can send in a single PUT request is 5 GB. Should you need to add larger files to the replenishment proposal, you can do so through the multipart upload mutations provided by the File Management Service. In this scenario, the process looks as follows:
- Run
prepareFileand take notice thedata.prepareFile.idreturned in the response body. This ID corresponds to a file id of a file in File Management Service. - Provide the id above as input to the
initiateMultipartUploadmutation and continue with the rest of steps required for multipart upload, as described in Uploading large files.
Processes
Each time when you run computeReplenishmentProposal, a new process with status NEW is attached to the replenishment proposal. You can view the proposal and the status of all its processes by running the replenishmentProposal query and requesting the processes field in the response, for example:
query ReplenishmentProposal ($id:ID! $fileId:ID, $processId:ID) {
replenishmentProposal(id:$id) {
id
organizationId
targetMonth
splitByCustomer
splitByIndustry
files (id: $fileId) {
id fileType name contentLength uploadUrl downloadUrl createdAt
}
processes (id: $processId) {
id
status
dataRange { from to }
targetMonth
errorMessages
productCentricResult { id name contentLength createdAt downloadUrl }
customerCentricResult { id name contentLength createdAt downloadUrl }
industryCentricResult { id name contentLength createdAt downloadUrl }
totals {
csvLines { customerOrders supplierOrders allFileLines }
}
createdAt
}
createdAt
}
}
{
"id": "YOUR_REPLENISHMENT_PROPOSAL_ID"
}
The status of any process is initially NEW. The status NEW will normally change to INPROCESS after approximately 1 minute. Note that, if you run computeReplenishmentProposal multiple times for the same proposal, each run will start a new process. In this case, you will need to track the status of each process separately. The processes field of the replenishmentProposal query provides a filter (by process ID) for that purpose.
The INPROCESS status of a process may take from a few minutes to a few hours, depending on the size of the input CSV files. After the INPROCESS status, the status may change to either ERROR (if errors are encountered) or DONE (upon successful processing).
If the status ERROR is encountered, check the errorMessages response field of the respective process for details.
If the process completes with status DONE, it generates 1-4 CSV output files. As mentioned previously, the number of files depends on the input parameters supplied at proposal creation time to the createReplenishmentProposal mutation.
If necessary, you may stop a running process through a call to killProcess. This is possible only while the process has not produced any results.
You may also delete a process through the deleteProcess mutation. You cannot delete a running process. Stop it first with killProcess.
Deleting replenishment proposals
You can delete replenishment proposals through a call to deleteReplenishmentProposal. Note, however, that it is not possible to delete a replenishment proposal if it has at least one running process that has already generated some result file. To delete such a proposal, you will need to wait for the process to finish first.
Webhooks
The Predictive Inventory Management Service supports webhooks. This means you can optionally configure SBS to send an HTTP POST request to an external server or application whenever any of the following events occur:
- COMPUTATION_SUCCESS - fires whenever a replenishment proposal computation finishes successfully.
- COMPUTATION_ERROR - fires when a replenishment proposal computation finishes with error.
The payload of each POST request includes the identifier of the replenishment proposal and the identifier of the process, for example:
The POST request of the COMPUTATION_SUCCESS event has the following payload:
{
"service": "predictive-inventory-management-api",
"event": "COMPUTATION_SUCCESS",
"tenantId": "<your-tenant-id>",
"payload": {
"organizationId": "<your-organization-id>",
"replenishmentProposalId": "<your-proposal-id>",
"processId": "<your-process-id>"
},
"customKey1": "Custom value 1",
"customKey2": "Custom value 2"
}
The POST request of the COMPUTATION_ERROR event has the following payload:
{
"service": "predictive-inventory-management-api",
"event": "COMPUTATION_ERROR",
"tenantId": "<your-tenant-id>",
"payload": {
"organizationId": "<your-organization-id>",
"replenishmentProposalId": "<your-proposal-id>",
"processId": "<your-process-id>"
},
"customKey1": "Custom value 1",
"customKey2": "Custom value 2"
}
Note that the custom keys (such as customKey1 and customKey2 above) will be present in the request body only if you configured them when creating the webhook. You may configure as many key-value pairs as required.
For information about configuring webhooks, see Webhooks.
Queries
analysisData
For a given process, this query returns replenishment proposal analysis data. Before you run this query, make sure to compute a replenishment proposal first, and set the computeAnalysisData input parameter to true. To view the results graphically as a chart, run the analysisDataViewerUrl query.
Arguments
| Argument | Type | Description |
|---|---|---|
| organizationId | ID! |
Mandatory. The identifier of the organization. |
| replenishmentProposalId | ID! |
Mandatory. The identifier of the replenishment proposal. |
| processId | ID! |
Mandatory. The identifier of a process (which belongs to replenishmentProposalId) that finished with status DONE. |
Result
AnalysisData type
| Attribute | Type | Description |
|---|---|---|
| targetMonth | Month |
The target month supplied as input when the replenishment proposal was created, in YYYY-MM format. |
| backdatedTargetMonth | Month |
The backdated target month supplied as input when creating the proposal. If the proposal was created with computeAnalysisData = true, then the backdated target month applies implicitly, in which case this field indicates the implicit value. |
| dataRange | DataRange |
The date range covered by the replenishment proposal, as inferred from the input data. |
| warnings | [String] |
The warnings recorded by the originating process, if any. Matches the process’s warnings. |
| analyticsLog | [String] |
The analytics log recorded by the originating process, if any. Matches the process’s analyticsLog. |
| runDurationSeconds | Int |
The whole number of seconds between the originating process’s createdAt and completedAt. This value is null until the process completes. |
products(nextToken: String) |
ProductsResult |
Returns a paginated, lightweight list of products (id, code, name) for which analysis data is available. Use the optional nextToken argument to fetch the next page; obtain its value from the nextToken attribute of the previous ProductsResult response. To retrieve the full detail of a single product, use the product field below. |
product(id: String!) |
Product |
Returns a single product for which analysis data is available, retrievable by the mandatory id input parameter. |
| splitByCustomer | Boolean |
If true, the replenishment proposal was created with results split by customer. |
| splitByIndustry | Boolean |
If true, the replenishment proposal was created with results split by industry. |
| customers | [Customer] |
The list of customers for which analysis data is available. See the Customer type. |
| industries | [Industry] |
The list of industries for which analysis data is available. See the Industry type. |
| diagnostics | [Diagnostic] |
Returns diagnostic data for the products included in the analysis. |
performance(nextToken: String) |
PerformanceResult |
Returns paginated performance metrics for the products included in the analysis, limited to the best-performing scenario for each product. Use the optional nextToken argument to fetch the next page; obtain its value from the nextToken attribute of the previous PerformanceResult response. |
| globalScores | GlobalScores |
Aggregated, replenishment-proposal-wide performance and coverage scores. See the GlobalScores type. |
ProductsResult type
| Attribute | Type | Description |
|---|---|---|
| items | [ProductEntry] |
The actual array of ProductEntry items returned by the query. |
| nextToken | String |
If null, then the query has reached the end of the list of results that match the query criteria. If not null, then use this value as input to the products attribute of the AnalysisData type to fetch the next set of results. |
ProductEntry type
A lightweight projection of a product, used by the paginated products field. To retrieve the full detail of a single product, query the product(id) field on AnalysisData, which returns the Product type.
| Attribute | Type | Description |
|---|---|---|
| id | String |
The identifier of the product. |
| code | String |
The product code. |
| name | String |
The product name. |
PerformanceResult type
| Attribute | Type | Description |
|---|---|---|
| items | [PerformanceEntry] |
The actual array of PerformanceEntry items returned by the query. |
| nextToken | String |
If null, then the query has reached the end of the list of results that match the query criteria. If not null, then use this value as input to the performance attribute of the AnalysisData type to fetch the next set of results. |
GlobalScores type
Aggregated, replenishment-proposal-wide performance and coverage scores.
| Attribute | Type | Description |
|---|---|---|
| optimizedProducts | Int |
The number of products for which the simulation produced an optimized outcome. |
| nonoptimizedProducts | Int |
The number of products for which the simulation did not produce an optimized outcome. |
| coverageScore | Float |
The aggregated coverage score across all products. |
| optimizationScore | Float |
The aggregated optimization score across all products. |
| globalPerformance | Float |
The aggregated performance score balancing coverage and optimization across all products. |
Customer type
| Attribute | Type | Description |
|---|---|---|
| id | String |
The identifier of the customer. |
| code | String |
The customer code (external). |
Industry type
| Attribute | Type | Description |
|---|---|---|
| id | String |
The identifier of the industry. |
| code | String |
The industry code (external). |
Diagnostic type
| Attribute | Type | Description |
|---|---|---|
| productId | String |
The internal identifier of the product. |
| productCode | String |
The product code (external). |
| productName | String |
The product name. |
| customerId | String |
The customer identifier. |
| customerCode | String |
The customer code (external). |
| industryCodeId | String |
The industry code identifier. For example, private versus public customers. |
| industryCode | String |
The industry code (external). |
| targetMonth | String |
The target month, in YYYY-MM format. |
| numberOfObservations | Int |
The number of observations. |
| monthsWithData | Int |
The number of months with non-zero sales. |
| avgMonthlySales | Float |
Average monthly sales during the simulation period. |
| sparsityProportion | Float |
The proportion of null values in the data. |
| numberOfOutliers | Int |
A measure of data stability. |
| proportionOfOutliers | Float |
The proportion of outliers. |
| historyFactor | Float |
A factor penalizing products with less than 18 months of history. |
| residualFactor | Float |
Indicates how much of the trend and seasonality can be explained. |
| diagnosticScore | Float |
The aggregated PIM suitability score. |
PerformanceEntry type
| Attribute | Type | Description |
|---|---|---|
| productId | String |
The internal identifier of the product. |
| productCode | String |
The product code (external). |
| productName | String |
The product name. |
| serviceLevel | Float |
The optional service level. |
| numberOfObservations | Int |
The number of monthly data points. |
| diagnosticScore | Float |
Diagnostic score, computed as a weighted average. |
| avgMonthlySales | Float |
Average monthly sales during the simulation period. |
| avgHistoricStock | Float |
Average level of historical stock. |
| historicCoverage | Float |
Proportion of historic coverage with actual stock. |
| pimCoverage | Float |
Proportion of coverage with simulated stock. |
| coverageRatio | Float |
The ratio of PIM coverage to historic coverage. |
| pimOptimization | Float |
Percentage optimized from actual historic stock. |
| pimPerformance | Float |
Performance score balancing coverage and optimization. |
| isBest | Boolean |
True if this entry is the best-performing scenario for the product. |
| isOptimized | Boolean |
True if the entry represents an optimized outcome for the product. |
Product type
| Attribute | Type | Description |
|---|---|---|
| id | String |
The identifier of the product. |
| code | String |
The product code. |
| name | String |
The product name. |
| optimalServiceLevels | [OptimalServiceLevel] |
See the OptimalServiceLevel type. |
monthlyDemand(filter: SplitFilter) |
[MonthlyDemand] |
See the MonthlyDemand type. The optional filter argument restricts results to a specific customer or industry. See the SplitFilter input. |
monthlyForecast(serviceLevel: Float!, filter: SplitFilter) |
[MonthlyForecast] |
See the MonthlyForecast type. The optional filter argument restricts results to a specific customer or industry. See the SplitFilter input. |
| kpis | [Kpi] |
See the Kpi type. |
| supplierLeadTime | [SupplierLeadTime] |
See the SupplierLeadTime type. |
| customerLeadTime | [CustomerLeadTime] |
See the CustomerLeadTime type. |
| realStock | [RealStock] |
See the RealStock type. |
| simulatedStock | [SimulatedStock] |
See the SimulatedStock type. |
| simulatedPlot | [SimulatedPlot] |
See the SimulatedPlot type. |
| customers | [Customer] |
The list of customers that had activity for this product. See the Customer type. |
| industries | [Industry] |
The list of industries that had activity for this product. See the Industry type. |
OptimalServiceLevel type
| Attribute | Type | Description |
|---|---|---|
| type | String |
This value affects the way the optimal service level is computed. Valid values: out-of-stock-based, hybrid-out-of-stock-over-stock. While the service level and the replenishment values associated for it do not change, the way we define the optimal service level depends of this choice of type: out-of-stock-based - count the number of times the stock was enough to cover existing ad-hoc demand; hybrid-out-of-stock-over-stock - do a weighted average of over stock (greater than ad-hoc demand) and under stock (less than ad-hoc demand) with a default 0.3 for the situations of overstock. |
| value | Float |
The optimal service level value. |
| details | String |
Computation details for optimal service level by type. |
MonthlyDemand type
| Attribute | Type | Description |
|---|---|---|
| month | Month |
Concatenation of year and month (yyyy-mm). |
| adhocOrders | Float |
Total ad hoc client orders for the year and month. |
| missedSales | Float |
Estimated missing sales from stock-outs. |
MonthlyForecast type
| Attribute | Type | Description |
|---|---|---|
| month | Month |
Concatenation of year and month (yyyy-mm). |
| serviceLevel | Float |
Service level, from [0.3, 0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 0.98]. |
| monthlySalesServiceLevelForecast | Float |
The monthly sales forecast at the given service level. This represents the monthly demand given the service level and the underlying sales mean/standard deviation predictions. |
SplitFilter input
| Attribute | Type | Description |
|---|---|---|
| customerId | String |
Optional. Filters results to a specific customer by ID. NOTE: Either customerId or industryCode are accepted as filter, not both. |
| industryCode | String |
Optional. Filters results to a specific industry by code. NOTE: Either customerId or industryCode are accepted as filter, not both. |
Kpi type
| Attribute | Type | Description |
|---|---|---|
| orderType | OrderType |
Defines the type of order. This is an enum with the following possible values: CUSTOMER, SUPPLIER. |
| totalOrders | Int |
The total number of orders. |
| onTime | Int |
The number of on time orders. |
| delayed | Int |
The number of delayed orders. |
| serviceRate | Float |
The relative number of orders on time. |
| meanLeadTime | Float |
The mean lead time as inferred from the PIM calculation. |
| stdLeadTime | Float |
The standard deviation of lead time as inferred from the PIM calculation. |
| aboveMeanLeadTime | Int |
The number of orders above mean lead time. |
| belowMeanLeadTime | Int |
The number of orders below mean lead time. |
SupplierLeadTime type
| Attribute | Type | Description |
|---|---|---|
| deliveryDate | Date |
Date of actual delivery (yyyy-mm-dd). |
| orderDate | Date |
Date of order placement (yyyy-mm-dd). |
| promisedDate | Date |
Date of promised delivery (yyyy-mm-dd). |
| quantity | Float |
Quantity to deliver. |
| deliveryTime | Int |
Number of days between shipment date and order date. |
| promisedTime | Int |
Number of days between promised date and order date. |
| onTime | Float |
Calculated according to the formula: 0.1 if t == 0 else max(t,0) for t = promised_time - delivery time. |
| delayed | Float |
Calculated according to the formula: 0.1 if t == 0 else min(t,0) for t = promised_time - delivery time. |
CustomerLeadTime type
| Attribute | Type | Description |
|---|---|---|
| shipmentDate | Date |
Date of actual delivery (yyyy-mm-dd). |
| quantity | Float |
Quantity to deliver. |
| orderDate | Date |
Date of order placement (yyyy-mm-dd). |
| promisedDate | Date |
Date of promised delivery (yyyy-mm-dd). |
| orderRule | OrderRule |
Valid values: Fixed Tranche, Adhoc Demand. Inherited from customer orders. |
| deliveryTime | Int |
Number of days between shipment date and order date. |
| promisedTime | Int |
Number of days between promised date and order date. |
| onTime | Float |
Calculated according to the formula: 0.1 if t == 0 else max(t,0) for t = promised_time - delivery time. |
| delayed | Float |
Calculated according to the formula: 0.1 if t == 0 else min(t,0) for t = promised_time - delivery time. |
RealStock type
| Attribute | Type | Description |
|---|---|---|
| date | Date |
Date goes over the period used in simulation, usually at least 12 months (yyyy-mm-dd). |
| initialStock | Float |
Initial stock of the day. |
| stockIn | Float |
Total stock in. |
| stockOut | Float |
Total stock out. |
| finalStock | Float |
Final stock of the day. |
| adhocShipmentDate | Date |
Ad-hoc delivery date (yyyy-mm-dd). |
| adhocShipmentQuantity | Float |
Ad-hoc delivery quantity. |
| adhocOrderQuantity | Float |
Ad-hoc order quantity. |
| trancheShipmentDate | Date |
Tranche delivery date (yyyy-mm-dd). |
| trancheShipmentQuantity | Float |
Tranche delivery quantity. |
| trancheOrderQuantity | Float |
Tranche order quantity. |
| supplierDeliveryDate | Date |
Supplier delivery date (yyyy-mm-dd). |
| supplierOrderQuantity | Float |
Supplier order quantity. |
| supplierShipmentQuantity | Float |
Supplier shipment quantity. |
SimulatedStock type
| Attribute | Type | Description |
|---|---|---|
| date | Date |
Date goes over the period used in simulation, usually at least 12 months. The format is YYYY-mm-dd. |
| beginningOfDayStock | Float |
Initial stock of the day. |
| toBeDelivered | Float |
Quantity to be delivered during the day. |
| stockOut | Float |
Total stock out for the day. |
| adhocDemand | Float |
Ad-hoc demand for the day. |
| tranches | Float |
Tranches are not ad-hoc commands but quantities agreed upon over large periods of time (e.g. 6 months) and delivered in several shipments. |
| replenishmentProposal | Float |
Quantity proposed for replenishment. |
| supplierOrder | Float |
Quantity submitted as supplier order. |
| plannedArrivalDate | Date |
Date when a shipment is supposed to arrive (yyyy-mm-dd). |
| stockIn | Float |
Total quantity that entered the stock during the day. |
| endOfDayStock | Float |
Stock at the end of the day. Should coincide with next day’s beginningOfDayStock. |
| safetyStock | Float |
The recommended safety stock. |
| serviceLevel | Float |
The service level for which the simulated stock was computed for this product_id. For a full simulation period, we should have the same service level. Each service level will be simulated for the simulation period. |
SimulatedPlot type
| Attribute | Type | Description |
|---|---|---|
| date | Date |
YYYY-MM-DD |
| endOfDayStock | Float |
Quantity in stock at the end of the day (simulated stock). |
| adhocDemand | Float |
Ad-hoc demand for the day. |
| tranches | Float |
Quantity of tranches (fixed demand) shipped during the day. |
| replenishmentProposal | Float |
Quantity proposed for replenishment (PIM). |
| safetyStock | Float |
Quantity of safety stock meant to cover the estimated supplier lead time and internal processing days. |
| realStock | Float |
Real stock at the end of the day. |
| serviceLevel | Float |
Service level from PIM. |
analysisDataViewerUrl
Returns a URL for viewing analysis data generated by a process.
Arguments
| Argument | Type | Description |
|---|---|---|
| organizationId | ID! |
Mandatory. The identifier of the organization. |
| replenishmentProposalId | ID! |
Mandatory. The identifier of the replenishment proposal. |
| processId | ID! |
Mandatory. The identifier of a process (which belongs to replenishmentProposalId) that finished with status DONE. |
| expiresIn | Int |
Optional. The interval, in seconds, after which the URL will expire. |
Result
The result is a URL having the Uri type.
organizations
Returns a list of active organizations defined for the given tenant.
Result
The result is an array of Organization.
Organization type
| Attribute | Type | Description |
|---|---|---|
| id | ID! |
Specifies the organization’s unique identifier. |
| name | String |
Specifies the organization’s name. |
replenishmentProposals
Returns the list of replenishment proposals for the organization ID supplied as input.
Arguments
| Argument | Type | Description |
|---|---|---|
| organizationId | ID! |
Mandatory. The identifier of the organization to which the replenishment proposal belongs. |
| filter | ReplenishmentProposalsFilter |
Optional. Supplies filtering criteria to the query. |
ReplenishmentProposalsFilter input
| Argument | Type | Description |
|---|---|---|
| createdAt | DateFilter |
Optional. Provides filtering options to the query. |
DateFilter input
| Attribute | Type | Description |
|---|---|---|
| from | Date |
Optional. Specifies a date in YYYY-MM-DD format. If provided, only records where the creation date starts with this date will be retrieved. |
| to | Date |
Optional. Specifies a date in YYYY-MM-DD format. If provided, the query will retrieve only records having the creation date up to and including this date. |
Result
The result is an array of objects of type ReplenishmentProposal.
Example
query ReplenishmentProposals ($organizationId:ID!, $filter:ReplenishmentProposalsFilter, $fileId:ID, $processId:ID) {
replenishmentProposals(organizationId:$organizationId, filter:$filter) {
id
organizationId
targetMonth
splitByCustomer
splitByIndustry
files (id: $fileId) {
id fileType name contentLength uploadUrl downloadUrl createdAt
}
processes (id: $processId) {
id
status
dataRange { from to }
targetMonth
errorMessages
productCentricResult { id name contentLength createdAt downloadUrl }
customerCentricResult { id name contentLength createdAt downloadUrl }
industryCentricResult { id name contentLength createdAt downloadUrl }
totals {
csvLines { customerOrders supplierOrders allFileLines }
}
createdAt
}
createdAt
}
}
{
"organizationId": "YOUR_ORGANIZATION_ID",
"filter": {
"createdAt": {
"from": "2025-01-01",
"to": "2025-12-31"
}
}
}
replenishmentProposal
Retrieves a single replenishment proposal by ID.
Arguments
| Argument | Type | Description |
|---|---|---|
| id | ID! |
Mandatory. The ID of the replenishment proposal to retrieve. |
Result
See the ReplenishmentProposal type.
version
Returns the API version.
Result
The result is of type String.
Mutations
computeReplenishmentProposal
Starts a process that computes a replenishment proposal, based on its current input data. Running this mutation will start a new process on each run.
MASTER_PARAMETERS_FILE_REQUIRED or RECEPTIONS_FILE_REQUIRED (see Error codes). Only the presence of these files is checked at this stage; their content is validated later, during computation.
Arguments
| Attribute | Type | Description |
|---|---|---|
| id | ID! |
Mandatory. The identifier of the replenishment proposal to be computed. |
Result
See the Process type.
createReplenishmentProposal
Creates a replenishment proposal.
Arguments
| Attribute | Type | Description |
|---|---|---|
| organizationId | ID! |
Mandatory. The identifier of the organization for which this replenishment proposal is created. |
| input | CreateReplenishmentProposalInput! |
Mandatory. Provides the actual input data to the mutation. |
CreateReplenishmentProposalInput input
| Attribute | Type | Description |
|---|---|---|
| targetMonth | Month! |
Mandatory. The month for which the replenishment proposal is computed. The value must have the YYYY-MM format. |
| backdatedTargetMonth | Month |
Optional. If provided, the replenishment proposal will compute data for every month starting with backdatedTargetMonth month up to and including targetMonth. This is useful for simulating backdated calculations in order to compare them against real data. NOTE: The backdatedTargetMonth must have the YYYY-MM format and be a month prior to targetMonth. NOTE: Setting this parameter is meaningful only if you set computeAnalysisData to true. Otherwise, it is ignored. |
| splitByCustomer | Boolean |
Optional. If this value is supplied, computing the proposal will generate a CSV output file with results grouped by customer ID. This parameter is mutually exclusive with splitByIndustry. It is not recommended to set this parameter when the input CSV data is extremely large. |
| splitByIndustry | Boolean |
Optional. If this value is supplied, computing the proposal will generate a CSV output file with results grouped by industry code ID. This parameter is mutually exclusive with splitByCustomer. It is not recommended to set this parameter when the input CSV data is extremely large. |
| computeAnalysisData | Boolean |
Optional. If this value is supplied, computing the proposal will generate Predictive Analysis Data queryable through the analysisData query. When you set this parameter to true and don’t set a backdatedTargetMonth, the Analysis Data computes a back-dated simulation of the past 12 months (that is, the implicit backdatedTargetMonth = targetMonth - 12 months). To run the back-dated simulation for a different period in the past, set the backdatedTargetMonth parameter explicitly. |
| demandCoverageType | DemandCoverageType |
Optional. Specifies whether customers place orders only on business days or on any calendar day. Valid values: Business - orders are placed from Monday through Friday, excluding public holidays. Calendar - customer orders are placed on any calendar day. |
| supplierOrdersInterval | Int |
Optional. The average frequency, in calendar days, with which the distribution company places supplier orders. The default value is 10. |
| monthsAheadSmoothing | Int |
Optional. Months ahead to consider for smoothing the target month demand when supplier orders interval type is Explicit. If not provided, the default value is 3. |
| leadTimeRecency | Int |
Optional. Months of supply lead time history to consider. The default value is 6. |
| supplierOrderReceptionDays | Int |
Optional. Processing time for reception of supply order. The default value is 1. |
| imputeMissingSales | Boolean |
Optional. Adjust/impute sales data when demand is missing due to lack of inventory (e.g. online shop). The default value is false. NOTE: This parameter is mutually exclusive with splitByCustomer and splitByIndustry. |
| supplyLeadTimeOffset | Float |
Optional. The fraction by which the mean supply lead time is increased for planning. For example, 0.1 plans as though suppliers deliver 10% slower than their history shows. Accepts a number from 0 to 3, inclusive. The default value is 0. The value applies to every supplier without a usable supply_lead_time_offset of its own in MasterParameters.csv. A supplier’s own value takes priority over this one; the two are not added together. |
Result
ReplenishmentProposal type
| Attribute | Type | Description |
|---|---|---|
| id | ID |
The identifier of the replenishment proposal. |
| organizationId | ID |
The identifier of the organization for which this replenishment proposal was created. |
| targetMonth | Month |
The target month for which the replenishment proposal was created. |
| backdatedTargetMonth | Month |
The backdated target month supplied as input when creating the proposal. If the proposal was created with computeAnalysisData = true, then the backdated target month applies implicitly, in which case this field indicates the implicit value. |
| splitByCustomer | Boolean |
If true, indicates that the replenishment proposal was created with an option to produce a separate output file with results grouped by customer. |
| splitByIndustry | Boolean |
If true, indicates that the replenishment proposal was created with an option to produce a separate output file with results grouped by industry. |
| computeAnalysisData | Boolean |
If true, indicates that the replenishment proposal was created with the computeAnalysisData option enabled. |
| demandCoverageType | DemandCoverageType |
Indicates whether customers place orders only on business days or on any calendar day. Valid values: Business - orders are placed from Monday through Friday, excluding public holidays. Calendar - customer orders are placed on any calendar day. |
| supplierOrdersInterval | Int |
The frequency, in calendar days, with which the distribution company places supplier orders. |
| supplierOrdersIntervalType | SupplierOrdersIntervalType |
The type used to determine the supplier orders interval. This is an enum value with a single member: Explicit. |
| monthsAheadSmoothing | Int |
Months ahead to consider for smoothing the target month demand. |
| leadTimeRecency | Int |
Months of supply lead time history to consider. |
| supplierOrderReceptionDays | Int |
Processing time for reception of supply order. |
| imputeMissingSales | Boolean |
Indicates if the replenishment proposal was created with the imputeMissingSales option enabled or disabled. |
| supplyLeadTimeOffset | Float |
The supply lead time offset that applies to every supplier without a usable value of its own in MasterParameters.csv. 0 if the proposal was created without one. |
files (id: ID) |
[File] |
The list of input files associated with the current proposal. You can optionally filter files by ID, by supplying the file ID as input argument to this field. |
processes (id: ID) |
[Process] |
The list of processes associated with the current proposal. You can optionally filter processes by ID, by supplying the process ID as input argument to this field. |
| createdAt | DateTime |
The date and time when the replenishment proposal was created. |
SupplierOrdersIntervalType enum
| Value | Description |
|---|---|
| Explicit | The supplier orders interval is explicitly set by the user at creation. |
File type
| Attribute | Type | Description |
|---|---|---|
| id | ID |
The unique identifier of the file. You can use this ID to refer to the file also through the File Management Service. |
| fileType | CsvFileType |
The type of data reported by the file. Valid values: CustomerOrders, SupplierOrders, Deliveries, MasterParameters, Receptions, Stock. |
| name | String |
The file name. |
| contentLength | Float |
The file size in bytes. |
uploadUrl(expiresIn: Int) |
Uri |
The URL at which the file content can be uploaded. Note that the upload URL expires after the number of seconds supplied in the expiresIn parameter (default is 30 seconds). The file size limit for upload is 5 GB. |
downloadUrl(expiresIn: Int) |
Uri |
The URL at which the file content can be downloaded. Note that the download URL expires after the number of seconds supplied in the expiresIn parameter. |
| createdAt | DateTime |
The date and time when the file was created. |
Process type
| Attribute | Type | Description |
|---|---|---|
| id | ID |
The unique identifier of the process. |
| status | ReplenishmentProposalStatus |
The status of the replenishment proposal. Valid values: NEW - computation has not started yet, INPROCESS - computation is in progress, DONE - computation has completed without errors, ERROR - computation has completed with errors. |
| dataRange | DataRange |
The date range for which the replenishment proposal was created. |
| targetMonth | Month |
The month for which the replenishment proposal was created, in YYYY-MM format. |
| backdatedTargetMonth | Month |
The backdated target month. Present if the backdatedTargetMonth input parameter was supplied as input when creating the proposal. |
| errorMessages | [String] |
The list of error messages, if applicable. |
| warnings | [String] |
The list of warnings, if applicable. |
| analyticsLog | [String] |
The analytics log produced by the analysis-data computation, as a list of lines. Present only when the proposal was computed with computeAnalysisData = true (that is, on the analysis/optimal-service-level path); otherwise absent. |
| productCentricResult | ResultFile |
The standard output file created by the process. In the standard file, results are grouped by product ID. |
| customerCentricResult | ResultFile |
An output file where results are grouped by customer ID. This file is created only if the replenishment proposal was created with the option splitByCustomer = true. |
| industryCentricResult | ResultFile |
An output file where results are grouped by industry code ID. This file is created only if the replenishment proposal was created with the option splitByIndustry = true. |
| optimalServiceLevels | ResultFile |
An output file that contains results with optimal service levels. This file is created only if the replenishment proposal was created with the option computeAnalysisData = true. |
| totals | Totals |
The totals computed by this process. |
| createdAt | DateTime |
The date and time when the process was created. |
| completedAt | DateTime |
The date and time when the process — including its analysis-data computation — completed (the transition to DONE). Absent until the process completes, and not set for processes that finish with status ERROR. |
DataRange type
| Attribute | Type | Description |
|---|---|---|
| from | Date |
The starting date of the range. |
| to | Date |
The ending date of the range. |
ResultFile type
| Attribute | Type | Description |
|---|---|---|
| id | ID |
The unique identifier of the file. You can use this ID to refer to the file also through the File Management Service. |
| name | String |
The file name. |
| contentLength | Float |
The file size in bytes. |
downloadUrl(expiresIn: Int) |
Uri |
The URL at which the file content can be downloaded. Note that the download URL expires after the number of seconds supplied in the expiresIn parameter. |
| createdAt | DateTime |
The date and time when the file was created. |
Totals type
| Attribute | Type | Description |
|---|---|---|
| csvLines | CsvFileLines |
The number of lines in each of the CSV files, as a CsvFileLines type. |
CsvFileLines type
| Attribute | Type | Description |
|---|---|---|
| customerOrders | Float |
Reports the number of lines in CustomerOrders.csv. |
| supplierOrders | Float |
Reports the number of lines in SupplierOrders.csv. |
| allFileLines | Float |
Reports the number of lines in both files above. |
deleteFile
Deletes a previously uploaded CSV file.
Arguments
| Attribute | Type | Description |
|---|---|---|
| replenishmentProposalId | ID! |
Mandatory. The identifier of the replenishment proposal. |
| fileId | ID! |
Mandatory. The identifier of the CSV file to be deleted. |
Result
DeletedFile type
| Attribute | Type | Description |
|---|---|---|
| id | ID |
The unique identifier of the file. You can use this ID to refer to the file also through the File Management Service. |
| fileType | CsvFileType |
The type of data reported by the file. Valid values: CustomerOrders, SupplierOrders, Deliveries, MasterParameters, Receptions, Stock. |
| name | String |
The file name. |
| createdAt | DateTime |
The date and time when the file was created. |
deleteProcess
Deletes a computation process and the result files.
Arguments
| Attribute | Type | Description |
|---|---|---|
| replenishmentProposalId | ID! |
Mandatory. The identifier of the replenishment proposal. |
| processId | ID! |
Mandatory. The identifier of the process to be deleted. |
Result
See the Process type.
deleteReplenishmentProposal
Deletes a replenishment proposal, including all its input and output files and processes.
Arguments
| Attribute | Type | Description |
|---|---|---|
| id | ID! |
Mandatory. The ID of the replenishment proposal to be deleted. |
Result
See the ReplenishmentProposal type.
Example
mutation DeleteReplenishmentProposal ($id:ID!) {
deleteReplenishmentProposal(id:$id) {
id
}
}
{
"id": "YOUR_REPLENISHMENT_PROPOSAL_ID"
}
killProcess
Stops a running computation process.
Arguments
| Attribute | Type | Description |
|---|---|---|
| replenishmentProposalId | ID! |
Mandatory. The identifier of the replenishment proposal. |
| processId | ID! |
Mandatory. The identifier of the process to be stopped. |
Result
See the Process type.
prepareFile
Generates a URL at which you can upload a CSV file to be used as input to the computation. Run this mutation for each CSV file that is to be supplied as input for a replenishment proposal.
Arguments
| Attribute | Type | Description |
|---|---|---|
| replenishmentProposalId | ID! |
Mandatory. The identifier of the replenishment proposal. |
| input | PrepareFileInput! |
Mandatory. Supplies the input data to the mutation. |
PrepareFileInput input
| Attribute | Type | Description |
|---|---|---|
| fileType | CsvFileType! |
Mandatory. This is an enumeration that identifies the type of the CSV file. Valid values: CustomerOrders, SupplierOrders, Deliveries, MasterParameters, Receptions, Stock. |
| name | String |
Optional. Supplies the name of the CSV file. |
Result
See the File type.
Error codes
See Conventions for the error format and the codes shared across all services. This service can also return the codes listed below, grouped by the object they concern. The Returned by column names the operations and fields that report each code.
Replenishment proposals
| Code | Meaning | Returned by |
|---|---|---|
REPLENISHMENT_PROPOSAL_NOT_FOUND |
No replenishment proposal exists for the identifier supplied. | replenishmentProposal, analysisData, analysisDataViewerUrl, computeReplenishmentProposal, prepareFile, deleteFile, deleteProcess, killProcess, deleteReplenishmentProposal |
TARGET_MONTH_ORDER_INVALID |
backdatedTargetMonth is not earlier than targetMonth. |
createReplenishmentProposal |
SUPPLIER_ORDERS_INTERVAL_NOT_POSITIVE |
supplierOrdersInterval is zero or negative. |
createReplenishmentProposal |
MONTHS_AHEAD_SMOOTHING_NOT_POSITIVE |
monthsAheadSmoothing is zero or negative. |
createReplenishmentProposal |
SUPPLIER_ORDER_RECEPTION_DAYS_NOT_POSITIVE |
supplierOrderReceptionDays is zero or negative. |
createReplenishmentProposal |
LEAD_TIME_RECENCY_NOT_POSITIVE |
leadTimeRecency is zero or negative. |
createReplenishmentProposal |
SUPPLY_LEAD_TIME_OFFSET_OUT_OF_RANGE |
supplyLeadTimeOffset is less than 0 or greater than 3. |
createReplenishmentProposal |
IMPUTE_MISSING_SALES_EXCLUDES_SPLIT |
imputeMissingSales is combined with splitByCustomer or splitByIndustry. |
createReplenishmentProposal |
SPLIT_BY_CUSTOMER_AND_INDUSTRY |
splitByCustomer and splitByIndustry are both set to true. |
createReplenishmentProposal |
Organizations
| Code | Meaning | Returned by |
|---|---|---|
ORGANIZATION_NOT_FOUND |
No organization exists for the identifier supplied. | replenishmentProposals, analysisDataViewerUrl, createReplenishmentProposal, computeReplenishmentProposal |
ORGANIZATION_LOOKUP_FAILED |
The list of organizations could not be retrieved. | organizations, replenishmentProposals, analysisDataViewerUrl, createReplenishmentProposal, computeReplenishmentProposal |
Processes
| Code | Meaning | Returned by |
|---|---|---|
PROCESS_NOT_FOUND |
No process exists for the identifier supplied. | analysisData, analysisDataViewerUrl, deleteProcess, killProcess, deleteReplenishmentProposal, ReplenishmentProposal.processes |
PROCESS_NOT_IN_REPLENISHMENT_PROPOSAL |
The process belongs to a different replenishment proposal than the one supplied. | deleteProcess, killProcess, deleteReplenishmentProposal, ReplenishmentProposal.processes |
PROCESS_RUNNING |
The process is still running. Stop it with killProcess before you delete it. |
deleteProcess |
PROCESS_RESULTS_ALREADY_GENERATED |
The process has already produced results, so it can no longer be stopped. | deleteProcess, killProcess, deleteReplenishmentProposal |
PROCESS_START_FAILED |
The computation could not be started. | computeReplenishmentProposal |
PROCESS_ID_MISSING |
The process has no identifier, so its result files cannot be read. | productCentricResult, customerCentricResult, industryCentricResult, and optimalServiceLevels fields of the Process type |
Input files
| Code | Meaning | Returned by |
|---|---|---|
MASTER_PARAMETERS_FILE_REQUIRED |
No MasterParameters file has been added to the replenishment proposal. | computeReplenishmentProposal |
RECEPTIONS_FILE_REQUIRED |
No Receptions file has been added to the replenishment proposal. | computeReplenishmentProposal |
STOCK_FILE_REQUIRED |
No Stock file has been added to the replenishment proposal. A Stock file is required when imputeMissingSales or computeAnalysisData is true. |
computeReplenishmentProposal |
Files
| Code | Meaning | Returned by |
|---|---|---|
FILE_NOT_FOUND |
No file with the identifier supplied is attached to the replenishment proposal. | deleteFile, ReplenishmentProposal.files |
FILE_CREATE_FAILED |
The file could not be created. | prepareFile |
FILE_DELETE_FAILED |
A file could not be deleted. | deleteFile, deleteProcess, deleteReplenishmentProposal |
FILE_UPLOAD_URL_FAILED |
No upload URL could be generated for the file. | uploadUrl field of the File type |
FILE_DOWNLOAD_URL_FAILED |
No download URL could be generated for the file. | downloadUrl field of the File and ResultFile types |
FILE_ID_MISSING |
The file has no identifier, so no URL can be generated for it. | uploadUrl field of the File type, downloadUrl field of the File and ResultFile types |
Analysis data
| Code | Meaning | Returned by |
|---|---|---|
ANALYSIS_DATA_UNAVAILABLE |
The process has no analysis data, for example because the replenishment proposal was computed with computeAnalysisData = false. |
analysisData, analysisDataViewerUrl |
PRODUCT_NOT_FOUND |
No product exists for the identifier supplied. | product field of the AnalysisData type |
SPLIT_FILTER_AMBIGUOUS |
The SplitFilter sets both customerId and industryCode. |
monthlyDemand and monthlyForecast fields of the Product type |
SPLIT_FILTER_CUSTOMER_REQUIRED |
The data is split by customer, and the SplitFilter has no customerId. |
monthlyDemand and monthlyForecast fields of the Product type |
SPLIT_FILTER_INDUSTRY_REQUIRED |
The data is split by industry, and the SplitFilter has no industryCode. |
monthlyDemand and monthlyForecast fields of the Product type |
SPLIT_FILTER_NOT_APPLICABLE |
The data is not split by customer or industry, and a SplitFilter was supplied. |
monthlyDemand and monthlyForecast fields of the Product type |
Formats and access
| Code | Meaning | Returned by |
|---|---|---|
INVALID_MONTH_FORMAT |
A Month value does not match the YYYY-MM format, or names a month outside 01–12. For computeReplenishmentProposal, the proposal’s stored targetMonth or backdatedTargetMonth is malformed. Delete the proposal and create a new one. |
Any operation or field that takes a Month value, computeReplenishmentProposal |
SERVICE_ACCESS_TOKEN_UNAVAILABLE |
The service could not authorize a request it makes to another SBS service on your behalf. | organizations, replenishmentProposals, analysisDataViewerUrl, createReplenishmentProposal, computeReplenishmentProposal, prepareFile, uploadUrl field of the File type |
A malformed value is rejected with the same code whether you pass it as a variable or write it into the operation text.
AI agent access (MCP)
The service serves its queries as tools to AI agent clients over the Model Context Protocol (MCP), a JSON-RPC 2.0 protocol through which a client reads a catalog of tools and calls them by name. Agent clients such as Claude Code connect to https://predictive-inventory-management-api.socrate.io/mcp.
Access
The MCP endpoint is on the same host as the GraphQL endpoint and accepts the same credentials:
- A tenant-level service access key, in the
x-api-keyheader. - A service access token, in the
Authorizationheader asBearer YOUR_SERVICE_ACCESS_TOKEN.
The endpoint speaks protocol revision 2026-07-28 and accepts protocol requests as POST only. It is stateless: every request carries its own credentials, and there is no handshake or session to open first. Your agent client must support revision 2026-07-28.
For connection instructions, open https://predictive-inventory-management-api.socrate.io/mcp in a browser. The page needs no credential.
Tools
The catalog holds one tool per query of this service:
| Tool | Required arguments | include values |
|---|---|---|
version |
— | — |
organizations |
— | — |
replenishmentProposals |
organizationId |
See Proposal include values |
replenishmentProposal |
id |
See Proposal include values |
analysisData |
organizationId, replenishmentProposalId, and processId |
warnings, analyticsLog, customers, industries, and diagnostics |
analysisDataViewerUrl |
organizationId, replenishmentProposalId, and processId |
— |
The optional arguments of each query (filter, expiresIn) are optional arguments of its tool.
The catalog a caller receives lists only the tools whose query the scope of its key or token allows. If a service access denial blocks a query, your agent does not see a tool for it. A tool call runs the query under the caller’s own credentials and returns the data that the equivalent GraphQL query returns for that caller. Every tool is marked read-only (readOnlyHint is true), and answers from SBS alone, without calling any system outside SBS (openWorldHint is false).
Optional result fields
By default, a tool returns compact records. You request the remaining fields by naming their paths in the tool’s optional include argument:
- Replenishment proposals. Without
include,replenishmentProposalsandreplenishmentProposalreturn each proposal’s own fields, such asid,targetMonth, andcreatedAt. Input files, processes, the messages and logs of a process, the result files of a process, and download URLs are returned only when named. - Analysis data. Without
include,analysisDatareturns the run’s headline fields,dataRange,globalScores, and the first page ofproductsand ofperformance, each with itsitemsandnextToken. The listswarnings,analyticsLog,customers,industries, anddiagnosticsare returned only when named.
A path is a sequence of field names separated by dots. Naming a path returns that field with its default content. Naming a path inside an optional field returns only that inner field: include: ["files.downloadUrl"] returns each file’s downloadUrl without its id or name. To receive the input files together with their download URLs, name both paths: include: ["files", "files.downloadUrl"].
No tool returns file upload URLs.
Proposal include values
The replenishmentProposals and replenishmentProposal tools accept these values:
| Value | Returns |
|---|---|
files |
The proposal’s input files |
files.downloadUrl |
The download URL of each input file |
processes |
The proposal’s processes |
processes.errorMessages |
The error messages of each process |
processes.warnings |
The warnings of each process |
processes.analyticsLog |
The analytics log of each process |
processes.productCentricResult |
The product-centric result file of each process |
processes.productCentricResult.downloadUrl |
The download URL of the product-centric result file |
processes.customerCentricResult |
The customer-centric result file of each process |
processes.customerCentricResult.downloadUrl |
The download URL of the customer-centric result file |
processes.industryCentricResult |
The industry-centric result file of each process |
processes.industryCentricResult.downloadUrl |
The download URL of the industry-centric result file |
processes.optimalServiceLevels |
The optimal service levels result file of each process |
processes.optimalServiceLevels.downloadUrl |
The download URL of the optimal service levels result file |
Large results
The diagnostics of a large run can exceed the size limit of a tool result. In that case, an analysisData call that names diagnostics fails with a message that states the limit. The analysisData tool returns the first page of products and of performance. To read a large run in full, request the following pages through the analysisData GraphQL query with nextToken, or open the run in the viewer whose URL the analysisDataViewerUrl tool returns.
Documentation resources
Besides its tools, the endpoint publishes, as addresses, this page and the API conventions page.
Connecting an agent client
To add the endpoint to Claude Code, run:
claude mcp add --transport http predictive-inventory-management https://predictive-inventory-management-api.socrate.io/mcp --header "x-api-key: YOUR_ACCESS_KEY"
Other agent clients take the same URL and header in their own configuration.
Example
An agent client builds the protocol requests for you. To call a tool directly over HTTP, send a POST request that names the protocol revision both in the MCP-Protocol-Version header and in the request’s _meta, the method in the Mcp-Method header, and, for a tool call, the tool in the Mcp-Name header:
POST /mcp HTTP/1.1
Host: predictive-inventory-management-api.socrate.io
Content-Type: application/json
Accept: application/json
x-api-key: YOUR_ACCESS_KEY
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: replenishmentProposal
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
},
"name": "replenishmentProposal",
"arguments": {
"id": "YOUR_PROPOSAL_ID",
"include": ["files", "files.downloadUrl"]
}
}
}
The proposal is returned in structuredContent, and as the same JSON text in content. The response below is shortened to one input file:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"content": [
{ "type": "text", "text": "{\"id\":\"YOUR_PROPOSAL_ID\", ...}" }
],
"structuredContent": {
"id": "YOUR_PROPOSAL_ID",
"organizationId": "YOUR_ORGANIZATION_ID",
"targetMonth": "2026-10",
"backdatedTargetMonth": "2025-10",
"splitByCustomer": false,
"splitByIndustry": false,
"computeAnalysisData": true,
"demandCoverageType": "Calendar",
"supplierOrdersInterval": 1,
"supplierOrdersIntervalType": "Explicit",
"monthsAheadSmoothing": 1,
"leadTimeRecency": 12,
"supplierOrderReceptionDays": 1,
"imputeMissingSales": false,
"supplyLeadTimeOffset": 0,
"files": [
{
"id": "YOUR_FILE_ID",
"fileType": "Stock",
"name": "Stock.csv",
"contentLength": 14839,
"downloadUrl": "YOUR_DOWNLOAD_URL",
"createdAt": "2026-10-07T06:10:13.189Z"
}
],
"createdAt": "2026-10-07T06:08:56.352Z"
}
}
}
Appendix 1: Input structure
To compute a minimal replenishment proposal (without analysis data or optimal service levels), the following CSV files are accepted as input:
- MasterParameters.csv (required)
- CustomerOrders.csv (required)
- SupplierOrders.csv (required)
- Receptions.csv (required)
- Stock.csv (optional, required only if imputeMissingSales = true)
To compute a replenishment proposal with analysis data or optimal service levels, the following files are accepted as input:
- MasterParameters.csv (required) - This file ensures that the analysis data charts operate with human-readable product names and codes in addition to product IDs.
- CustomerOrders.csv (required)
- SupplierOrders.csv (required)
- Deliveries.csv (required)
- Receptions.csv (required)
- Stock.csv (required)
You may supply multiple files of the same type as input as long as they follow the structure described below. Note the following:
- Each CSV file is comma-separated.
- The first row of each CSV file is the header row. It must name every column listed in that file’s table below, spelled exactly as shown and in the same order. A file with a missing, extra, renamed, or reordered column is rejected when the replenishment proposal is computed: the process ends with status ERROR.
The Requirement column of each table applies to the cell values, not to the column. Every column is present in the header row, whatever its requirement:
- Mandatory: every row has a value.
- Optional: the cell may be empty.
- Conditional: the cell is required only in the situation that the column’s description names.
The following sections describe the structure of all input files.
CustomerOrders.csv
| Column | Type | Requirement | Description |
|---|---|---|---|
| product_id | String | Mandatory | The unique product identifier. Must not contain spaces. |
| customer_id | String | Mandatory | The customer identifier. Must not contain spaces. |
| industry_code_id | String | Optional | The industry code identifier. Must not contain spaces. |
| product_group_id | String | Optional | The product group identifier. Must not contain spaces. |
| is_return | Boolean | Mandatory | Indicates whether the order was a return. Valid values: true, false. |
| order_date | String | Mandatory | The date when the order was placed, in YYYY-MM-DD format. |
| order_quantity | Float | Mandatory | The quantity of products ordered. |
| supplier_id | String | Mandatory | The provider identifier. |
| promised_date | String | Conditional | The date of promised delivery, in YYYY-MM-DD format. Required only when computing the replenishment proposal with simulator option (that is, with an explicit backdatedTargetMonth). For all other cases, the column should still be present but may be empty. |
| order_rule | String | Mandatory | The order type. Valid values: Fixed Tranche, Adhoc Demand. Only Adhoc Demand rows count as demand. Fixed Tranche rows mark planned tranche demand, which the forecast does not use. |
| customer_code | String | Optional | The human-readable customer code. Carried for reporting; not used by the computation. |
| industry_code | String | Optional | The human-readable industry code. Carried for reporting; not used by the computation. |
| lost_sales | Integer | Optional | The quantity of sales missed due to lack of inventory, as a whole number. |
| warehouse_name | String | Mandatory | The name of the warehouse associated with the order. |
| organization_name | String | Mandatory | The name of the organization associated with the order. |
SupplierOrders.csv
| Column | Type | Requirement | Description |
|---|---|---|---|
| product_id | String | Mandatory | The unique product identifier. Must not contain spaces. |
| is_return | Boolean | Mandatory | Indicates whether the order was a return. Valid values: true, false. |
| order_date | String | Mandatory | The date when the order was placed, in YYYY-MM-DD format. |
| order_quantity | Float | Mandatory | The quantity of products ordered. |
| lead_time | Integer | Mandatory | The number of days in which the products were delivered. |
| lead_time_contractual | Integer | Mandatory | The lead time (in days) agreed in the supplier contract. |
| supplier_id | String | Mandatory | The identifier of the supplier. |
| promised_date | String | Conditional | The date of promised delivery, in YYYY-MM-DD format. Required only when computing the replenishment proposal with simulator option (that is, with an explicit backdatedTargetMonth). For all other cases, the column should still be present but may be empty. |
Deliveries.csv
| Column | Type | Requirement | Description |
|---|---|---|---|
| product_id | String | Mandatory | The unique product identifier. Must not contain spaces. |
| quantity | Float | Mandatory | The quantity of delivered products. |
| order_date | String | Mandatory | The date when the order was placed, in YYYY-MM-DD format. |
| shipment_date | String | Mandatory | The date of the shipment, in YYYY-MM-DD format. |
| promised_date | String | Mandatory | The date of promised delivery, in YYYY-MM-DD format. |
| order_rule | String | Mandatory | Indicates the shipment type. Valid values: Fixed Tranche, Adhoc Demand. |
Receptions.csv
| Column | Type | Requirement | Description |
|---|---|---|---|
| product_id | String | Mandatory | The unique product identifier. Must not contain spaces. |
| quantity | Float | Mandatory | The quantity of delivered products. |
| order_date | String | Mandatory | The date when the order was placed, in YYYY-MM-DD format. |
| delivery_date | String | Mandatory | The date of reception, in YYYY-MM-DD format. |
| promised_date | String | Mandatory | The date of promised delivery, in YYYY-MM-DD format. |
| is_return | Boolean | Mandatory | Indicates whether the reception is a return. Valid values: true, false. |
| supplier_id | String | Mandatory | The identifier of the supplier. |
Stock.csv
| Column | Type | Requirement | Description |
|---|---|---|---|
| product_id | String | Mandatory | The unique product identifier. Must not contain spaces. |
| date | String | Mandatory | The date of stock movement, in YYYY-MM-DD format. |
| doc_id | String | Optional | The document ID. Used for sorting. If null, this line represents the initial stock. |
| stock_in | Float | Mandatory | The quantity that entered the stock. |
| stock_out | Float | Mandatory | The quantity that exited the stock. |
| ending_stock | Float | Mandatory | The final stock of the day. |
MasterParameters.csv
The header row must list exactly the columns below, in this order. A file whose header omits a column is rejected.
| Column | Type | Requirement | Description |
|---|---|---|---|
| product_id | String | Mandatory | The product identifier from your ERP system. |
| product_code | String | Mandatory | The product code from your ERP system. |
| product_name | String | Mandatory | The product name from your ERP system. |
| equivalent_product_id | String | Optional | The associated product identifier. For example, this could be an old id when a product is replaced with a new one. |
| product_group_id | String | Optional | The product group identifier. |
| supplier_id | String | Conditional | The supplier identifier. If is_default_supplier = true, then supplier_id is mandatory. Optional otherwise. |
| is_default_supplier | Boolean | Mandatory | Indicates if the current supplier is the default supplier. Valid values: true, false. If this value is true, then the supplier_id must be present. NOTE: A product may have multiple suppliers (in which case multiple products rows exist). However, any single product may have only one default supplier. |
| lead_time_recency | Number(int) | Mandatory | Months of supply lead time history to consider. |
| supply_order_reception_days | Number(int) | Mandatory | The processing time for reception of supply order. |
| supply_order_freq_days | Number(int) | Mandatory | The average time, in days, between supply orders in a month (for example, 0, 7, 10, 15). |
| lead_time_contractual | Number(int) | Mandatory | The lead time, in days, agreed in the supplier contract. Set to 0 when not defined in the ERP. This is distinct from the observed lead_time_recency. |
| supply_lead_time_offset | Float | Optional | The fraction by which the supplier’s mean supply lead time is increased for planning. For example, 0.1 plans as though the supplier delivers 10% slower than its history shows. Accepts a number from 0 to 3, inclusive, with a decimal point as separator. The value applies per supplier: if rows of the same supplier carry different values, one of them applies to all of that supplier’s products. An empty, non-numeric, or out-of-range value means the proposal’s supplyLeadTimeOffset applies, which is 0 if the proposal was created without one. The column must be present, but the cell may be empty. |
Appendix 2: Output structure
The result of computing a replenishment proposal is 1-4 CSV files, depending on the input parameters you specified when creating the proposal.
- product_centric.csv - this file is created if you did not set
splitByCustomer= true orsplitByIndustry= true. It contains results grouped by product. - customer_centric.csv - this file is created only if you created the replenishment proposal with the option
splitByCustomer= true; it contains results grouped by customer ID. - industry_centric.csv - this file is created only if you created the replenishment proposal with the option
splitByIndustry= true; it contains results grouped by industry ID. - optimal_service_level.csv - this file is created only if you created the replenishment proposal with the option
computeAnalysisData= true.
The following sections describe the structure of all output files.
product_centric.csv
| Column | Type | Description |
|---|---|---|
| product_id | String | The unique product identifier. |
| customer_id | String | The customer identifier. |
| industry_code_id | String | The industry code identifier. |
| product_group_id | String | The product group identifier. |
| target_month | String | The month for which the levels are calculated (year-month). |
| service_level | Float | The percentage level of service to cover. It expresses the level of coverage against the combined uncertainty in historical demand (with parameters monthly_sales_meand_prediction, monthly_sales_std_prediction) and historical lead time (with parameters lead_time_mean, lead_time_std, lead_time_min). |
| rop_estimate | Integer | The re-order point trigger estimate based on the service level, for simulation of continuous review systems (for example, orders placed at any time). |
| min_estimate | Integer | The safety stock level for lead time + supply frequency (units to cover variation in demand and lead time). |
| max_estimate | Integer | The replenish stock level for lead time + order frequency (units to cover expected + variation in demand and lead time). |
| expected_estimate | Integer | The stock level to cover expected demand and lead time. |
| monthly_sales_service_level_forecast | Integer | The monthly sales forecast at the given service level. This represents the monthly demand given the service level (and the monthly_sales_mean_prediction, monthly_sales_std_prediction). |
| months_with_data | Integer | Number of months with historical data. |
| model | String | The statistical model applied. |
| monthly_sales_mean_prediction | Float | The average sales forecast based on monthly aggregated historical demand data. |
| monthly_sales_std_prediction | Float | The standard deviation of the sales forecast based on monthly aggregated historical demand data. |
| lead_time_mean | Float | The historical average of supply lead time. Measured in fractions of days, it represents the average days in lead times for this product and supplier. |
| lead_time_std | Float | The historical standard deviation of supply lead time. Measured in fractions of days, it represents the standard deviation around the lead_time_mean, observed in lead times for this product and supplier |
| lead_time_min | Float | The historical minimum of supply lead time. Measured in fractions of days. |
| lead_time_recency | Integer | The number of months of supply lead time history considered for this row’s supplier. |
| supply_order_freq_days | Integer | The average time between supply orders, measured in fractions of days; the order_freq_estimate is based on this number of days, on the estimated monthly demand for the scenario, and on the service level. |
| supply_order_reception_days | Integer | The number of days between the reception of a supply order and the stock becoming available, for this row’s supplier. |
| supply_lead_time_offset | Float | The fraction by which the mean supply lead time was increased when this row was computed: the supplier’s own value from MasterParameters.csv or, failing that, the proposal’s supplyLeadTimeOffset. 0 means no offset was applied. lead_time_mean reports the historical value, without the offset. |
customer_centric.csv
This file has the same structure as product_centric.csv, with results grouped by the customer_id column.
industry_centric.csv
This file has the same structure as product_centric.csv, with results grouped by the industry_code_id column.
optimal_service_levels.csv
| Column | Type | Description |
|---|---|---|
| product_id | String | The unique product identifier. |
| optimal_service_level | Float | One of the service levels provided - this is an alternative computation of the optimal. |
| type | String | Possible values: out-of-stock-based, hybrid-out-of-stock-over-stock. |
| details | String | Computation details for the optimal service level by type. |
| last_updated | String | Date of last computation (YYYY-MM-DD). |