Product master data
S/4HANA API_PRODUCT_SRV read surfaces — the product, its plant extensions, and its storage-location views. Point an inbound pipeline at these paths unchanged; the field shapes follow a live S/4HANA $metadata.
Base URL: https://mock-server.oscar-int.prc.re · Basic auth procureai / demo
1. Endpoints
All read-only (GET). Row counts are what this host currently serves.
| Entity set | OData | Path | Rows |
|---|---|---|---|
A_Product | v2 | /sap/opu/odata/sap/API_PRODUCT_SRV/A_Product | 80 |
A_ProductPlant | v2 | /sap/opu/odata/sap/API_PRODUCT_SRV/A_ProductPlant | 73 |
A_ProductStorageLocation | v2 | /sap/opu/odata/sap/API_PRODUCT_SRV/A_ProductStorageLocation | 49 |
Product | v4 | /sap/opu/odata4/sap/api_product/srvd_a2x/sap/product/0001/Product | 80 |
Single-entity reads use OData v2 key syntax: A_Product('SKU') and A_ProductPlant(Product='SKU',Plant='KOK2').
2. Query options
| Option | Supported |
|---|---|
$filter | eq, ne, and, or, parentheses, and startswith(). An expression this mock cannot parse falls back to no filter rather than an empty result. |
$top / $skip | Yes, with a paged next link. |
$inlinecount | allpages sets d.__count. |
$expand | to_Description on A_Product only. Navigation from A_ProductPlant to its storage locations is not implemented — read the entity sets separately and join on Product. |
3. Will my pipeline config work here?
Filters taken verbatim from real inbound-pipeline configs, with the rows this host returns for each. A non-zero, non-total count means the filter is genuinely being applied.
| Entity set | $filter | Matched |
|---|---|---|
A_Product | startswith(ProductGroup,'A') and (ProductType eq 'Z100' or ProductType eq 'Z102') | 15 / 80 |
A_ProductPlant | Plant eq 'KOK2' or Plant eq 'KOK6' | 14 / 73 |
A_ProductStorageLocation | Plant eq 'KOK2' or Plant eq 'KOK6' | 10 / 49 |
4. A_Product
One row per material. Carries the commodity classification (ProductGroup) and the base unit.
| Field | Type | Example |
|---|---|---|
Product | string | CW-APC-5L |
ProductType | string | ZDIE |
BaseUnit | string | PCE |
ProductGroup | string | A030102 |
ProductDescription | string | All-purpose cleaner 5L |
CatalogueProductId | string | cleanworks:APC-5L |
{
"d": {
"results": [
{
"Product": "CW-APC-5L",
"ProductType": "ZDIE",
"BaseUnit": "PCE",
"ProductGroup": "A030102",
"ProductDescription": "All-purpose cleaner 5L",
"CatalogueProductId": "cleanworks:APC-5L"
}
]
}
}5. A_ProductPlant
One row per material and plant (SAP MARC) — the material is extended to that plant. It carries no storage location: that is one grain further down, in A_ProductStorageLocation. Note also that a plant extension alone does not mean the material is stocked — service and non-stock material types carry plant views too, so pair it with a ProductType whitelist.
| Field | Type | Example |
|---|---|---|
Product | string | CW-APC-5L |
Plant | string | HBN1 |
ProfileCode | string | (empty) |
ProfileValidityStartDate | string (nullable) | null |
PurchasingGroup | string | 001 |
CountryOfOrigin | string | (empty) |
Region | string | (empty) |
ProductionInvtryManagedLoc | string | (empty) |
IsBatchManagementRequired | boolean | false |
SerialNumberProfile | string | (empty) |
IsMarkedForDeletion | boolean | false |
MRPType | string | PD |
MRPResponsible | string | (empty) |
MRPGroup | string | (empty) |
ReorderThresholdQuantity | string | 0 |
PlanningTimeFence | string | 0 |
LotSizingProcedure | string | EX |
MinimumLotSizeQuantity | string | 0 |
MaximumLotSizeQuantity | string | 0 |
FixedLotSizeQuantity | string | 0 |
RoundingProfile | string | (empty) |
GoodsReceiptDuration | string | 0 |
PlannedDeliveryDurationInDays | string | 0 |
SafetyStock | string | 0 |
{
"d": {
"results": [
{
"Product": "CW-APC-5L",
"Plant": "HBN1",
"ProfileCode": "",
"ProfileValidityStartDate": null,
"PurchasingGroup": "001",
"CountryOfOrigin": "",
"Region": "",
"ProductionInvtryManagedLoc": "",
"IsBatchManagementRequired": false,
"SerialNumberProfile": "",
"IsMarkedForDeletion": false,
"MRPType": "PD",
"MRPResponsible": "",
"MRPGroup": "",
"ReorderThresholdQuantity": "0",
"PlanningTimeFence": "0",
"LotSizingProcedure": "EX",
"MinimumLotSizeQuantity": "0",
"MaximumLotSizeQuantity": "0",
"FixedLotSizeQuantity": "0",
"RoundingProfile": "",
"GoodsReceiptDuration": "0",
"PlannedDeliveryDurationInDays": "0",
"SafetyStock": "0"
}
]
}
}6. A_ProductStorageLocation
One row per material, plant and storage location (SAP MARD). The row's existence is the “has a storage-location view” signal; quantities are not here — those live in a separate material-stock API.
IsMarkedForDeletionis how de-stocking is signalled. Flagged rows stay in the collection — 13 of 49 here — so a consumer never has to infer removal from a row's absence. Do not filter them out of the query, or you lose exactly that signal.- There is no change timestamp on this entity or on
A_ProductPlant— onlyCreationDate. A delta load keyed on “last changed” is not possible; these sources full-reload. Scope them by plant to keep that affordable.
| Field | Type | Example |
|---|---|---|
Product | string | CW-APC-5L |
Plant | string | HBN1 |
StorageLocation | string | 7000 |
WarehouseStorageBin | string | BIN-7000 |
MaintenanceStatus | string | DL |
PhysicalInventoryBlockInd | string | (empty) |
CreationDate | string | /Date(1639008000000)/ |
IsMarkedForDeletion | boolean | false |
DateOfLastPostedCntUnRstrcdStk | string (nullable) | null |
InventoryCorrectionFactor | string | 0 |
InvtryRestrictedUseStockInd | string | (empty) |
InvtryCurrentYearStockInd | string | (empty) |
InvtryQualInspCurrentYrStkInd | string | (empty) |
InventoryBlockStockInd | string | (empty) |
InvtryRestStockPrevPeriodInd | string | (empty) |
InventoryStockPrevPeriod | string | (empty) |
InvtryStockQltyInspPrevPeriod | string | (empty) |
HasInvtryBlockStockPrevPeriod | string | (empty) |
FiscalYearCurrentPeriod | string | 2021 |
FiscalMonthCurrentPeriod | string | 12 |
FiscalYearCurrentInvtryPeriod | string | 2021 |
LeanWrhsManagementPickingArea | string | (empty) |
{
"d": {
"results": [
{
"Product": "CW-APC-5L",
"Plant": "HBN1",
"StorageLocation": "7000",
"WarehouseStorageBin": "BIN-7000",
"MaintenanceStatus": "DL",
"PhysicalInventoryBlockInd": "",
"CreationDate": "/Date(1639008000000)/",
"IsMarkedForDeletion": false,
"DateOfLastPostedCntUnRstrcdStk": null,
"InventoryCorrectionFactor": "0",
"InvtryRestrictedUseStockInd": "",
"InvtryCurrentYearStockInd": "",
"InvtryQualInspCurrentYrStkInd": "",
"InventoryBlockStockInd": "",
"InvtryRestStockPrevPeriodInd": "",
"InventoryStockPrevPeriod": "",
"InvtryStockQltyInspPrevPeriod": "",
"HasInvtryBlockStockPrevPeriod": "",
"FiscalYearCurrentPeriod": "2021",
"FiscalMonthCurrentPeriod": "12",
"FiscalYearCurrentInvtryPeriod": "2021",
"LeanWrhsManagementPickingArea": ""
}
]
}
}Joining the three
Join on Product. A_Product supplies the commodity, A_ProductPlant narrows to plants, and A_ProductStorageLocation adds storage granularity. A material extended to two plants produces two joined rows for one product — aggregate per Product if the target expects one record each.
Inspect calls against this host in /debug/requests.