Pedidos em JSON: esquema ph.order/1.2
Payload versionado de pedidos ph.order/1.2: esquema JSON publicado, regras de compatibilidade e exemplos de entrega.
Quando uma venda é confirmada, o pedido é entregue na integração (webhook, SFTP ou correio) com este JSON canónico e versionado. Esta página é a especificação exata do formato ph.order/1.2.
Regras de formato
- Todas as chaves estão sempre presentes; as chaves nunca são omitidas.
- null significa «dado desconhecido»; não deve interpretar-se como 0 (alguns canais não desagregam impostos por linha).
- Os montantes são números com até 2 casas decimais.
- tax_rate é um decimal: 0.21 equivale a 21 %.
- channel é o código interno do canal (p. ex. ebay, wllp) e channel_name o seu nome visível (p. ex. Ebay, Wallapop).
- total_gross é o preço de venda para o vendedor, com a comissão do vendedor incluída: channel_fees_gross (o que o canal lhe retém desse montante) e buyer_fees_gross (o que o comprador paga ao canal além do preço, nunca dentro de total_gross) são informativos; shipping_gross (transporte) também o é, e pode estar incluído ou não em total_gross consoante o canal (as lines dão a desagregação da mercadoria).
Exemplo de payload
{
"schema": "ph.order/1.2",
"order_id": "123456789",
"channel": "ebay",
"channel_name": "Ebay",
"created_at": "2026-06-18T10:32:00+00:00",
"status": "accepted",
"currency": "EUR",
"original_currency": "EUR",
"exchange_rate": 1.0,
"customer": {
"foreign_id": "a1b2c3d4",
"first_name": "Toni",
"last_name": "Bosch",
"company_name": null,
"email": "toni.bosch@example.com",
"tax_number": "12345678Z",
"phone": "+34600000000",
"address": {
"street": "Carrer Major 1",
"city": "Campdevànol",
"province": "Girona",
"postal_code": "17530",
"country": "ES"
}
},
"lines": [
{
"external_id": "ITEM-001",
"title": "Faro delantero izquierdo",
"quantity": 1,
"line_net": 100.00,
"line_tax": 21.00,
"line_gross": 121.00,
"tax_rate": 0.21
}
],
"shipping_gross": 10.00,
"channel_fees_gross": 13.00,
"buyer_fees_gross": null,
"total_net": 100.00,
"total_tax": 21.00,
"total_gross": 131.00,
"carrier": "Correos",
"tracking_code": "AB123456789ES",
"tracking_url": "https://tracking.example.com/AB123456789ES",
"payment_method": "card",
"source_account": null
}
Campos
| Campo | Tipo | Descrição |
|---|---|---|
schema | string | Identificador do esquema e da sua versão, «ph.order/MAIOR.MENOR» (hoje ph.order/1.2). Reparar apenas no maior. |
order_id | string | Identificador único do pedido. |
channel | string | Código interno do canal de venda (p. ex. ebay, wllp). |
channel_name | string | Nome visível do canal de venda (p. ex. Ebay, Wallapop). |
created_at | string | null | Data e hora de criação do pedido, em formato ISO 8601. |
status | string | Estado do pedido (p. ex. accepted). Lista de valores aberta. |
currency | string | null | Moeda dos montantes do pedido em formato ISO 4217 (p. ex. EUR). |
original_currency | string | null | Moeda em que o comprador pagou, em formato ISO 4217. Se for outra, o pedido foi convertido e os seus montantes estão em currency. |
exchange_rate | number | null | Unidades de original_currency que valia uma unidade de currency ao converter o pedido (p. ex. 0.8346 libras por euro); 1 se não foi convertido. |
customer | object | Dados do comprador (objeto; ver campos mais abaixo). |
lines | array | Linhas do pedido, uma por artigo (lista de objetos; ver campos mais abaixo). |
shipping_gross | number | null | Montante do envio com impostos incluídos. |
channel_fees_gross | number | null | Comissão que o canal retém ao vendedor pelo pedido (informativo; incluída em total_gross, o canal desconta-a do pagamento). |
buyer_fees_gross | number | null | Encargos que o comprador paga ao canal além do preço, p. ex. a proteção do comprador (informativo; não faz parte de total_gross). |
total_net | number | null | Base tributável total do pedido (sem impostos). |
total_tax | number | null | Montante total de impostos do pedido. |
total_gross | number | null | Preço de venda para o vendedor, impostos e comissão do vendedor incluídos (o transporte pode estar incluído ou não consoante o canal). |
carrier | string | null | Transportadora do envio. |
tracking_code | string | null | Código de seguimento do envio. |
tracking_url | string | null | URL de seguimento do envio. |
payment_method | string | null | Método de pagamento (p. ex. card). Lista de valores aberta. |
source_account | string | null | Conta de origem no canal de venda, se aplicável. |
customer.foreign_id | string | null | Identificador do comprador no canal de origem. |
customer.first_name | string | null | Nome do comprador. |
customer.last_name | string | null | Apelidos do comprador. |
customer.company_name | string | null | Denominação social do comprador, se for uma empresa. |
customer.email | string | null | Correio eletrónico do comprador. |
customer.tax_number | string | null | Identificação fiscal do comprador (NIF/CIF/VAT). |
customer.phone | string | null | Telefone do comprador. |
customer.address | object | Morada de envio do comprador (objeto; ver campos mais abaixo). |
customer.address.street | string | null | Rua e número da morada de envio. |
customer.address.city | string | null | Localidade da morada de envio. |
customer.address.province | string | null | Distrito ou região da morada de envio. |
customer.address.postal_code | string | null | Código postal da morada de envio. |
customer.address.country | string | null | País da morada de envio, em formato ISO 3166-1 alpha-2 (p. ex. ES). |
lines[].external_id | string | null | Identificador do artigo no catálogo (SKU ou referência). |
lines[].title | string | null | Título ou descrição do artigo. |
lines[].quantity | integer | null | Unidades do artigo nesta linha. |
lines[].line_net | number | null | Base tributável da linha (sem impostos). |
lines[].line_tax | number | null | Montante de impostos da linha. |
lines[].line_gross | number | null | Montante da linha com impostos incluídos. |
lines[].tax_rate | number | null | Taxa de imposto da linha em decimal (0.21 = 21 %). |
Compatibilidade e versões
Para não ter de voltar a mexer na integração em futuras versões, convém construir o leitor seguindo estas regras:
- Versionamento: o campo schema é ph.order/MAIOR.MENOR (hoje ph.order/1.2). Reparar apenas no MAIOR (o 1) e aceitar qualquer versão menor.
- Versões publicadas: 1.0, o esquema inicial. 1.1 adiciona buyer_fees_gross e fixa channel_fees_gross como a comissão que o canal cobra ao vendedor em todos os canais; no Wallapop continha a proteção do comprador, que passa para buyer_fees_gross. 1.2 adiciona original_currency e exchange_rate: um pedido pago noutra moeda chega com os montantes em euros, e estes campos indicam em que moeda o comprador pagou e a que câmbio.
- Só se adiciona, nunca se retira: dentro da versão maior 1 as mudanças são aditivas. Poderão adicionar-se campos novos (sempre presentes, com null quando não se apliquem), mas nunca se eliminará, renomeará nem se mudará o tipo ou o significado de um campo existente. Única exceção: a da 1.1 indicada nas versões publicadas.
- Ignorar os campos não reconhecidos: o leitor deve descartá-los sem falhar (não validar com additionalProperties: false).
- Listas de valores abertas: em status, channel, payment_method, currency e original_currency podem aparecer valores novos; tratar um valor desconhecido sem quebrar (p. ex. como «outro»).
- Só uma mudança de versão MAIOR (ph.order/2.0) exigiria adaptação, e seria avisada com antecedência; as versões menores não exigem qualquer mudança por parte do consumidor, salvo a exceção da 1.1 indicada acima.
Para validar com um JSON Schema, disponibiliza-se um laxo para ph.order/1.x que já contempla tudo isto (aceita campos novos e qualquer versão menor). Para coordenar a mudança ou solicitar o esquema e payloads de teste, contactar o responsável no Portal Hero.