1. Customization and development

Bulk updates

Bulk update endpoints let you process large pricing and discount workloads in fewer API calls. OrderCloud accepts each request, creates a bulk job, and processes items asynchronously. Currently the only supported resources are price schedules, discounts, and discount assignments, all of which are covered in this document. Additional resources might be added in the future.

Beta feature

This feature is currently in beta. Behavior and properties might change before general availability.

Bulk endpoints

ResourceOperationEndpointDescription
Price schedulesUpsertPOST /v1/bulk/priceschedules/upsertCreate or update price schedules in bulk.
Price schedulesDeletePOST /v1/bulk/priceschedules/deleteDelete price schedules in bulk by ID.
DiscountsUpsertPOST /v1/bulk/discounts/upsertCreate or update discounts in bulk.
DiscountsDeletePOST /v1/bulk/discounts/deleteDelete discounts in bulk by ID.
Discount assignmentsUpsertPOST /v1/bulk/discounts/assignments/upsertCreate or update discount assignments in bulk.
Discount assignmentsDeletePOST /v1/bulk/discounts/assignments/deleteDelete discount assignments in bulk by composite key (DiscountID + BuyerID or BuyerGroupID).

All endpoints return 202 Accepted with job metadata.

Common bulk behavior

Asynchronous job processing

Each bulk request returns an initial job descriptor.

{
  "JobID": "bulk_01J123ABC...",
  "Resource": "Discounts",
  "Operation": "Upsert",
  "Status": "Queued",
  "ItemsReceived": 50000,
  "ItemsCompleted": 0,
  "ItemsSucceeded": 0,
  "ItemsFailed": 0,
  "DateReceived": "2025-11-11T20:32:00Z",
  "DateStarted": null,
  "DateCompleted": null
}

To track progress, call:

GET /v1/bulk/jobs/{jobID}

Example response:

{
  "JobID": "bulk_01J123ABC...",
  "Resource": "Discounts",
  "Operation": "Upsert",
  "Status": "Queued | Running | Completed | Failed | Cancelled",
  "ItemsReceived": 50000,
  "ItemsCompleted": 48045,
  "ItemsSucceeded": 48000,
  "ItemsFailed": 45,
  "DateReceived": "2025-11-11T20:32:00Z",
  "DateStarted": "2025-11-11T20:32:11Z",
  "DateCompleted": null
}

Jobs remain queryable for 24 hours after completion.

Error retrieval

To retrieve indexed item errors, call:

GET /v1/bulk/jobs/{jobID}/errors

If no items fail, the response is an empty array:

[]

Example error payload:

[
  {
    "ItemIndex": 2341,
    "ErrorCode": "NotFound",
    "Message": "Catalog not found.",
    "Data": {
      "ObjectType": "Catalog",
      "ObjectID": "invalid-catalog-id"
    }
  }
]

Each error object includes:

  • ItemIndex: Zero-based index from the original request.
  • ErrorCode: Standardized error code.
  • Message: Human-readable error message.
  • Data: Optional context for the failure.

Limits

LimitValue
Maximum items per request50,000
Maximum payload size25 MB
Concurrent running jobs2

If payload size exceeds the limit, the API returns 400 with Bulk.PayloadTooLarge.

You can submit more than two jobs, but only two jobs run at the same time per marketplace. Additional jobs remain queued.

Tip

Use gzip compression for large payloads to reduce request size and upload time.

Price schedule bulk operations

Upsert price schedules

POST /v1/bulk/priceschedules/upsert

Each item is a full price schedule object.

{
  "Items": [
    {
      "ID": "B2B-DEFAULT-USD",
      "Name": "Default B2B Pricing - USD",
      "Currency": "USD",
      "MinQuantity": 1,
      "MaxQuantity": null,
      "UseCumulativeQuantity": false,
      "RestrictedQuantity": false,
      "ApplyTax": true,
      "ApplyShipping": true,
      "OrderType": "Standard",
      "PriceBreaks": [
        { "Quantity": 1, "Price": 10.0 },
        { "Quantity": 100, "Price": 9.5 }
      ],
      "SaleStart": "2025-11-01T00:00:00Z",
      "SaleEnd": "2025-11-30T23:59:59Z",
      "xp": {
        "Region": "NA"
      },
      "DefaultForProductID": "MY-PRODUCT",
      "DefaultForSupplierID": null
    }
  ]
}

Behavior:

  1. If the ID does not exist, OrderCloud creates the price schedule.
  2. If the ID exists, OrderCloud updates the price schedule (PUT-style replacement).
  3. OrderCloud replaces the full PriceBreaks array.
  4. If provided, OrderCloud applies default assignment fields after save.

Default assignment fields for price schedules

Use DefaultForProductID and DefaultForSupplierID to set defaults during upsert.

CombinationResult
DefaultForProductID onlySets Product.DefaultPriceScheduleID.
DefaultForProductID and DefaultForSupplierIDSets ProductSupplier.DefaultPriceScheduleID for that supplier on that product.
DefaultForSupplierID onlyInvalid. Returns a validation error.
Neither fieldStandard upsert without default assignment.

Validation and ownership rules:

  1. Referenced product and supplier objects must exist, or the item returns NotFound.
  2. For supplier-owned schedules, ownership must match the supplier or marketplace owner, or the item returns InvalidDefaultPriceScheduleID.
  3. If the default is already set, OrderCloud skips the write.
  4. These fields do not change schedule ownership.

Delete price schedules

POST /v1/bulk/priceschedules/delete
{
  "IDs": [
    "B2B-DEFAULT-USD",
    "SUMMER-PROMO-2024",
    "LEGACY-TEST-SCHEDULE"
  ]
}

Behavior:

  1. OrderCloud deletes each ID independently.
  2. Missing IDs return NotFound for those items.

Discount bulk operations

Upsert discounts

POST /v1/bulk/discounts/upsert

Each item is a full discount object.

{
  "Items": [
    {
      "ID": "ACME-CONTRACT-2024",
      "Description": "Acme Corp negotiated pricing",
      "DiscountBreaks": [
        { "Quantity": 1, "Amount": 18.0 },
        { "Quantity": 100, "Amount": 22.0 }
      ],
      "CategoryID": "heavy-machinery"
    },
    {
      "ID": "GLOBAL-MFG-VOLUME",
      "Description": "Global Manufacturing volume discount",
      "DiscountBreaks": [
        { "Quantity": 1, "Amount": 15.0 }
      ],
      "CatalogID": "industrial-equipment"
    }
  ]
}

Behavior:

  1. If the ID does not exist, OrderCloud creates the discount.
  2. If the ID exists, OrderCloud updates the discount (PUT-style replacement).
  3. OrderCloud validates all break and scope rules per item.

Delete discounts

POST /v1/bulk/discounts/delete
{
  "IDs": [
    "ACME-CONTRACT-2023",
    "LEGACY-VOLUME-2022",
    "EXPIRED-CONTRACT-Q4"
  ]
}

Behavior:

  1. OrderCloud deletes each ID independently.
  2. Missing IDs return NotFound for those items.

Discount assignment bulk operations

Upsert discount assignments

POST /v1/bulk/discounts/assignments/upsert
{
  "Items": [
    { "DiscountID": "ENTERPRISE-VOLUME", "BuyerGroupID": "enterprise-customers" },
    { "DiscountID": "ACME-CONTRACT-2024", "BuyerID": "acme-corp" },
    { "DiscountID": "GLOBAL-MFG-VOLUME", "BuyerID": "global-manufacturing", "UserGroupID": "procurement-team" }
  ]
}

Each item must follow discount assignment rules.

  1. Buyer group assignment: DiscountID and BuyerGroupID
  2. Buyer assignment: DiscountID and BuyerID
  3. User group assignment: DiscountID, BuyerID, and UserGroupID

Delete discount assignments

POST /v1/bulk/discounts/assignments/delete
{
  "Items": [
    { "DiscountID": "ACME-CONTRACT-2023", "BuyerID": "acme-corp" },
    { "DiscountID": "LEGACY-VOLUME-2022", "BuyerGroupID": "enterprise-customers" }
  ]
}

Each item identifies one assignment to remove.

Behavior:

  • If both the discount and party exist, but no assignment exists, this error is caught and the request is ignored.
  • If either the discount or the party does not exist, this error is surfaced in the error payload.

Authorization

RoleAccess
PriceScheduleAdminFull access to bulk upsert and delete operations for price schedules, discounts, and discount assignments.
PriceScheduleReaderRead-only access to bulk jobs and bulk job errors.
If you have suggestions for improving this article, let us know!