on_handStock físicoLa cantidad que modifica el sistema con autoridad.
Guía
Moku separa stock físico y reservas para calcular disponibilidad y proteger unidades comprometidas.
on_handStock físicoLa cantidad que modifica el sistema con autoridad.
reservedReservadoUnidades retenidas por checkout, pedido o reserva pública.
availableDisponibleon_hand - reserved. Publica este valor en canales externos.
Cada item devuelve location_id: default, una ubicación contable explícita dentro de vendor_id. El mismo nombre en dos vendedores no representa stock compartido. Los IDs actuales de inventario no cambian: guárdalos como valores opacos, sin recalcularlos.
Todavía no existen administración de bodegas ni asignación entre ubicaciones. Un futuro inventario administrado por un marketplace usará otra ubicación para no descontar dos veces el stock del vendedor.
Cada item admite hasta 256 reservas activas. Al alcanzar el límite, una reserva nueva falla con RESERVATION_CONFLICT; renovar o liquidar una reserva vigente sigue permitido. Las reservas vencidas liberan disponibilidad y capacidad inmediatamente, aunque la limpieza llegue después.
El catálogo no reemplaza el inventario autorizado: si falta un registro de stock o está mal formado, la operación falla de forma cerrada. No se toma stock de una instantánea del producto.
Cada item también declara stock_pool_id: default. El ID opaco existente no cambia; futuros pools serán aditivos.
Seguir la guía de producto a stock
La API usa producción, aunque los pagos estén en sandbox. Los IDs y las respuestas de esta guía son ficticios; reemplázalos por los de tu tienda.
Solicitud · ejemplo ilustrativo
: "${MOKU_PAT:?}" &&
test "${MOKU_ALLOW_WRITES:-}" = "1" &&
curl --silent --show-error --fail-with-body \
--request POST \
'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/inventory-items/WyJwcm9kdWN0X2RlbW9fdGF6b24iLCJ2YXJpYXRpb25fZGVtb19henVsIl0/adjustments' \
--header "Authorization: Bearer ${MOKU_PAT}" \
--header 'Accept: application/json' \
--header 'Idempotency-Key: demo_stock_001' \
--header 'Content-Type: application/json' \
--data-raw '{
"target_on_hand": 8,
"expected_version": 7
}'Ejemplo para PHP CLI con la extensión cURL. No es un plugin de WordPress ni debe ejecutarse en el navegador.
<?php
$token = getenv('MOKU_PAT');
if ($token === false || $token === '') {
throw new RuntimeException('MOKU_PAT');
}
if (getenv('MOKU_ALLOW_WRITES') !== '1') {
throw new RuntimeException('MOKU_ALLOW_WRITES=1');
}
$url = 'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/inventory-items/WyJwcm9kdWN0X2RlbW9fdGF6b24iLCJ2YXJpYXRpb25fZGVtb19henVsIl0/adjustments';
$body = <<<'MOKU_REQUEST_JSON'
{
"target_on_hand": 8,
"expected_version": 7
}
MOKU_REQUEST_JSON;
$curl = curl_init($url);
if ($curl === false) {
throw new RuntimeException('curl_init');
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Authorization: Bearer ' . $token,
'Idempotency-Key: demo_stock_001',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
if ($response === false) {
$message = curl_error($curl);
curl_close($curl);
throw new RuntimeException($message);
}
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
$result = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
$failed = $status < 200 || $status >= 300;
if ($failed) {
fwrite(STDERR, "HTTP {$status}\n");
}
fwrite(
$failed ? STDERR : STDOUT,
json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL
);
exit($failed ? 1 : 0);Respuesta 200 application/json
{
"data": {
"id": "WyJwcm9kdWN0X2RlbW9fdGF6b24iLCJ2YXJpYXRpb25fZGVtb19henVsIl0",
"vendor_id": "vendor_demo_ceramica",
"location_id": "default",
"stock_pool_id": "default",
"product_id": "product_demo_tazon",
"product_name": "Tazón de cerámica",
"product_image_url": "https://example.com/tazon-azul.jpg",
"variation_id": "variation_demo_azul",
"variation_options": {
"Color": "Azul"
},
"sku": "TAZ-AZUL",
"on_hand": 8,
"reserved": 2,
"available": 6,
"version": 8,
"status": "low_stock"
}
}
Omite authority_connection_id cuando Moku controla el Stock Pool. Cuando WooCommerce tiene rol inventory: source, envía el ID exacto de esa conexión.
Los replays exactos se reconocen durante al menos 30 días y la identidad incluye token y operación. Nunca reutilices intencionalmente una clave para otro trabajo; una credencial nueva no comparte los recibos de la anterior.
Una conexión con rol de destino y stock Moku puede reservar entre 60 y 3600 segundos, renovar, consumir o liberar. Una reserva creada por un pedido externo se administra exclusivamente mediante el estado del pedido.
INVENTORY_VERSION_CONFLICT, vuelve a leer el item.target_on_hand sobre la versión actual.ON_HAND_BELOW_RESERVED impide establecer stock por debajo de compromisos activos. AUTHORITY_CONFLICT indica que otro sistema es el escritor vigente.