API de Dropshipping
Para quem é isto
Seção intitulada “Para quem é isto”Para desenvolvedores que automatizam uma loja própria ou na qual trabalham, usando a API REST, os SDKs do Posty5 ou n8n. Compradores e fornecedores nunca chamam essas rotas. Se você gerencia a loja manualmente, o guia do lojista é a página que você procura. Abrir o guia do lojista
Autenticação
Seção intitulada “Autenticação”Cada solicitação carrega sua chave de API neste cabeçalho —
X-API-Key: YOUR_API_KEYCrie uma chave no painel do Posty5, nas configurações da conta, em Chaves de API. As chaves de API estão disponíveis para contas de Desenvolvedor.
Cada rota abaixo funciona em uma loja e verifica a permissão da loja exibida ao lado. O proprietário da chave deve ser o dono da loja ou fazer parte da equipe com essa permissão.
Quando o plano do proprietário da loja não inclui dropshipping (Pro ou superior), essas rotas são recusadas — conectar um fornecedor (com uma chave de API ou fazendo login), substituir suas credenciais, ativar uma conexão, alterar sua automação, navegar pelos produtos de um fornecedor, buscar um produto de um fornecedor, resolver a URL de um produto, visualizar ou executar uma importação, criar um link de produto e enviar, tentar novamente ou pagar um pedido ao fornecedor. O plano do proprietário é o que decide, não o plano do membro da equipe que está chamando. Todo o resto permanece aberto em qualquer plano, de modo que uma loja que caia abaixo do Pro ainda pode ler o que tem, desativar uma conexão, alterar suas configurações, testá-la ou desconectá-la, editar, sincronizar ou remover links de produtos, e cancelar um pedido ao fornecedor ou atendê-lo manualmente.
URL base
Seção intitulada “URL base”- dropshipping.developer.base.hostAt
- dropshipping.developer.base.prefixIs
- dropshipping.developer.base.docsAt
Os caminhos abaixo são relativos ao prefixo do fornecedor. O primeiro parâmetro é sempre o ID da loja e o ID seguinte é a conexão do fornecedor.
Conexões
Seção intitulada “Conexões”| Método | Rota | Permissão | O que faz |
|---|---|---|---|
GET | /:storeId/catalogue | suppliers.view | Os fornecedores que esta loja pode conectar, com o que cada um pode fazer. |
GET | /:storeId | suppliers.view | As conexões de fornecedores da loja, com integridade e automação. As credenciais nunca são retornadas. |
POST | /:storeId | suppliers.manage | Conecte um fornecedor com sua chave de API. A chave é verificada com o fornecedor antes de ser armazenada. |
POST | /:storeId/oauth/start | suppliers.manage | Iniciar a conexão de um fornecedor que utiliza login, como o AliExpress. Retorna o endereço para o qual o lojista será enviado. |
PUT | /:storeId/:id | suppliers.manage | Substituir as credenciais da conexão. |
POST | /:storeId/:id/test | suppliers.manage | Verificar a conexão agora e registrar seu status de saúde. |
GET | /:storeId/:id/balance | suppliers.view | O saldo da conta no fornecedor, caso o fornecedor o informe. |
GET | /:storeId/:id/impact | suppliers.view | O que a desconexão afetaria — produtos vinculados e pedidos abertos ao fornecedor. |
PUT | /:storeId/:id/settings | suppliers.manage | Alterar as próprias configurações do fornecedor. |
PUT | /:storeId/:id/automation | suppliers.manage | Alterar como os pedidos são enviados e os limites. |
PUT | /:storeId/:id/enabled | suppliers.manage | Ligar ou desligar a conexão. |
DELETE | /:storeId/:id | suppliers.manage | Desconectar. As credenciais são excluídas e os produtos importados continuam sendo da loja. |
Produtos de fornecedores, importações e links
Seção intitulada “Produtos de fornecedores, importações e links”| Método | Rota | Permissão | O que faz |
|---|---|---|---|
GET | /:storeId/:id/products | suppliers.import | Navegue ou pesquise no catálogo do fornecedor. |
POST | /:storeId/:id/products/resolve-url | suppliers.import | Converta um link de produto colado no ID de produto do fornecedor. |
GET | /:storeId/:id/products/:supplierProductId | suppliers.import | Um produto do fornecedor com suas variantes, custos e estoque. |
POST | /:storeId/:id/import/preview | suppliers.import | Defina o preço dos produtos escolhidos com a regra de preço e indique eventuais duplicatas. Nada é cobrado. |
POST | /:storeId/:id/import | suppliers.import | Importe até 50 produtos. Uma importação grande retorna um ID de tarefa para consulta. |
GET | /:storeId/imports/:jobId | suppliers.import | O progresso de uma importação em segundo plano. |
GET | /:storeId/links | suppliers.view | Os links de produtos da loja. |
POST | /:storeId/links | suppliers.import | Vincular um produto que a loja já possui a um produto do fornecedor. |
PUT | /:storeId/links/:linkId | suppliers.import | Alterar as variantes de um link, regra de preço ou chaves de sincronização. |
DELETE | /:storeId/links/:linkId | suppliers.import | Desvincular. O produto continua sendo da loja. |
POST | /:storeId/links/:linkId/sync | suppliers.import | Sincronizar um link agora. |
Pedidos ao fornecedor
Seção intitulada “Pedidos ao fornecedor”| Método | Rota | Permissão | O que faz |
|---|---|---|---|
GET | /:storeId/orders | suppliers.view | Pedidos ao fornecedor, do mais recente para o mais antigo, filtrados e paginados por cursor. Os campos de consulta estão listados abaixo da tabela. |
GET | /:storeId/orders/:supplierOrderId | suppliers.view | Um pedido ao fornecedor com seu histórico. |
POST | /:storeId/orders/:orderId/groups/:groupKey/submit | suppliers.orders.manage | Enviar uma parte de um pedido para o fornecedor agora. |
POST | /:storeId/orders/:supplierOrderId/retry | suppliers.orders.manage | Tentar novamente um pedido ao fornecedor na fila, pausado ou com falha. |
POST | /:storeId/orders/:supplierOrderId/pay | suppliers.orders.manage | Pagar um pedido ao fornecedor que foi criado, mas não pago. |
POST | /:storeId/orders/:supplierOrderId/cancel | suppliers.orders.manage | Retirar o pedido junto ao fornecedor, caso o fornecedor ainda permita. |
POST | /:storeId/orders/:orderId/groups/:groupKey/fulfil-manually | suppliers.orders.manage | Assumir uma parte para que a própria loja a envie. |
A lista aceita estes campos de consulta — status, needsReview, integrationId, orderId, contractModel, cursor, pageSize
A lista é paginada por cursor, como as outras listas da loja, e não aceita número de página. Uma página contém 25 linhas, a menos que você solicite outro tamanho, e nunca mais de 100. Cada resposta é uma página, as linhas, seguidas por um bloco de paginação com os cursores próximo e anterior, se há mais linhas, a contagem total e o tamanho da página —
{ "items": [{ "_id": "SUPPLIER_ORDER_ID", "status": "needsReview" }], "pagination": { "nextCursor": "NEXT_CURSOR", "previousCursor": null, "hasMore": true, "totalCount": 42, "pageSize": 25 }}Para ler a próxima página, repita a chamada com os mesmos filtros e o cursor seguinte da página anterior como cursor. Pare quando não houver mais linhas. Leia todas as páginas antes de agir sobre as linhas, uma nova tentativa ou um pagamento altera a lista que o cursor percorre.
Duas ações aceitam um corpo opcional —
submit—{ "payNow": true }— também pagar o pedido assim que for criado, onde o fornecedor pode ser pago a partir de um saldo. Pagar agora é decisão do próprio lojista, portanto, a verificação de se o comprador pagou é ignorada — um pedido não pago ou com pagamento na entrega também é pago, e a escolha é registrada no histórico do pedido ao fornecedor. As verificações de destino, estoque, limite de custo e saldo ainda se aplicam.retry—{ "acceptCost": true }— aceitar o novo custo do fornecedor após uma alteração de preço. É registrado como a decisão de quem fez a chamada.
Adições aos pedidos da loja
Seção intitulada “Adições aos pedidos da loja”GET /api/store-orders/:storeId/:id— Os detalhes do pedido adicionam as partes do pedido e, para um usuário que também tem a permissão de visualizar fornecedores, seus pedidos ao fornecedor com os custos.GET /api/store-orders/:storeId?needsAttention=true— Cada pedido na lista contém um resumo de suas partes, e a lista aceita um filtro para pedidos com uma parte que precisa de atenção.
Objetos
Seção intitulada “Objetos”Conexão de fornecedor
Seção intitulada “Conexão de fornecedor”supplierKey— Qual fornecedor, conforme nomeado no catálogo.mode— teste ou produção.enabled— Se a conexão está ativada.hasCredentials— Se as credenciais estão armazenadas. As credenciais em si nunca são retornadas.automation— Como os pedidos são enviados e os limites que os interrompem.health— O resultado da última verificação.isCircuitOpen,circuitOpenUntil— A conexão está pausada após erros repetidos, até esse momento.lastWebhookAt— Quando o fornecedor enviou a última notificação.webhookUrl— O endereço para o qual o fornecedor envia suas notificações, na lista de conexões. Vazio quando nenhum endereço público estiver configurado.
Link de produto
Seção intitulada “Link de produto”productId,supplierProductId— O produto da loja e o produto do fornecedor ao qual ele está vinculado.variants[]— Cada variante da loja mapeada para uma variante do fornecedor, com seu custo e estoque.priceRule— Como o preço da loja é calculado a partir do custo.sync— Quais campos a sincronização horária pode alterar.lastSyncAt,lastSyncError— A última sincronização e, se falhou, o motivo.
Um pedido ao fornecedor
Seção intitulada “Um pedido ao fornecedor”status— Em que etapa está o pedido ao fornecedor. A tabela abaixo lista todos os valores.reviewReason,reviewMessage— O motivo da interrupção, escolhido a partir de uma lista fechada, e as palavras do fornecedor com qualquer informação sensível removida.retryable— Se tentar novamente sem alterações pode funcionar.supplierOrderNumber— Nosso número, enviado ao fornecedor como o número do pedido dele. Nunca muda entre as repetições de uma mesma tentativa.supplierOrderId,supplierStatus— O ID e o status próprios do fornecedor, conforme definidos por ele.costs,payment— O valor cobrado pelo fornecedor e se a loja já realizou o pagamento.shipping— A transportadora e o código de rastreio assim que o fornecedor realizar o envio.attempt,events[]— O número desta tentativa e seu histórico.destination,destinationRedacted— O endereço de entrega, apenas para um chamador autorizado a ver dados de clientes. Caso contrário, ele é removido e a flag indica isso.
dropshipping.developer.objects.paymentValuesList
Em um pedido de loja
Seção intitulada “Em um pedido de loja”fulfilmentGroups[]— As partes do pedido — uma para os itens da própria loja e uma por conexão de fornecedor — cada uma com seu status, itens e remessa.fulfilmentSummary— Quantas partes existem e quantas foram enviadas ou entregues.supplierOrders[]— Os pedidos aos fornecedores por trás das partes, para um chamador autorizado a ver fornecedores.
Status e razões
Seção intitulada “Status e razões”Status de partes do pedido
Seção intitulada “Status de partes do pedido”Um pedido avança no ritmo de sua parte mais lenta. Ele só é considerado enviado quando todas as partes forem enviadas, e entregue quando todas forem entregues.
| Valor | Significado | O que um programa pode fazer |
|---|---|---|
pending | Ainda não iniciado. | Nada — aguarde. |
processing | Sendo preparado pela loja ou pelo fornecedor. | Nada — aguarde. |
shipped | Entregue a uma transportadora. | Ler o rastreamento do envio da parte. |
delivered | Entregue. Final. | Nada — aguarde. |
cancelled | Cancelado. Final. | Nada — aguarde. |
Status dos pedidos ao fornecedor
Seção intitulada “Status dos pedidos ao fornecedor”| Valor | Significado | O que um programa pode fazer |
|---|---|---|
queued | Aguardando para ser enviado. | Nada — aguarde. |
needsReview | Interrompido com um motivo. Requer intervenção humana ou alteração nos dados de entrada. | Exiba para um operador. Tente novamente apenas após a causa ser resolvida. |
submitted | Criado no fornecedor, ainda não aceito nem pago. | Efetue o pagamento, caso a loja pague manualmente. |
confirmed | Aceito e pago no fornecedor. | Nada — aguarde. |
processing | Sendo preparado pelo fornecedor. | Nada — aguarde. |
shipped | Enviado pelo fornecedor, com rastreamento. | Nada — aguarde. |
delivered | Entregue. Final. | Nada — aguarde. |
cancelled | Cancelado. Final. | Nada — aguarde. |
failed | Um erro temporário, como um tempo limite excedido. O trabalho tenta novamente sozinho. | Tente novamente uma vez, se as tentativas automáticas tiverem parado. |
Motivos de revisão
Seção intitulada “Motivos de revisão”Um pedido ao fornecedor pausado contém exatamente um destes motivos. A segunda coluna é o valor que a API define para cada um.
| Valor | retryable | Significado | O que um programa pode fazer |
|---|---|---|---|
insufficientBalance | false | O saldo da loja no fornecedor não pode cobrir o pedido. | Avise alguém. Tente novamente após recarregar o saldo. |
variantUnavailable | false | O fornecedor não oferece mais esta variante. | Nada sem intervenção humana. |
destinationUnsupported | false | O fornecedor não entrega lá ou a loja excluiu o país. | Nada sem intervenção humana. |
costAboveLimit | false | O custo está acima do limite definido pela loja. | Tentar novamente apenas por decisão de uma pessoa. |
costChanged | false | O preço do fornecedor mudou desde a importação. | Tentar novamente, aceitando o novo custo, apenas por decisão de uma pessoa. |
customerPaymentPending | false | O comprador não pagou online. | Envie quando a loja decidir. |
customerPaymentNotSettled | false | O pagamento está autorizado, mas não liquidado. | Tente novamente após a liquidação do pagamento. |
connectionUnhealthy | true | O fornecedor não respondeu ou a conexão está pausada. | Tente novamente mais tarde. |
supplierRefused | true | O fornecedor rejeitou o pedido. | Leia a mensagem. Tente novamente assim que a causa for resolvida. |
connectionMissing | false | A conexão está inativa, foi removida ou o fornecedor foi desativado pelo Posty5. | Nada. Uma pessoa precisa intervir. |
supplierAlreadyShipped | false | Uma solicitação de cancelamento foi recebida após o fornecedor já ter enviado o pedido. | Nada — trate como uma devolução. |
testMode | false | Foi feita uma conexão de teste com um fornecedor sem ambiente de teste (sandbox). Nenhum pedido foi feito. | Nada até que a conexão esteja ativa. |
customerCaptureFailed | false | Promessa de venda — o fornecedor foi pago, mas a cobrança do comprador falhou. | Avise alguém imediatamente. |
O endereço de notificação do fornecedor
Seção intitulada “O endereço de notificação do fornecedor”POST /api/store-suppliers/webhook/:supplierKey/:integrationIdOs fornecedores que enviam notificações chamam este endereço para relatar o status do pedido, rastreamento e estoque.
O Posty5 encontra a conexão a partir do endereço e verifica a mensagem com as credenciais da própria conexão. Cada recusa recebe a mesma resposta 400, e 503 quando o Posty5 não consegue decidir, fazendo com que o fornecedor envie novamente. Uma notificação apenas faz o Posty5 reler o pedido no fornecedor. Ela nunca movimenta dinheiro, estoque ou status por conta própria.
Idempotência e novas tentativas
Seção intitulada “Idempotência e novas tentativas”Um pedido ao fornecedor é protegido contra duplicatas de três maneiras.
- Um trabalho por parte do pedido, independentemente do que o acione —
- Uma chave única por tentativa, enviada ao fornecedor como o número do pedido. Antes de criar, o Posty5 pergunta ao fornecedor se esse número já existe, para que uma criação que expirou após o sucesso seja encontrada e não repetida.
- Antes de pagar, o Posty5 lê o status próprio do fornecedor. Um pedido já pago lá é registrado, não pago novamente.
O que isso significa para o seu programa
Seção intitulada “O que isso significa para o seu programa”- Chamar o envio duas vezes resulta em um único pedido ao fornecedor.
- dropshipping.developer.idem.rules.retryWhen
- Um pedido pausado não se resolve sozinho. Ele precisa de uma intervenção humana ou de uma entrada alterada.
- Para acompanhar um pedido, consulte o pedido ao fornecedor novamente. Não chame o envio em loop.
Quando os pedidos são enviados
Seção intitulada “Quando os pedidos são enviados”Com um nível automático, uma parte do fornecedor é enviada uma vez, quando o pedido é confirmado — por um membro da equipe ou por pagamento online.
O pagamento automático ao fornecedor exige que o pagamento do comprador seja efetuado, conforme confirmado pelo provedor de pagamento. Um pedido sem pagamento online fica aguardando, a menos que a conexão permita pedidos não pagos.
Sob a promessa de venda, o envio começa assim que o pagamento do comprador for autorizado, e o comprador é cobrado quando o fornecedor aceita.
Exemplos
Seção intitulada “Exemplos”Listar os pedidos ao fornecedor aguardando revisão —
curl "https://api.posty5.com/api/store-suppliers/STORE_ID/orders?needsReview=true" \ -H "X-API-Key: YOUR_API_KEY"A resposta é uma página de pedidos a fornecedores. Uma linha interrompida por saldo baixo se parece com isto —
{ "_id": "SUPPLIER_ORDER_ID", "orderNumber": "1042", "fulfilmentGroupKey": "GROUP_KEY", "supplierKey": "cjdropshipping", "attempt": 1, "status": "needsReview", "reviewReason": "insufficientBalance", "reviewMessage": "Balance is insufficient", "retryable": false, "supplierOrderNumber": "SUPPLIER_ORDER_NUMBER", "payment": { "status": "unpaid" }}A mesma chamada do TypeScript —
const response = await fetch( `https://api.posty5.com/api/store-suppliers/${storeId}/orders?needsReview=true`, { headers: { "X-API-Key": process.env.POSTY5_API_KEY! } },);const { result } = await response.json();// result.items: the supplier orders on this page// result.pagination.nextCursor: send it back as `cursor` while result.pagination.hasMoreE do C# —
using var http = new HttpClient { BaseAddress = new Uri("https://api.posty5.com") };http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("POSTY5_API_KEY"));var json = await http.GetStringAsync($"/api/store-suppliers/{storeId}/orders?needsReview=true");// { "result": { "items": [...], "pagination": { "nextCursor": "...", "hasMore": true, ... } } }// Send pagination.nextCursor back as &cursor= while pagination.hasMore is true.SDKs e n8n
Seção intitulada “SDKs e n8n”Os pacotes de loja JavaScript e .NET possuem cada um um cliente de fornecedores cobrindo cada grupo acima — catálogo, conexões, produtos do fornecedor, importações, links e pedidos ao fornecedor. Quando um pedido ao fornecedor é pausado para revisão, enviar, tentar novamente e pagar geram um erro em vez de retornar, portanto, leia o pedido ao fornecedor novamente para ver o motivo.
- npm —
@posty5/store4.3.0—store.suppliers - NuGet —
Posty5.Store3.2.0—store.Suppliers
Nenhuma dessas versões foi publicada ainda. Até que sejam, chame as rotas acima diretamente.
Do TypeScript, tente novamente cada pedido ao fornecedor pausado porque o preço do fornecedor mudou, aceitando o novo custo —
import { HttpClient } from "@posty5/core";import { IStoreSupplierOrder, StoreClient } from "@posty5/store";
const store = new StoreClient(new HttpClient({ apiKey: process.env.POSTY5_API_KEY }));
// Read every page first: a retry changes the list the cursor walks.const paused: IStoreSupplierOrder[] = [];let cursor: string | undefined;do { const page = await store.suppliers.listSupplierOrders(storeId, { needsReview: true, cursor, pageSize: 100 }); paused.push(...page.items); cursor = page.pagination.hasMore ? page.pagination.nextCursor ?? undefined : undefined;} while (cursor);
for (const supplierOrder of paused) { if (supplierOrder.reviewReason === "costChanged") { await store.suppliers.retry(storeId, supplierOrder._id, { acceptCost: true }); }}E do C# —
using Posty5.Core.Configuration;using Posty5.Core.Http;using Posty5.Core.Models;using Posty5.Store;using Posty5.Store.Models;
var http = new Posty5HttpClient(new Posty5Options { ApiKey = Environment.GetEnvironmentVariable("POSTY5_API_KEY") });var store = new StoreClient(http);
// Read every page first: a retry changes the list the cursor walks.var paused = new List<StoreSupplierOrder>();string? cursor = null;do{ var page = await store.Suppliers.ListSupplierOrdersAsync(storeId, new SupplierOrderSearchParams { NeedsReview = true }, new PaginationParams { Cursor = cursor, PageSize = 100 }); if (page == null) break; paused.AddRange(page.Items); cursor = page.Pagination.HasMore ? page.Pagination.NextCursor : null;} while (cursor != null);
foreach (var supplierOrder in paused){ if (supplierOrder.ReviewReason == "costChanged") await store.Suppliers.RetryAsync(storeId, supplierOrder.Id!, acceptCost: true);}O nó da loja Posty5 para n8n (versão 4.4.0 do pacote n8n) cobre fornecedores, produtos de fornecedores, links de produtos, pedidos ao fornecedor, partes de pedidos e pedidos. Ele também ainda não foi publicado.