Pular para o conteúdo

API de Dropshipping

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


Cada solicitação carrega sua chave de API neste cabeçalho —

Terminal window
X-API-Key: YOUR_API_KEY

Crie 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.


  • 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.

MétodoRotaPermissãoO que faz
GET/:storeId/cataloguesuppliers.viewOs fornecedores que esta loja pode conectar, com o que cada um pode fazer.
GET/:storeIdsuppliers.viewAs conexões de fornecedores da loja, com integridade e automação. As credenciais nunca são retornadas.
POST/:storeIdsuppliers.manageConecte um fornecedor com sua chave de API. A chave é verificada com o fornecedor antes de ser armazenada.
POST/:storeId/oauth/startsuppliers.manageIniciar 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/:idsuppliers.manageSubstituir as credenciais da conexão.
POST/:storeId/:id/testsuppliers.manageVerificar a conexão agora e registrar seu status de saúde.
GET/:storeId/:id/balancesuppliers.viewO saldo da conta no fornecedor, caso o fornecedor o informe.
GET/:storeId/:id/impactsuppliers.viewO que a desconexão afetaria — produtos vinculados e pedidos abertos ao fornecedor.
PUT/:storeId/:id/settingssuppliers.manageAlterar as próprias configurações do fornecedor.
PUT/:storeId/:id/automationsuppliers.manageAlterar como os pedidos são enviados e os limites.
PUT/:storeId/:id/enabledsuppliers.manageLigar ou desligar a conexão.
DELETE/:storeId/:idsuppliers.manageDesconectar. As credenciais são excluídas e os produtos importados continuam sendo da loja.
MétodoRotaPermissãoO que faz
GET/:storeId/:id/productssuppliers.importNavegue ou pesquise no catálogo do fornecedor.
POST/:storeId/:id/products/resolve-urlsuppliers.importConverta um link de produto colado no ID de produto do fornecedor.
GET/:storeId/:id/products/:supplierProductIdsuppliers.importUm produto do fornecedor com suas variantes, custos e estoque.
POST/:storeId/:id/import/previewsuppliers.importDefina o preço dos produtos escolhidos com a regra de preço e indique eventuais duplicatas. Nada é cobrado.
POST/:storeId/:id/importsuppliers.importImporte até 50 produtos. Uma importação grande retorna um ID de tarefa para consulta.
GET/:storeId/imports/:jobIdsuppliers.importO progresso de uma importação em segundo plano.
GET/:storeId/linkssuppliers.viewOs links de produtos da loja.
POST/:storeId/linkssuppliers.importVincular um produto que a loja já possui a um produto do fornecedor.
PUT/:storeId/links/:linkIdsuppliers.importAlterar as variantes de um link, regra de preço ou chaves de sincronização.
DELETE/:storeId/links/:linkIdsuppliers.importDesvincular. O produto continua sendo da loja.
POST/:storeId/links/:linkId/syncsuppliers.importSincronizar um link agora.
MétodoRotaPermissãoO que faz
GET/:storeId/orderssuppliers.viewPedidos 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/:supplierOrderIdsuppliers.viewUm pedido ao fornecedor com seu histórico.
POST/:storeId/orders/:orderId/groups/:groupKey/submitsuppliers.orders.manageEnviar uma parte de um pedido para o fornecedor agora.
POST/:storeId/orders/:supplierOrderId/retrysuppliers.orders.manageTentar novamente um pedido ao fornecedor na fila, pausado ou com falha.
POST/:storeId/orders/:supplierOrderId/paysuppliers.orders.managePagar um pedido ao fornecedor que foi criado, mas não pago.
POST/:storeId/orders/:supplierOrderId/cancelsuppliers.orders.manageRetirar o pedido junto ao fornecedor, caso o fornecedor ainda permita.
POST/:storeId/orders/:orderId/groups/:groupKey/fulfil-manuallysuppliers.orders.manageAssumir 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.
  • 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.

  • 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.
  • 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.
  • 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

  • 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.

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.

ValorSignificadoO que um programa pode fazer
pendingAinda não iniciado.Nada — aguarde.
processingSendo preparado pela loja ou pelo fornecedor.Nada — aguarde.
shippedEntregue a uma transportadora.Ler o rastreamento do envio da parte.
deliveredEntregue. Final.Nada — aguarde.
cancelledCancelado. Final.Nada — aguarde.
ValorSignificadoO que um programa pode fazer
queuedAguardando para ser enviado.Nada — aguarde.
needsReviewInterrompido 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.
submittedCriado no fornecedor, ainda não aceito nem pago.Efetue o pagamento, caso a loja pague manualmente.
confirmedAceito e pago no fornecedor.Nada — aguarde.
processingSendo preparado pelo fornecedor.Nada — aguarde.
shippedEnviado pelo fornecedor, com rastreamento.Nada — aguarde.
deliveredEntregue. Final.Nada — aguarde.
cancelledCancelado. Final.Nada — aguarde.
failedUm erro temporário, como um tempo limite excedido. O trabalho tenta novamente sozinho.Tente novamente uma vez, se as tentativas automáticas tiverem parado.

Um pedido ao fornecedor pausado contém exatamente um destes motivos. A segunda coluna é o valor que a API define para cada um.

ValorretryableSignificadoO que um programa pode fazer
insufficientBalancefalseO saldo da loja no fornecedor não pode cobrir o pedido.Avise alguém. Tente novamente após recarregar o saldo.
variantUnavailablefalseO fornecedor não oferece mais esta variante.Nada sem intervenção humana.
destinationUnsupportedfalseO fornecedor não entrega lá ou a loja excluiu o país.Nada sem intervenção humana.
costAboveLimitfalseO custo está acima do limite definido pela loja.Tentar novamente apenas por decisão de uma pessoa.
costChangedfalseO preço do fornecedor mudou desde a importação.Tentar novamente, aceitando o novo custo, apenas por decisão de uma pessoa.
customerPaymentPendingfalseO comprador não pagou online.Envie quando a loja decidir.
customerPaymentNotSettledfalseO pagamento está autorizado, mas não liquidado.Tente novamente após a liquidação do pagamento.
connectionUnhealthytrueO fornecedor não respondeu ou a conexão está pausada.Tente novamente mais tarde.
supplierRefusedtrueO fornecedor rejeitou o pedido.Leia a mensagem. Tente novamente assim que a causa for resolvida.
connectionMissingfalseA conexão está inativa, foi removida ou o fornecedor foi desativado pelo Posty5.Nada. Uma pessoa precisa intervir.
supplierAlreadyShippedfalseUma solicitação de cancelamento foi recebida após o fornecedor já ter enviado o pedido.Nada — trate como uma devolução.
testModefalseFoi 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.
customerCaptureFailedfalsePromessa de venda — o fornecedor foi pago, mas a cobrança do comprador falhou.Avise alguém imediatamente.

POST /api/store-suppliers/webhook/:supplierKey/:integrationId

Os 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.


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.
  • 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.

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.


Listar os pedidos ao fornecedor aguardando revisão —

Terminal window
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.hasMore

E 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.

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/store 4.3.0 — store.suppliers
  • NuGet — Posty5.Store 3.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.