Skip to main content

Price Update Endpoint

The price update endpoint is the inbound channel through which the external Laravel pricing middleware pushes current precious metals prices to WooCommerce every minute.


Endpointโ€‹

POST /wp-json/suma/v1/product/update-prices

Authentication: Bearer token

Handler class: \Suma\Endpoints\Pricing (inc/endpoints/class-pricing.php)

Called by: External Laravel pricing middleware (every 60 seconds)


Request Formatโ€‹

{
"products": [
{
"sku": "SM-1OZ-SILVER-BAR",
"price": 29.95,
"sale_price": null,
"spot_price": 27.50,
"premium": 2.45
},
{
"sku": "SM-1OZ-GOLD-AGE",
"price": 1950.00,
"sale_price": null,
"spot_price": 1880.00,
"premium": 70.00
}
]
}

Response Formatโ€‹

{
"updated": 142,
"skipped": 3,
"errors": [
{ "sku": "SM-DISCONTINUED-ITEM", "error": "Product not found" }
],
"execution_time_ms": 1240
}

Update Logic (PriceUpdater::update_batch())โ€‹

For each product in the payload:

1. Find WC product by SKU (wp_is_post() + sku lookup)
โ†’ If not found: add to errors[], continue

2. Validate the new price is positive and numeric
โ†’ If invalid: add to errors[], continue

3. Update WooCommerce product price fields:
- _price โ†’ new price
- _regular_price โ†’ new price (if not on sale)
- _sale_price โ†’ sale_price from payload (or null)

4. Flush Redis object cache for this product ID
(wp_cache_delete on product and related keys)

5. Mark this product ID for CloudFront invalidation

After loop:
6. Trigger CloudFront cache invalidation for all updated product URLs
7. Update spot price cache in Redis (suma_pricing_cache)
8. Return summary (updated count, skipped, errors)

Performance Requirementsโ€‹

Performance-Critical Endpoint

This endpoint runs every 60 seconds. Violating these rules will cause pricing pipeline delays and customer-facing stale prices.

Rules:

  • No blocking external API calls in the update loop
  • No email sends during batch processing
  • Batch database operations where possible โ€” avoid N+1 queries
  • Use wp_defer_term_counting(true) around the batch to prevent repeated wp_terms lock contention
  • Total execution time target: < 10 seconds for ~200 products
  • Never call wp_update_post() with wp_after_insert_post actions if they trigger expensive hooks

Sale Management Endpointsโ€‹

POST /wp-json/suma/v1/product/start-salesโ€‹

Starts scheduled product sales. Called by a cron job when date_on_sale_from has been reached.

Logic:

  1. Query products with date_on_sale_from <= now AND date_on_sale_to >= now
  2. Set _price = _sale_price for each matching product
  3. Clear caches

POST /wp-json/suma/v1/product/end-expired-salesโ€‹

Ends product sales that have passed their expiry date.

Logic:

  1. Query products with date_on_sale_to < now AND _price = _sale_price
  2. Restore _price = _regular_price
  3. Clear _sale_price
  4. Clear caches

Cron Configurationโ€‹

These endpoints are called via Ymir's external cron runner (not wp-cron).

From ymir.yml:

cron: 1  # Single cron execution โ€” Ymir calls WordPress cron every minute

For the price update specifically, the Laravel middleware's own cron calls the WP REST endpoint directly โ€” it does not go through WordPress's internal cron system.


Spot Price Alert Emailsโ€‹

POST /wp-json/suma/v1/product/spot-price-alert-emailโ€‹

Triggers price alert emails to customers who have registered for spot price notifications at a specific target price.

When triggered: After a successful price update batch, if any product's price has crossed a customer's alert threshold, this endpoint sends the notification email via WooCommerce's email system.

note

Alert subscriptions are managed via a custom ACF field or meta on user accounts. The alert email uses the standard WooCommerce transactional email system (routed through Mailgun).