mercado de serviços API de Comerciantes
Fase 1: produtos e recebimento

API de Comerciantes: conecte SKUs, pré-avisos de compra e o estoque de Shenzhen ao seu sistema

Para empresas que vendem na Shopee, Coupang e momo. Envie por API os códigos de barras de produto gerados ao anunciar e faça o pré-aviso dos códigos de rastreio e do conteúdo ao comprar; quando a mercadoria chega ao armazém de Shenzhen, uma ordem de serviço é aberta automaticamente e cada peça é etiquetada, escaneada e armazenada, com estoque e divergências informados em tempo real.

Empresas

Público-alvo (exige número de identificação fiscal de Taiwan de 8 dígitos)

200

Limite de SKUs por requisição em lote

WO-SK

Ordem de etiquetagem aberta automaticamente na chegada

60 / min

Limite padrão de requisições por chave

1 Visão geral

A fase 1 oferece “produtos e recebimento”: da criação do SKU até a armazenagem da mercadoria como estoque no armazém de Shenzhen.

O que você já pode fazer

  • Criar ou atualizar SKUs em lote (identificados pelo seu seller_sku), com um código de barras de produto para cada cor e cada tamanho, vinculados aos códigos de variação da Shopee / Coupang / momo.
  • Verificar automaticamente os requisitos de importação pelo código tarifário de 11 dígitos e sinalizar produtos que exigem inspeção, licença ou que não podem ser importados.
  • Fazer o pré-aviso dos códigos de rastreio e do conteúdo de cada caixa ao comprar; quando a mercadoria chega ao armazém de Shenzhen, uma ordem de etiquetagem WO-SK é aberta automaticamente e o armazém etiqueta, escaneia e armazena peça por peça.
  • Consultar o estoque por armazém e o extrato de movimentações de estoque, e receber por webhook, em tempo real, chegadas, recebimentos concluídos, divergências de quantidade e alterações de estoque.

Fluxo de recebimento

  1. Criar SKUs: envie códigos de barras de produto, variações, descrições declaradas e códigos tarifários.
  2. Pré-aviso de recebimento: envie os códigos de rastreio e a quantidade prevista de cada SKU.
  3. Chegada ao armazém de Shenzhen: ao escanear o código de rastreio, a ordem de serviço WO-SK é aberta e impressa automaticamente.
  4. Etiquetagem e armazenagem: o armazém imprime os códigos de barras de produto, etiqueta cada peça e a escaneia para contagem.
  5. Recebimento concluído: a quantidade recebida entra no estoque de Shenzhen, itens danificados são contados à parte e as divergências são notificadas ao seu sistema.
Sobre os requisitos de importação: o sistema faz a verificação automática com base nos códigos de requisitos de importação dos dados tarifários da Administração Aduaneira de Taiwan, apenas como referência operacional. Se um produto realmente exige inspeção, licença ou declaração aduaneira formal é determinado pela análise da alfândega e do nosso despachante aduaneiro parceiro. O estoque de um comerciante destina-se à venda e não se enquadra nas isenções para uso pessoal.

Funcionalidades planejadas

Pedidos de envio em lote, lotes de envio agrupados automaticamente conforme as regras de declaração, além de estoque antecipado, triagem e etiquetas de envio dos marketplaces no armazém de Taoyuan. Serão anunciados nesta página quando forem lançados.

2 Acesso e chaves

A API de Comerciantes está disponível apenas para empresas registradas, e cada chave é vinculada a uma conta de comerciante aprovada.

Como obter acesso

  1. Na área do membro, adicione um declarante do tipo “empresa” com o número de identificação fiscal de Taiwan de 8 dígitos.
  2. Entre em contato com o atendimento da HowBridge para solicitar a ativação da API de Comerciantes; a chave é emitida após a aprovação.
  3. A chave é exibida apenas uma vez. Guarde-a em uma variável de ambiente no servidor e nunca a coloque em navegador ou app.
  4. Para usar webhooks, primeiro configure e verifique a URL na página de API da área do membro e depois assine os eventos de comerciante.
Todas as requisições usam Authorization: Bearer <chave>. Tokens gerados ao entrar no app ou no site como membro comum não podem chamar a API de Comerciantes.
Authorization: Bearer 12|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/json

3 Convenções

Todos os endpoints seguem as regras abaixo.

Base URL

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

Formato e idioma

Requisições e respostas são em JSON. As mensagens de erro vêm em chinês tradicional por padrão; envie Accept-Language: en para recebê-las em inglês. Na lógica do seu código, use sempre error.code, que é fixo em inglês.

Estrutura da resposta

Em caso de sucesso, retorna {"success": true, "data": …, "meta": …}; em caso de falha, {"success": false, "error": {"code", "message", "errors", "context"}}, em que errors traz o detalhamento por campo. A única exceção é chave ausente ou inválida: HTTP 401 com corpo {"message": "Unauthenticated."}.

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

Limites de requisições

60 requisições por minuto e 5.000 por dia por chave (300 por minuto e 50.000 por dia no plano de alto volume); uma requisição em lote conta como uma. Para dados em tempo real, assine webhooks em vez de fazer polling.

Cabeçalho de respostaDescrição
X-RateLimit-LimitLimite por minuto
X-RateLimit-RemainingRequisições restantes neste minuto
X-RateLimit-Limit-Day
X-RateLimit-Remaining-Day
Limite diário e requisições restantes
Retry-AfterSegundos de espera para tentar novamente após exceder o limite

Idempotência (Idempotency-Key)

Requisições de escrita aceitam o cabeçalho Idempotency-Key (8–128 caracteres: letras, números e _-:.). Ao reenviar após um timeout de rede com a mesma chave e o mesmo conteúdo, você recebe a resposta original, com o cabeçalho Idempotent-Replayed: true; usar a mesma chave com conteúdo diferente retorna 422. Os registros são mantidos por 24 horas.

Respostas em lote

Endpoints em lote informam o resultado item a item: 200 quando todos têm sucesso, 207 quando alguns falham e 422 quando todos falham. Cada item traz index, status (created / updated / failed) e o motivo da falha.

Caracteres dos identificadores

seller_sku aceita apenas letras, números e ._- (1–64 caracteres); códigos de barras de produto aceitam também / e + (3–64 caracteres). Maiúsculas e minúsculas são tratadas como iguais.

4 SKUs de produtos

O SKU é identificado de forma única pelo seu seller_sku: reenviar o mesmo seller_sku atualiza o registro, alterando apenas os campos enviados.

Criar ou atualizar SKUs em lote

POST/api/v1/merchant/skus/batch

Até 200 itens por requisição. Cada item é processado de forma independente; a falha de um não afeta os demais.

CampoTipoObrigatórioDescrição
seller_skustringObrigatórioSeu código de SKU, por exemplo o SKU da variação na Shopee.
product_namestringObrigatório na criaçãoNome do produto. SKUs com o mesmo nome são agrupados no mesmo produto.
barcodestringOpcionalCódigo de barras do produto: o armazém imprime a etiqueta e faz o escaneamento na armazenagem com base neste código. Cada cor e cada tamanho devem ter códigos diferentes. Se não houver código de barras, deixe em branco e o sistema gera um código de barras do sistema. Acima de 16 caracteres, a etiqueta passa a usar o código de barras do sistema.
gtinstringOpcionalCódigo de barras internacional GTIN (8 / 12 / 13 / 14 dígitos, com validação do dígito verificador). Para a opção da Shopee “produto sem GTIN”, envie 00.
specobjectOpcionalVariação, por exemplo {"color": "preto", "size": "M"}, até 5 atributos.
declared_name_zh
declared_name_en
stringOpcionalDescrição declarada (em chinês / inglês): informe material e finalidade; não use “amostra” nem “presente”.
declared_unit_valuenumberOpcionalValor unitário declarado: o preço unitário de compra pago ao fornecedor, não o preço de venda no marketplace.
declared_currencystringOpcionalCNY, TWD ou USD; obrigatório quando o valor unitário for informado.
hs_codestringOpcionalCódigo de classificação tarifária de 11 dígitos, usado pelo sistema para verificar os requisitos de importação.
origin_countrystringOpcionalCódigo ISO do país de origem; padrão CN.
weight_gintegerOpcionalPeso unitário (gramas).
dimensions_cmarrayOpcionalComprimento, largura e altura (centímetros), por exemplo [20, 15, 3].
battery_typestringOpcionalnone, contained (embutida), packed (acompanha o produto), standalone (bateria avulsa).
channelsarrayOpcionalVínculos com produtos nos marketplaces, até 20: platform (shopee / coupang / momo / other), shop_id, item_id, model_id, platform_sku.

Exemplo de solicitação (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" } ]
    }
  ]
}'

Resposta 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 } }
}

Verificação de requisitos de importação (regulation.status)

okSem códigos de requisitos de importação.
review_requiredO requisito abrange apenas parte dos produtos (por exemplo, C02 “parte dos produtos deste item está sujeita a inspeção”); confirme conforme o uso real do produto.
formal_requiredHá requisitos de importação (inspeção, quarentena, licença etc.); não é possível usar a declaração simplificada.
blockedProduto da China continental com importação proibida (MW0, origem na China continental); não pode ser incluído em pré-aviso de recebimento.
unclassifiedCódigo tarifário ainda não informado; não é possível verificar.

Consultar SKUs

GET/api/v1/merchant/skus

Filtre por seller_sku, barcode, regulation_status ou updated_since (ISO 8601) e pagine com page / per_page (máximo 100).

Consultar um SKU

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

Atualizar vínculos com marketplaces

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

A lista enviada substitui integralmente os vínculos existentes; a mesma variação de marketplace não pode ser vinculada a dois SKUs.

Baixar etiquetas de código de barras

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

Retorna um PDF de etiquetas de 40×30 mm; qty é a quantidade de etiquetas (1–1000). O armazém de Shenzhen imprime a mesma etiqueta na etiquetagem; este endpoint serve para quando você quiser etiquetar por conta própria antes do envio.

5 Pré-aviso de recebimento

Depois que a compra for despachada, faça o pré-aviso com os códigos de rastreio e o conteúdo. Uma ordem de recebimento pode ter vários códigos de rastreio, cada um com seus SKUs e quantidades.

Criar ordem de recebimento

POST/api/v1/merchant/inbound-orders

Validação da ordem inteira: se houver qualquer erro, nada é criado. Um código de rastreio só pode pertencer a uma ordem de recebimento em andamento por vez; SKUs repetidos no mesmo pacote têm as quantidades somadas.

CampoTipoObrigatórioDescrição
reference_nostringObrigatórioSeu número de pedido de compra ou de ordem de recebimento, único por comerciante (letras, números e ._-/).
supplier_order_nostringOpcionalNúmero do pedido no fornecedor, por exemplo o número de um pedido no 1688.
warehouse_codestringOpcionalArmazém de recebimento; no momento, apenas SZ (armazém de Shenzhen).
notesstringOpcionalObservações (até 1.000 caracteres).
packagesarrayObrigatórioLista de pacotes, até 50.
packages[].tracking_nostringObrigatórioCódigo de rastreio de transportadora expressa chinesa.
packages[].carrierstringOpcionalCódigo da transportadora, por exemplo yto ou sf.
packages[].itemsarrayObrigatórioConteúdo do pacote: seller_sku e qty, até 500 linhas no total da ordem de recebimento.

Exemplo de solicitação (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 }
      ]
    }
  ]
}'
Proteção contra reenvio: criar novamente o mesmo reference_no retorna 409 INBOUND_REFERENCE_EXISTS, com o id da ordem de recebimento original em error.context.inbound_order_id. Para tentar novamente com segurança, envie o cabeçalho Idempotency-Key.

Status da ordem de recebimento

createdPré-aviso enviado; nenhum pacote chegou ainda.
partially_arrivedParte dos pacotes chegou ao armazém de Shenzhen.
arrivedTodos os pacotes chegaram; etiquetagem e armazenagem em andamento.
completedArmazenagem concluída, com quantidades iguais ao pré-aviso.
completed_with_discrepancyConcluída, mas com falta, excesso ou avaria.
cancelledCancelada.

Status do pacote

awaiting_arrivalAguardando chegada.
labelingRecebido no armazém; ordem de serviço aberta, etiquetagem e armazenagem em andamento.
receivedArmazenagem concluída.
mismatchA titularidade registrada na entrada do pacote não corresponde ao seu pré-aviso; o atendimento está verificando.
cancelledCancelado ou anulado; o código de rastreio foi liberado.

Consultar ordens de recebimento

GET/api/v1/merchant/inbound-orders

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

Filtre por status, reference_no ou updated_since. Cada pacote retorna as quantidades previstas, recebidas e danificadas, além da divergência.

Cancelar ordem de recebimento

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

Só é possível cancelar enquanto nenhum pacote tiver chegado; após o cancelamento, os códigos de rastreio podem ser incluídos em um novo pré-aviso.

6 Estoque

O estoque é separado por armazém: SZ armazém de Shenzhen e TY armazém de Taoyuan (o estoque de Taoyuan será liberado junto com as funções de envio).

Consultar estoque

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

Filtre por warehouse_code e seller_sku[] (até 200).

on_handQuantidade em estoque.
reservedQuantidade reservada para pedidos.
availableQuantidade disponível = em estoque − reservada.
damagedQuantidade danificada; não pode ser enviada.

Resposta 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 }
}

Extrato de movimentações de estoque

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

Registros de movimentação que só são acrescentados, nunca alterados. Avance as páginas com o cursor after_id (até 500 registros por requisição) e guarde o meta.next_after_id da resposta para continuar a conciliação.

7 Eventos de webhook

Os eventos são enviados para a sua URL assim que acontecem, sem necessidade de polling.

Configuração

  1. Configure a URL do webhook na página de API da área do membro (somente https) e conclua a verificação de propriedade: seu endpoint deve responder HTTP 200 com o corpo {"challenge": "valor recebido"}.
  2. Chame PUT /api/v1/merchant/webhook/events para assinar os eventos de comerciante. Alterar a URL depois na área do membro não remove essas assinaturas.
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_flaggedA verificação de requisitos de importação de um SKU passou para “requer confirmação”, “requer declaração aduaneira formal” ou “importação proibida”.
inbound.arrivedO pacote chegou ao armazém de Shenzhen e a ordem de serviço foi aberta.
inbound.mismatchA titularidade registrada na entrada do pacote não corresponde ao pré-aviso; o atendimento está verificando.
inbound.receivedArmazenagem do pacote concluída, com as quantidades previstas, recebidas e danificadas de cada SKU.
inbound.discrepancyA quantidade armazenada difere do pré-aviso ou há itens danificados (enviado junto com inbound.received).
inventory.changedO estoque foi alterado; inclui o estoque atualizado dos SKUs afetados.

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"
  }
}

Verificação de assinatura

Cada envio inclui X-Lucky-Event, X-Lucky-Delivery-Id e X-Lucky-Signature: t=timestamp,v1=assinatura. Calcule o HMAC-SHA256 com o seu webhook secret sobre “timestamp + . + corpo bruto”, compare com v1 e rejeite timestamps com mais de 5 minutos. Nas novas tentativas do mesmo evento, delivery_id não muda e pode ser usado para eliminar duplicidades.

Respostas diferentes de 2xx geram novas tentativas após 1 minuto, 5 minutos, 30 minutos, 2 horas e 6 horas; após 20 falhas consecutivas, o webhook é desativado automaticamente e precisa ser configurado novamente na área do membro.

// 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 erro

error.code é sempre em inglês. Abaixo estão os erros mais comuns.

HTTPerror.codeDescrição
401—Chave ausente, inválida ou expirada (corpo: {"message": "Unauthenticated."}).
403MERCHANT_TOKEN_REQUIREDEste token não tem permissão para a API de Comerciantes (por exemplo, um token gerado no login de membro comum).
403MERCHANT_NOT_APPROVED
MERCHANT_SUSPENDED
A conta ainda não foi aprovada como comerciante ou o comerciante está suspenso.
403APP_SUSPENDED
APP_REVOKED
APP_NOT_FOUND
O aplicativo de API vinculado à chave foi suspenso ou revogado.
422VALIDATION_FAILED
PRODUCT_NAME_REQUIRED
Formato de dados inválido; veja o detalhamento por campo em error.errors.
422BATCH_TOO_LARGEO número de itens excede o limite do lote.
207 / 409SKU_BARCODE_DUPLICATE
SKU_BARCODE_CONFLICT
O código de barras do produto já está em uso por outro SKU ou é igual ao código de barras do sistema ou ao código de separação de outro SKU.
207 / 422GTIN_INVALID
HS_CODE_NOT_FOUND
Dígito verificador do GTIN incorreto ou código tarifário inexistente.
404 / 422SKU_NOT_FOUND
SKU_IMPORT_BLOCKED
SKU não encontrado, ou o SKU é de importação proibida e não pode ser incluído em pré-aviso.
409INBOUND_REFERENCE_EXISTSO número de referência da ordem de recebimento já existe.
422TRACKING_IN_USE
TRACKING_FORECASTED_BY_OTHER
TRACKING_ALREADY_WAREHOUSED
TRACKING_NOT_AVAILABLE
O código de rastreio já está em uma ordem de recebimento em andamento, já foi incluído em pré-aviso de outro membro ou já deu entrada no armazém em nome de outro membro.
409INBOUND_NOT_CANCELLABLEJá há pacotes no armazém; a ordem de recebimento não pode ser cancelada.
400 / 409 / 422IDEMPOTENCY_KEY_INVALID
IDEMPOTENCY_IN_PROGRESS
IDEMPOTENCY_KEY_REUSED
Idempotency-Key com formato inválido, usada com conteúdo diferente, ou a requisição anterior ainda está em processamento.
409CONFLICT_RETRYO mesmo registro está sendo alterado por outra requisição; reenvie em instantes.
429RATE_LIMIT_EXCEEDEDLimite de requisições excedido; aguarde o tempo indicado em Retry-After e tente novamente.

9 Exemplos de código

Execute os exemplos abaixo no servidor; nunca coloque a chave em 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 Suporte técnico

Se tiver qualquer problema na integração, informe o horário da requisição, o endpoint e o error.code para que possamos ajudar a investigar.

Conta oficial no LINE @0523tw

E-mail técnico howyunqisoftware@gmail.com

Versão v1, fase 1 (2026-09-17): SKUs de produtos, pré-aviso de recebimento, etiquetagem e armazenagem em Shenzhen, consulta de estoque, webhooks.

Solicitar ativação ao suporte