O que vem no JSON
O objeto data é o Bill of Lading virado dado. As cargas estão dentro do contêiner que as leva, então você não precisa cruzar listas.
A forma
| Bloco | O que traz |
|---|---|
bl_number | O número do BL, junto de tipo, situação de emissão, datas e vias originais |
reference_numbers | Booking, waybill, master BL, contrato de serviço e as demais referências |
shipper | Quem embarca: nome, identificação fiscal, endereço separado, contato |
consignee | Quem recebe, na mesma forma |
notify_parties | Lista, porque um BL pode ter mais de um notify |
agents | Armador e agentes, cada um com o papel |
other_parties | Qualquer papel que não seja nenhum dos acima |
voyage | Navio, viagem, portos de embarque e descarga, recebimento, entrega, transbordo |
freight | Incoterm, condição de pagamento e as linhas de custo |
containers | Um por contêiner, com as cargas que estão dentro dele |
cargo_without_container | As cargas que o documento não repartiu entre os contêineres |
declared_totals | Os totais como o documento os imprime, sem recálculo. Vêm null quando o documento não imprime um total: a plataforma não soma por você e apresenta como declarado |
A carga está dentro do contêiner
Esta é a diferença que mais economiza código do seu lado. Para saber o que vem no FCIU6596670, você lê o contêiner e lê o que está dentro. Não existe lista de vínculos para cruzar.
{
"container_number": "FCIU6596670",
"seal_numbers": ["UL-2443323"],
"container_type": "20GP",
"size_in_feet": 20,
"package_count": 18,
"gross_weight": { "value": 20291.664, "unit": "KG" },
"tare_weight_empty_container": { "value": 2100, "unit": "KG" },
"cargo_weight_excluding_tare": { "value": 18191.664, "unit": "KG" },
"measurement_volume": { "value": 25, "unit": "M3" },
"cargo": [ ... ]
}cargo_weight_excluding_tare é o bruto menos a tara, calculado aqui para você não refazer. Quando o documento não declara tara ele vem null, e nunca o bruto: armadores discordam sobre o que o peso bruto de um contêiner inclui, e escolher uma interpretação por você gravaria no seu sistema uma carga mais pesada do que é.
Quando a mesma carga está em dois contêineres
Acontece com frequência: 36 totes repartidos em 18 e 18. Uma carga e dois contêineres não cabem numa árvore sem repetir alguma coisa, então a carga aparece dentro dos dois — e três campos dizem isso em voz alta, para ninguém somar errado.
{
"cargo_id": 1,
"description": "EVOTHERM P25, TE, 2100 LB, HAZARDOUS CHEMICALS...",
"ncm_codes": [{ "code": "3824", "digit_count": 4 }],
"package_count_in_this_container": 18,
"gross_weight_in_this_container": { "value": 18191.664, "unit": "KG" },
"also_loaded_in_containers": ["HLBU3614917"],
"total_in_all_containers": {
"package_count": 36,
"gross_weight": { "value": 36383.328, "unit": "KG" }
}
}cargo_id é o mesmo nos dois contêineres. É por ele que você sabe que são a mesma carga, e não duas. Somar os nós sem olhar o id daria 72 volumes num embarque de 36.Quando a carga cabe num contêiner só, also_loaded_in_containers vem vazio e a parte é igual ao total.
Carga que o documento não repartiu
Um BL com três contêineres e três cargas frequentemente não diz qual carga está em qual. Nesse caso a plataforma não distribui por conta própria: essas cargas saem em cargo_without_container, inteiras, e quem responde pela carga decide na conferência.
Distribuir por plausibilidade produziria um vínculo com cara de dado lido, e esse vínculo vira declaração aduaneira com o NCM no contêiner errado.
Carga perigosa
Quando o documento declara carga perigosa, cada carga traz a lista dangerous_goods, com uma entrada por declaração impressa: número ONU, nome, classe, grupo de embalagem e o que mais o emissor escreveu junto. Carga comum vem com a lista vazia.
{
"cargo_id": 2,
"description": "ALUMINIUM PROFILES AND ACCESSORIES",
"hazardous_material_marked": true,
"dangerous_goods": [
{
"un_number": "1219",
"un_number_as_printed": "UN1219",
"proper_shipping_name": "ISOPROPANOL",
"technical_name": "ISOPROPANOL SOLUTION",
"hazard_class": "3",
"subsidiary_hazard_classes": [],
"packing_group": "II",
"flash_point": { "value": 12.0, "unit": "CEL", "method": "closed_cup", "as_printed": "12.0 C C.C." },
"shipped_as_limited_quantity": true,
"marine_pollutant": null,
"ems": null,
"package_count": 4,
"package_type": "BOX",
"emergency_contact": "+4917843374341"
},
{ "un_number": "1133", "proper_shipping_name": "ADHESIVES", "hazard_class": "3", "packing_group": "II", ... }
]
}| Campo | O que é |
|---|---|
un_number | Os quatro dígitos do número ONU. null quando o impresso não tem exatamente quatro |
un_number_as_printed | O número como estava no documento, com prefixo e pontuação |
proper_shipping_name | O nome apropriado para embarque, como impresso |
technical_name | O nome técnico que o emissor pôs entre parênteses |
hazard_class | Classe ou divisão, sem o rótulo: CLASS 3 vem como 3 |
subsidiary_hazard_classes | Riscos subsidiários declarados |
packing_group | I, II ou III, sempre em romano: PG 2 vem como II |
flash_point | Ponto de fulgor, com unidade (CEL ou FAH) e método (closed_cup ou open_cup) |
shipped_as_limited_quantity | true quando declarado LTD QTY. null quando o documento não diz |
marine_pollutant | true quando declarado poluente marinho. null quando o documento não diz |
ems | O plano de emergência do IMDG, como impresso |
package_count | Quantos volumes esta declaração cobre, quando impresso junto dela |
emergency_contact | O contato de emergência da declaração |
hazardous_material_marked é a coluna HM do formulário: true quando marcada, false quando existe e está em branco, null quando o formulário não tem a coluna.
null, mesmo quando o número ONU só admite um valor: completar pela lista da ONU faria uma declaração errada parecer certa. Declaração repetida no documento vem repetida.Tudo separado, até o CEP
Seu sistema raramente quer o texto como está no papel. Às vezes quer só o CNPJ, às vezes só o CEP. Cada parte vem quebrada até o último pedaço:
{
"name": "INGEVITY QUIMICA LTD",
"tax_ids": [
{ "type": "cnpj", "label": "CNPJ",
"number": "30381107001160", "as_printed": "30.381.107/0011-60" }
],
"address": {
"street": "AV CONSTANTE PAVAN",
"street_number": "4327",
"complement": null,
"district": "BETEL",
"city": "PAULINIA",
"state": "SP",
"postal_code": { "as_printed": "13148-198", "digits_only": "13148198" },
"country": "BRAZIL",
"country_code": "BR"
},
"contact": { "phone": "+55 19 3514-1600", "email": null, "fax": null, "attention_to": null }
}tax_ids é uma lista porque o mesmo bloco pode trazer CNPJ e inscrição estadual, ou um documento estrangeiro. number é o valor limpo, para comparar e gravar; as_printed é o que estava escrito, para conferir sem abrir o PDF.
Quantidade sempre vem com unidade
Peso, cubagem e medidas nunca vêm como número solto. Vêm como { value, unit }, com a unidade que o documento usou, sem conversão. Um BL em libras chega em libras: converter por você seria transformar em silêncio um número que vira declaração aduaneira.
"gross_weight": { "value": 18450.5, "unit": "KGS" },
"measurement_volume": { "value": 58.2, "unit": "CBM" }Como a leitura foi feita
Página de origem de cada campo, endereço como estava impresso, base de cada vínculo, correções automáticas e o texto que não coube em campo nenhum: nada disso é o BL, então nada disso está dentro de data. Fica em extraction, e vem completo só quando pedido.
"extraction": {
"contradictions_found": 0,
"unmapped_text_blocks": 2,
"auto_corrections_applied": 0,
"url": "/v1/ebl/documents/{job_id}?include=extraction"
}O resumo aparece sempre, mesmo sem pedir. Um documento com texto que não coube em campo nenhum precisa avisar que isso existe: a garantia de que nada se perde não pode depender de você adivinhar um parâmetro.
GET /v1/ebl/documents/{job_id}?include=extraction| Dentro de extraction | O que é |
|---|---|
unmapped_text | Todo texto que não virou campo, com a página. Nada é descartado |
contradictions_in_document | Onde o documento se contradiz. O documento não é corrigido: quem decide é quem responde pela carga |
auto_corrections | Consertos determinísticos aplicados sobre a leitura, como dígito verificador de contêiner |
party_sources | Página e endereço como impresso, por parte |
cargo_container_links | De onde veio cada vínculo carga × contêiner, e de onde vieram os números repartidos |
cargo_sources | O cargo_id de cada carga, a página em que foi lida e a página de cada declaração de carga perigosa |
Campo ausente e campo nulo
null significa que o documento não trazia aquilo. Não é zero, não é vazio, e nunca é um valor inventado para tapar a lacuna. Se o BL não declara o IMO do navio, vessel_imo_number vem null.
A chave continua presente de propósito: sem ela você não distingue "não consta no documento" de "o campo saiu da API". Se o tamanho da resposta importar mais que essa distinção, peça omit_null=true e as chaves nulas somem. Lista vazia e texto vazio continuam, porque já são um valor.
GET /v1/ebl/documents/{job_id}?omit_null=trueVersão do formato
Todo resultado carrega schema_version. Campo novo pode aparecer sem aviso, então trate desconhecido como ignorável. Campo existente não muda de significado nem some dentro da mesma versão.