mercado de servicios API de Comerciantes
Fase 1: productos y recepción

API de Comerciantes: conecta tus SKU, los preavisos de compra y el inventario de Shenzhen a tu sistema

Para empresas que venden en Shopee, Coupang y momo. Envía por API los códigos de barras de producto generados al publicar y el preaviso de los números de seguimiento y del contenido al comprar; cuando la mercancía llega al almacén de Shenzhen, se abre automáticamente una orden de trabajo y cada pieza se etiqueta, se escanea y se ubica en estantería, con el inventario y las diferencias informados en tiempo real.

Empresas

Destinatarios (se requiere número de identificación fiscal taiwanés de 8 dígitos)

200

Máximo de SKU por solicitud en lote

WO-SK

Orden de etiquetado automática a la llegada

60 / min

Límite de solicitudes predeterminado por clave

1 Descripción general

La fase 1 ofrece «productos y recepción»: desde la creación del SKU hasta la ubicación de la mercancía como inventario en el almacén de Shenzhen.

Lo que ya puedes hacer

  • Crear o actualizar SKU en lote (identificados por tu seller_sku), con un código de barras de producto para cada color y cada talla, vinculados a los códigos de variante de Shopee / Coupang / momo.
  • Verificar automáticamente los requisitos de importación a partir del código arancelario de 11 dígitos y marcar los productos que requieren inspección o permiso, o cuya importación no está permitida.
  • Enviar el preaviso de los números de seguimiento y del contenido de cada caja al comprar; cuando la mercancía llega al almacén de Shenzhen, se abre automáticamente una orden de etiquetado WO-SK y el almacén etiqueta, escanea y ubica cada pieza.
  • Consultar el inventario por almacén y el registro de movimientos de inventario, y recibir por webhook, en tiempo real, las llegadas, las recepciones completadas, las diferencias de cantidad y los cambios de inventario.

Flujo de recepción

  1. Crear SKU: envía códigos de barras de producto, variantes, descripciones declaradas y códigos arancelarios.
  2. Preaviso de recepción: envía los números de seguimiento y la cantidad prevista de cada SKU.
  3. Llegada al almacén de Shenzhen: al escanear el número de seguimiento, se abre e imprime automáticamente una orden de trabajo WO-SK.
  4. Etiquetado y ubicación: el almacén imprime los códigos de barras de producto, etiqueta cada pieza y la escanea para contarla.
  5. Recepción completada: las unidades recibidas pasan al inventario de Shenzhen, las dañadas se contabilizan aparte y las diferencias se notifican a tu sistema.
Sobre los requisitos de importación: el sistema los determina automáticamente a partir de los códigos de requisitos de importación de los datos arancelarios de la Administración de Aduanas de Taiwán, solo como referencia operativa. Si un producto requiere realmente inspección, permiso o declaración aduanera formal lo determina la revisión de la aduana y de nuestro agente de aduanas asociado. El inventario de un comerciante tiene fines de venta y no puede acogerse a las exenciones para uso personal.

Funciones previstas

Pedidos de envío en lote, lotes de envío agrupados automáticamente según las normas de declaración, e inventario anticipado, clasificación y etiquetas de envío de los marketplaces en el almacén de Taoyuan. Se anunciarán en esta página cuando estén disponibles.

2 Acceso y claves

La API de Comerciantes solo está disponible para empresas registradas, y cada clave está vinculada a una cuenta de comerciante aprobada.

Pasos para obtener acceso

  1. En el área de miembros, añade un declarante de tipo «empresa» con su número de identificación fiscal taiwanés de 8 dígitos.
  2. Contacta con la atención al cliente de HowBridge para solicitar la activación de la API de Comerciantes; la clave se emite tras la aprobación.
  3. La clave se muestra una sola vez. Guárdala en una variable de entorno del servidor y nunca la incluyas en un navegador ni en una app.
  4. Si necesitas webhooks, primero configura y verifica la URL en la página de API del área de miembros y luego suscríbete a los eventos de comerciante.
Todas las solicitudes usan Authorization: Bearer <clave>. Los tokens generados al iniciar sesión como miembro en la app o en la web no pueden llamar a la API de Comerciantes.
Authorization: Bearer 12|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/json

3 Convenciones

Todos los endpoints comparten las siguientes reglas.

Base URL

https://0523.tw/api/v1/merchant

Formato e idioma

Las solicitudes y respuestas son JSON. Los mensajes de error están en chino tradicional por defecto; envía Accept-Language: en para recibirlos en inglés. En tu código, basa siempre la lógica en error.code, que está fijo en inglés.

Estructura de la respuesta

En caso de éxito devuelve {"success": true, "data": …, "meta": …}; en caso de error, {"success": false, "error": {"code", "message", "errors", "context"}}, donde errors contiene el detalle por campo. La única excepción es una clave ausente o no válida: HTTP 401 con el cuerpo {"message": "Unauthenticated."}.

{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "…",
    "errors": [
      { "code": "TRACKING_IN_USE", "field": "packages.0.tracking_no", "message": "…" }
    ]
  }
}

Límites de solicitudes

60 solicitudes por minuto y 5000 por día por clave (300 por minuto y 50 000 por día en el plan de alto volumen); una solicitud en lote cuenta como una. Para datos en tiempo real, suscríbete a webhooks en lugar de hacer sondeos.

Encabezado de respuestaDescripción
X-RateLimit-LimitLímite por minuto
X-RateLimit-RemainingSolicitudes restantes en este minuto
X-RateLimit-Limit-Day
X-RateLimit-Remaining-Day
Límite diario y solicitudes restantes
Retry-AfterSegundos de espera antes de reintentar tras superar el límite

Idempotencia (Idempotency-Key)

Las solicitudes de escritura admiten el encabezado Idempotency-Key (8–128 caracteres: letras, dígitos y _-:.). Si reenvías tras un tiempo de espera de red agotado con la misma clave y el mismo contenido, recibirás la respuesta original con el encabezado Idempotent-Replayed: true; usar la misma clave con otro contenido devuelve 422. Los registros se conservan 24 horas.

Respuestas en lote

Los endpoints en lote informan el resultado de cada elemento: 200 si todos tienen éxito, 207 si fallan algunos y 422 si fallan todos. Cada elemento incluye index, status (created / updated / failed) y el motivo del error.

Caracteres de los identificadores

seller_sku solo admite letras, dígitos y ._- (1–64 caracteres); los códigos de barras de producto admiten además / y + (3–64 caracteres). No se distingue entre mayúsculas y minúsculas.

4 SKU de productos

El SKU se identifica de forma única por tu seller_sku: volver a enviar el mismo seller_sku lo actualiza y solo modifica los campos incluidos.

Crear o actualizar SKU en lote

POST/api/v1/merchant/skus/batch

Hasta 200 elementos por solicitud. Cada elemento se procesa de forma independiente, por lo que un error no afecta a los demás.

CampoTipoObligatorioDescripción
seller_skustringObligatorioTu código de SKU, por ejemplo el SKU de la variante en Shopee.
product_namestringObligatorio al crearNombre del producto. Los SKU con el mismo nombre se agrupan bajo un mismo producto.
barcodestringOpcionalCódigo de barras del producto: el almacén imprime la etiqueta y escanea la ubicación con este código. Cada color y cada talla deben tener un código distinto. Si no tienes código de barras, déjalo vacío y el sistema generará un código de barras del sistema. Si supera los 16 caracteres, la etiqueta se imprime con el código de barras del sistema.
gtinstringOpcionalCódigo de barras internacional GTIN (8 / 12 / 13 / 14 dígitos, se verifica el dígito de control). Para la opción de Shopee «producto sin GTIN», envía 00.
specobjectOpcionalVariante, por ejemplo {"color": "negro", "size": "M"}, hasta 5 atributos.
declared_name_zh
declared_name_en
stringOpcionalDescripción declarada (en chino / inglés): indica el material y el uso; no escribas «muestra» ni «regalo».
declared_unit_valuenumberOpcionalValor unitario declarado: tu precio unitario de compra al proveedor, no el precio de venta en el marketplace.
declared_currencystringOpcionalCNY, TWD o USD; obligatorio si se indica un valor unitario.
hs_codestringOpcionalCódigo de clasificación arancelaria de 11 dígitos, con el que el sistema verifica los requisitos de importación.
origin_countrystringOpcionalCódigo ISO del país de origen; por defecto CN.
weight_gintegerOpcionalPeso unitario (gramos).
dimensions_cmarrayOpcionalLargo, ancho y alto (centímetros), por ejemplo [20, 15, 3].
battery_typestringOpcionalnone, contained (integrada), packed (incluida con el producto), standalone (batería suelta).
channelsarrayOpcionalVínculos con productos de los marketplaces, hasta 20: platform (shopee / coupang / momo / other), shop_id, item_id, model_id, platform_sku.

Ejemplo de solicitud (POST JSON)

curl -X POST https://0523.tw/api/v1/merchant/skus/batch \
  -H "Authorization: Bearer $LUCKY_MERCHANT_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: sku-sync-20260917-001" \
  -d '{
  "items": [
    {
      "seller_sku": "TEE-RED-S",
      "barcode": "4710000000011",
      "product_name": "Cotton T-shirt",
      "spec": { "color": "red", "size": "S" },
      "declared_name_en": "Cotton knitted T-shirt",
      "declared_unit_value": 18.5,
      "declared_currency": "CNY",
      "hs_code": "61091000006",
      "weight_g": 160,
      "channels": [ { "platform": "shopee", "shop_id": "123456", "item_id": "2233", "model_id": "445566" } ]
    }
  ]
}'

Respuesta 200

{
  "success": true,
  "data": [
    {
      "index": 0,
      "seller_sku": "TEE-RED-S",
      "status": "created",
      "sku": {
        "seller_sku": "TEE-RED-S",
        "barcode": "4710000000011",
        "system_barcode": null,
        "pick_code": "131999",
        "hs_code": "61091000006",
        "regulation": { "status": "ok", "import_codes": [], "reasons": [] },
        "channels": [ { "platform": "shopee", "shop_id": "123456", "item_id": "2233", "model_id": "445566", "platform_sku": null } ]
      }
    }
  ],
  "meta": { "summary": { "created": 1, "updated": 0, "failed": 0 } }
}

Verificación de requisitos de importación (regulation.status)

okSin códigos de requisitos de importación.
review_requiredEl requisito solo afecta a parte de los productos (por ejemplo, C02 «parte de los productos de esta partida está sujeta a inspección»); confírmalo según el uso real del producto.
formal_requiredHay requisitos de importación (inspección, cuarentena, permisos, etc.); no se puede usar la declaración simplificada.
blockedProducto de China continental cuya importación no está permitida (MW0, origen China continental); no se puede incluir en un preaviso de recepción.
unclassifiedAún no se ha indicado el código arancelario; no se puede verificar.

Consultar SKU

GET/api/v1/merchant/skus

Filtra por seller_sku, barcode, regulation_status o updated_since (ISO 8601) y pagina con page / per_page (máximo 100).

Consultar un SKU

GET/api/v1/merchant/skus/{seller_sku}

Actualizar vínculos con marketplaces

PUT/api/v1/merchant/skus/{seller_sku}/channels

La lista enviada sustituye por completo los vínculos existentes; una misma variante de marketplace no puede vincularse a dos SKU.

Descargar etiquetas de código de barras

GET/api/v1/merchant/skus/{seller_sku}/label.pdf?qty=10

Devuelve un PDF de etiquetas de 40×30 mm; qty es el número de etiquetas (1–1000). El almacén de Shenzhen imprime la misma etiqueta al etiquetar; este endpoint sirve si quieres etiquetar por tu cuenta antes del envío.

5 Preaviso de recepción

Cuando se despache la compra, envía el preaviso con los números de seguimiento y el contenido. Una orden de recepción puede tener varios números de seguimiento, cada uno con sus SKU y cantidades.

Crear una orden de recepción

POST/api/v1/merchant/inbound-orders

Se valida la orden completa: si hay cualquier error, no se crea nada. Un número de seguimiento solo puede pertenecer a una orden de recepción en curso a la vez; los SKU repetidos dentro de un mismo paquete se combinan sumando sus cantidades.

CampoTipoObligatorioDescripción
reference_nostringObligatorioTu número de pedido de compra o de orden de recepción, único por comerciante (letras, dígitos y ._-/).
supplier_order_nostringOpcionalNúmero de pedido del proveedor, por ejemplo un número de pedido de 1688.
warehouse_codestringOpcionalAlmacén de recepción; por ahora solo se admite SZ (almacén de Shenzhen).
notesstringOpcionalObservaciones (hasta 1000 caracteres).
packagesarrayObligatorioLista de paquetes, hasta 50.
packages[].tracking_nostringObligatorioNúmero de seguimiento de una empresa de mensajería china.
packages[].carrierstringOpcionalCódigo de la empresa de mensajería, por ejemplo yto o sf.
packages[].itemsarrayObligatorioContenido del paquete: seller_sku y qty, hasta 500 líneas en total por orden de recepción.

Ejemplo de solicitud (POST JSON)

curl -X POST https://0523.tw/api/v1/merchant/inbound-orders \
  -H "Authorization: Bearer $LUCKY_MERCHANT_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: po-20260917-0001" \
  -d '{
  "reference_no": "PO-20260917-0001",
  "supplier_order_no": "1688-3312456789",
  "packages": [
    {
      "tracking_no": "YT1234567890123",
      "carrier": "yto",
      "items": [
        { "seller_sku": "TEE-RED-S", "qty": 40 },
        { "seller_sku": "TEE-RED-M", "qty": 60 }
      ]
    }
  ]
}'
Protección contra reenvíos: volver a crear el mismo reference_no devuelve 409 INBOUND_REFERENCE_EXISTS, con el id de la orden de recepción original en error.context.inbound_order_id. Para reintentar de forma segura, envía el encabezado Idempotency-Key.

Estados de la orden de recepción

createdPreaviso enviado; todavía no ha llegado ningún paquete.
partially_arrivedAlgunos paquetes han llegado al almacén de Shenzhen.
arrivedTodos los paquetes han llegado; etiquetado y ubicación en curso.
completedUbicación completada; las cantidades coinciden con el preaviso.
completed_with_discrepancyCompletada, pero con faltantes, excedentes o daños.
cancelledCancelada.

Estados del paquete

awaiting_arrivalPendiente de llegada.
labelingIngresado en el almacén; orden de trabajo abierta, etiquetado y ubicación en curso.
receivedUbicación completada.
mismatchLa titularidad del paquete registrada al ingresar no coincide con tu preaviso; atención al cliente lo está verificando.
cancelledCancelado o anulado; el número de seguimiento ha quedado liberado.

Consultar órdenes de recepción

GET/api/v1/merchant/inbound-orders

GET/api/v1/merchant/inbound-orders/{id}

Filtra por status, reference_no o updated_since. Cada paquete devuelve las cantidades previstas, recibidas y dañadas, además de la diferencia.

Cancelar una orden de recepción

POST/api/v1/merchant/inbound-orders/{id}/cancel

Solo se puede cancelar mientras no haya llegado ningún paquete; tras la cancelación, los números de seguimiento pueden volver a incluirse en un preaviso.

6 Inventario

El inventario se separa por almacén: SZ almacén de Shenzhen y TY almacén de Taoyuan (el inventario de Taoyuan se habilitará junto con las funciones de envío).

Consultar inventario

GET/api/v1/merchant/inventory?warehouse_code=SZ

Filtra por warehouse_code y seller_sku[] (hasta 200).

on_handCantidad en inventario.
reservedCantidad reservada para pedidos.
availableCantidad disponible = en inventario − reservada.
damagedCantidad dañada; no se puede enviar.

Respuesta 200

{
  "success": true,
  "data": [
    { "seller_sku": "TEE-RED-S", "barcode": "4710000000011", "warehouse_code": "SZ",
      "on_hand": 38, "reserved": 0, "available": 38, "damaged": 2, "updated_at": "2026-09-17T15:20:11+08:00" }
  ],
  "meta": { "total": 1, "page": 1, "per_page": 100, "last_page": 1 }
}

Registro de movimientos de inventario

GET/api/v1/merchant/inventory/movements?after_id=0&limit=200

Registros de movimientos que solo se añaden y nunca se modifican. Avanza de página con el cursor after_id (hasta 500 registros por solicitud) y guarda el meta.next_after_id de la respuesta para continuar la conciliación.

7 Eventos de webhook

Los eventos se envían a tu URL en cuanto ocurren, sin necesidad de sondeos.

Configuración

  1. Configura la URL del webhook en la página de API del área de miembros (solo https) y completa la verificación de titularidad: tu endpoint debe responder HTTP 200 con el cuerpo {"challenge": "valor recibido"}.
  2. Llama a PUT /api/v1/merchant/webhook/events para suscribirte a los eventos de comerciante. Cambiar después la URL en el área de miembros no elimina esas suscripciones.
curl -X PUT https://0523.tw/api/v1/merchant/webhook/events \
  -H "Authorization: Bearer $LUCKY_MERCHANT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"events": ["inbound.arrived", "inbound.received", "inbound.discrepancy", "inventory.changed"]}'

Lista de eventos

sku.regulation_flaggedLa verificación de requisitos de importación de un SKU pasa a «requiere confirmación», «requiere declaración aduanera formal» o «importación no permitida».
inbound.arrivedEl paquete ha llegado al almacén de Shenzhen y se ha abierto la orden de trabajo.
inbound.mismatchLa titularidad del paquete registrada al ingresar no coincide con el preaviso; atención al cliente lo está verificando.
inbound.receivedUbicación del paquete completada, con las cantidades previstas, recibidas y dañadas de cada SKU.
inbound.discrepancyLa cantidad ubicada difiere del preaviso o hay unidades dañadas (se envía junto con inbound.received).
inventory.changedEl inventario ha cambiado; incluye el inventario actualizado de los SKU afectados.

inbound.received

{
  "event": "inbound.received",
  "delivery_id": "5b0f1c2e-8f3a-4d7e-9c21-0a6b2d4e8f10",
  "created_at": "2026-09-17T15:20:11+08:00",
  "data": {
    "inbound_order_id": 128,
    "reference_no": "PO-20260917-0001",
    "order_status": "completed_with_discrepancy",
    "tracking_no": "YT1234567890123",
    "work_order": "WO-SK-315",
    "warehouse_code": "SZ",
    "items": [
      { "seller_sku": "TEE-RED-S", "expected_qty": 40, "received_qty": 38, "damaged_qty": 2, "difference": 0 },
      { "seller_sku": "TEE-RED-M", "expected_qty": 60, "received_qty": 59, "damaged_qty": 0, "difference": -1 }
    ],
    "received_at": "2026-09-17T15:20:10+08:00"
  }
}

Verificar la firma

Cada envío incluye X-Lucky-Event, X-Lucky-Delivery-Id y X-Lucky-Signature: t=marca_de_tiempo,v1=firma. Calcula un HMAC-SHA256 con tu webhook secret sobre «marca de tiempo + . + cuerpo sin procesar», compáralo con v1 y rechaza las marcas de tiempo de más de 5 minutos. En los reintentos de un mismo evento, delivery_id no cambia y puede usarse para eliminar duplicados.

Las respuestas distintas de 2xx se reintentan tras 1 minuto, 5 minutos, 30 minutos, 2 horas y 6 horas; tras 20 fallos consecutivos, el webhook se desactiva automáticamente y debe volver a configurarse en el área de miembros.

// PHP
$body   = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_LUCKY_SIGNATURE'] ?? '';
parse_str(str_replace(',', '&', $header), $sig);   // ['t' => '1789…', 'v1' => 'ab12…']

$expected = hash_hmac('sha256', ($sig['t'] ?? '') . '.' . $body, getenv('LUCKY_WEBHOOK_SECRET'));

if (! hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) ($sig['t'] ?? 0)) > 300) {
    http_response_code(400);
    exit;
}
$event = json_decode($body, true);   // de-duplicate by $event['delivery_id']
http_response_code(200);

8 Códigos de error

error.code siempre está en inglés. Estos son los errores más comunes.

HTTPerror.codeDescripción
401—Clave ausente, no válida o caducada (cuerpo: {"message": "Unauthenticated."}).
403MERCHANT_TOKEN_REQUIREDEste token no tiene permiso para la API de Comerciantes (por ejemplo, un token generado al iniciar sesión como miembro normal).
403MERCHANT_NOT_APPROVED
MERCHANT_SUSPENDED
La cuenta aún no está aprobada como comerciante o el comerciante está suspendido.
403APP_SUSPENDED
APP_REVOKED
APP_NOT_FOUND
La aplicación de API asociada a la clave está suspendida o revocada.
422VALIDATION_FAILED
PRODUCT_NAME_REQUIRED
Formato de datos incorrecto; consulta el detalle por campo en error.errors.
422BATCH_TOO_LARGEEl número de elementos supera el límite del lote.
207 / 409SKU_BARCODE_DUPLICATE
SKU_BARCODE_CONFLICT
El código de barras del producto ya lo usa otro SKU o coincide con el código de barras del sistema o el código de preparación de otro SKU.
207 / 422GTIN_INVALID
HS_CODE_NOT_FOUND
Dígito de control del GTIN incorrecto o código arancelario inexistente.
404 / 422SKU_NOT_FOUND
SKU_IMPORT_BLOCKED
No se encuentra el SKU, o el SKU corresponde a un producto cuya importación no está permitida y no puede incluirse en un preaviso.
409INBOUND_REFERENCE_EXISTSEl número de referencia de la orden de recepción ya existe.
422TRACKING_IN_USE
TRACKING_FORECASTED_BY_OTHER
TRACKING_ALREADY_WAREHOUSED
TRACKING_NOT_AVAILABLE
El número de seguimiento ya está en una orden de recepción en curso, ya lo ha incluido otro miembro en un preaviso o ya ingresó en el almacén a nombre de otro miembro.
409INBOUND_NOT_CANCELLABLEYa ha llegado algún paquete; la orden de recepción no se puede cancelar.
400 / 409 / 422IDEMPOTENCY_KEY_INVALID
IDEMPOTENCY_IN_PROGRESS
IDEMPOTENCY_KEY_REUSED
Idempotency-Key con formato incorrecto, usada con otro contenido, o la solicitud anterior aún se está procesando.
409CONFLICT_RETRYOtra solicitud está modificando el mismo registro; vuelve a enviarla en unos instantes.
429RATE_LIMIT_EXCEEDEDLímite de solicitudes superado; espera el tiempo indicado en Retry-After y vuelve a intentarlo.

9 Ejemplos de código

Ejecuta los siguientes ejemplos en el servidor; nunca incluyas la clave en código de front-end.

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

$api = Http::withToken(config('services.lucky.merchant_key'))
    ->acceptJson()
    ->baseUrl('https://0523.tw/api/v1/merchant')
    ->timeout(20);

// 1) Sync SKUs (up to 200 per request)
$res = $api->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
    ->post('/skus/batch', ['items' => $items]);

foreach ($res->json('data') as $row) {
    if ($row['status'] === 'failed') {
        logger()->warning('SKU failed', $row['errors']);
    }
}

// 2) Forecast an inbound order
$order = $api->withHeaders(['Idempotency-Key' => 'po-' . $po->id])
    ->post('/inbound-orders', [
        'reference_no' => $po->number,
        'packages'     => [[
            'tracking_no' => $po->tracking_no,
            'items'       => [['seller_sku' => 'TEE-RED-S', 'qty' => 40]],
        ]],
    ])->throw()->json('data');

// 3) Read Shenzhen stock
$stock = $api->get('/inventory', ['warehouse_code' => 'SZ'])->json('data');

10 Soporte técnico

Si tienes cualquier problema durante la integración, indícanos la hora de la solicitud, el endpoint y el error.code para que podamos ayudarte a investigarlo.

Cuenta oficial de LINE @0523tw

Correo técnico howyunqisoftware@gmail.com

Versión v1, fase 1 (2026-09-17): SKU de productos, preaviso de recepción, etiquetado y ubicación en Shenzhen, consulta de inventario, webhooks.

Contactar con soporte para activarla