From a380bc9801bb5471d9c1128bce07c1321dd26abc Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 10:36:07 -0700 Subject: [PATCH 01/14] docs(openapi): fix container edit path "Edit a container" was documented as PATCH /containers. The live API answers PATCH /containers/{id} (401 unauthenticated) and 404s on PATCH /containers, so move the operation under /containers/{id}. Types are regenerated. Co-Authored-By: Claude Opus 5.5 --- .../containers/edit-a-container.mdx | 2 +- docs/openapi.json | 114 +++++++++--------- .../src/generated/terminal49.ts | 56 ++++----- 3 files changed, 87 insertions(+), 85 deletions(-) diff --git a/docs/api-docs/api-reference/containers/edit-a-container.mdx b/docs/api-docs/api-reference/containers/edit-a-container.mdx index d6bc5927..b6a6efdb 100644 --- a/docs/api-docs/api-reference/containers/edit-a-container.mdx +++ b/docs/api-docs/api-reference/containers/edit-a-container.mdx @@ -3,5 +3,5 @@ title: Edit a container description: Update editable container attributes in the Terminal49 API, including weight, seal number, and reference fields, on active or completed shipments. og:title: Edit a Container | Terminal49 API Documentation og:description: Update container attributes like weight, seal number, or reference fields using the Terminal49 API. Apply changes to active or completed shipments. -openapi: patch /containers +openapi: patch /containers/{id} --- \ No newline at end of file diff --git a/docs/openapi.json b/docs/openapi.json index 50db8216..9cabd5c4 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -7489,63 +7489,6 @@ ] } ] - }, - "patch": { - "summary": "Edit a container", - "operationId": "patch-containers-id", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/container" - } - } - } - } - } - } - }, - "description": "Update a container", - "tags": [ - "Containers" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "data": { - "type": "object", - "required": [ - "attributes", - "type" - ], - "properties": { - "attributes": { - "type": "object", - "properties": { - "ref_numbers": { - "type": "array", - "items": { - "type": "string", - "example": "REF-12345" - } - } - } - } - } - } - } - } - } - } - } } }, "/containers/{id}": { @@ -7734,6 +7677,63 @@ "description": "Comma delimited list of relations to include" } ] + }, + "patch": { + "summary": "Edit a container", + "operationId": "patch-containers-id", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/container" + } + } + } + } + } + } + }, + "description": "Update a container", + "tags": [ + "Containers" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "attributes", + "type" + ], + "properties": { + "attributes": { + "type": "object", + "properties": { + "ref_numbers": { + "type": "array", + "items": { + "type": "string", + "example": "REF-12345" + } + } + } + } + } + } + } + } + } + } + } } }, "/containers/{id}/raw_events": { diff --git a/sdks/typescript-sdk/src/generated/terminal49.ts b/sdks/typescript-sdk/src/generated/terminal49.ts index bdddfe63..ed25485a 100644 --- a/sdks/typescript-sdk/src/generated/terminal49.ts +++ b/sdks/typescript-sdk/src/generated/terminal49.ts @@ -413,11 +413,7 @@ export interface paths { delete?: never; options?: never; head?: never; - /** - * Edit a container - * @description Update a container - */ - patch: operations["patch-containers-id"]; + patch?: never; trace?: never; }; "/containers/{id}": { @@ -439,7 +435,11 @@ export interface paths { delete?: never; options?: never; head?: never; - patch?: never; + /** + * Edit a container + * @description Update a container + */ + patch: operations["patch-containers-id"]; trace?: never; }; "/containers/{id}/raw_events": { @@ -5160,24 +5160,19 @@ export interface operations { }; }; }; - "patch-containers-id": { + "get-containers-id": { parameters: { - query?: never; + query?: { + /** @description Comma delimited list of relations to include */ + include?: string; + }; header?: never; - path?: never; - cookie?: never; - }; - requestBody?: { - content: { - "application/json": { - data?: { - attributes: { - ref_numbers?: string[]; - }; - }; - }; + path: { + id: string; }; + cookie?: never; }; + requestBody?: never; responses: { /** @description OK */ 200: { @@ -5187,24 +5182,32 @@ export interface operations { content: { "application/json": { data?: components["schemas"]["container"]; + included?: (components["schemas"]["shipment"] | components["schemas"]["terminal"] | components["schemas"]["transport_event"])[]; }; }; }; }; }; - "get-containers-id": { + "patch-containers-id": { parameters: { - query?: { - /** @description Comma delimited list of relations to include */ - include?: string; - }; + query?: never; header?: never; path: { id: string; }; cookie?: never; }; - requestBody?: never; + requestBody?: { + content: { + "application/json": { + data?: { + attributes: { + ref_numbers?: string[]; + }; + }; + }; + }; + }; responses: { /** @description OK */ 200: { @@ -5214,7 +5217,6 @@ export interface operations { content: { "application/json": { data?: components["schemas"]["container"]; - included?: (components["schemas"]["shipment"] | components["schemas"]["terminal"] | components["schemas"]["transport_event"])[]; }; }; }; From 65eebad11057c70c1f84e9a7f72408ef8262ed36 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 14:01:38 -0700 Subject: [PATCH 02/14] feat(sdk): cover the remaining OpenAPI operations Add the operations the SDK was missing: - documents, email submissions, and document schemas managers - container, shipment, and tracking-request custom field update/delete - container and shipment party roles - container update, shipping line get, webhook events and trigger, party create/update, and custom field list filters Co-Authored-By: Claude Opus 5.5 --- sdks/typescript-sdk/src/client.ts | 156 ++++++++- .../src/client.write-endpoints.test.ts | 311 ++++++++++++++++++ .../src/client/managers/containers.ts | 133 ++++++-- .../src/client/managers/documents.ts | 252 ++++++++++++++ .../client/managers/entity-subresources.ts | 126 +++++++ .../src/client/managers/index.ts | 2 + .../src/client/managers/shipments.ts | 110 +++++-- .../src/client/managers/shipping-lines.ts | 10 + .../src/client/managers/tracking-requests.ts | 67 +++- sdks/typescript-sdk/src/client/transport.ts | 6 +- 10 files changed, 1115 insertions(+), 58 deletions(-) create mode 100644 sdks/typescript-sdk/src/client.write-endpoints.test.ts create mode 100644 sdks/typescript-sdk/src/client/managers/documents.ts create mode 100644 sdks/typescript-sdk/src/client/managers/entity-subresources.ts diff --git a/sdks/typescript-sdk/src/client.ts b/sdks/typescript-sdk/src/client.ts index 50fda651..eb2adef5 100644 --- a/sdks/typescript-sdk/src/client.ts +++ b/sdks/typescript-sdk/src/client.ts @@ -17,6 +17,9 @@ import { } from './client/errors.js'; import { ContainerManager, + DocumentManager, + DocumentSchemaManager, + EmailSubmissionManager, ShipmentManager, ShippingLineManager, TrackingRequestManager, @@ -27,6 +30,7 @@ import type { TrackingRequestType, } from './client/managers/tracking-requests.js'; import { Transport } from './client/transport.js'; +import type { paths } from './generated/terminal49.js'; import type { CallOptions, ContainerInclude, @@ -56,6 +60,35 @@ export { ValidationError, }; +type TriggerWebhookBody = + paths['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/webhooks/trigger']['post']['requestBody']['content']['application/json']; + +/** Parameters for {@link Terminal49Client.triggerWebhook}. */ +export interface TriggerWebhookParams { + /** HTTPS destination URL for the test delivery. */ + url: string; + /** Webhook event name used to generate the example payload, e.g. `tracking_request.succeeded`. */ + event: string; + /** Optional secret used to sign the request in `X-T49-Webhook-Signature`. */ + secret?: string; + /** Document type for `document_representation.*` example payloads. */ + documentType?: string; +} + +/** Filters accepted by `customFields.list`. */ +export interface CustomFieldListFilters { + entityType?: 'Shipment' | 'Container'; + entityId?: string; + definitionId?: string; +} + +/** Filters accepted by `customFieldDefinitions.list`. */ +export interface CustomFieldDefinitionListFilters { + entityType?: 'Shipment' | 'Container'; + dataType?: string; + displayName?: string; +} + /** Configuration for {@link Terminal49Client}. */ export interface Terminal49ClientConfig { /** Terminal49 API token. Pass either the raw token or a value prefixed with `Token ` or `Bearer `. */ @@ -109,6 +142,9 @@ export class Terminal49Client { public containers: ContainerManager; public trackingRequests: TrackingRequestManager; public shippingLines: ShippingLineManager; + public documents: DocumentManager; + public emailSubmissions: EmailSubmissionManager; + public documentSchemas: DocumentSchemaManager; public webhooks = { list: (options?: ListOptions) => this.listWebhooks(options), @@ -123,6 +159,9 @@ export class Terminal49Client { delete: (id: string, options?: CallOptions) => this.deleteWebhook(id, options), ips: (options?: CallOptions) => this.getWebhookIps(options), + events: (options?: CallOptions) => this.listWebhookEvents(options), + trigger: (params: TriggerWebhookParams, options?: CallOptions) => + this.triggerWebhook(params, options), }; public webhookNotifications = { @@ -154,6 +193,13 @@ export class Terminal49Client { public parties = { list: (options?: ListOptions) => this.listParties(options), get: (id: string, options?: CallOptions) => this.getParty(id, options), + create: (payload: Record, options?: CallOptions) => + this.createParty(payload, options), + update: ( + id: string, + payload: Record, + options?: CallOptions, + ) => this.updateParty(id, payload, options), }; public metroAreas = { @@ -161,7 +207,9 @@ export class Terminal49Client { }; public customFieldDefinitions = { - list: (options?: ListOptions) => this.listCustomFieldDefinitions(options), + list: ( + options?: ListOptions & { filters?: CustomFieldDefinitionListFilters }, + ) => this.listCustomFieldDefinitions(options), get: (id: string, options?: CallOptions) => this.getCustomFieldDefinition(id, options), create: (payload: Record, options?: CallOptions) => @@ -196,7 +244,8 @@ export class Terminal49Client { }; public customFields = { - list: (options?: ListOptions) => this.listCustomFields(options), + list: (options?: ListOptions & { filters?: CustomFieldListFilters }) => + this.listCustomFields(options), get: (id: string, options?: CallOptions) => this.getCustomField(id, options), create: (payload: Record, options?: CallOptions) => @@ -237,6 +286,15 @@ export class Terminal49Client { defaultFormat, ); this.shippingLines = new ShippingLineManager(this.transport, defaultFormat); + this.documents = new DocumentManager(this.transport, defaultFormat); + this.emailSubmissions = new EmailSubmissionManager( + this.transport, + defaultFormat, + ); + this.documentSchemas = new DocumentSchemaManager( + this.transport, + defaultFormat, + ); } /** @@ -258,12 +316,8 @@ export class Terminal49Client { throw new ValidationError('query is required (/query)'); } - const params = new URLSearchParams({ query }); - // `/search` is not present in the generated OpenAPI types, so it cannot be - // routed through the typed `client.GET(...)`. `executeManual` runs it through - // the same Auth -> Retry -> ErrorMapping -> timeout pipeline as the typed client. - return this.transport.executeManual( - `${this.transport.baseUrl}/search?${params.toString()}`, + return this.transport.execute(() => + this.transport.client.GET('/search', { params: { query: { query } } }), ); } @@ -515,6 +569,38 @@ export class Terminal49Client { return this.formatResult(raw, options?.format); } + /** List the event names a webhook can subscribe to. */ + async listWebhookEvents(options?: CallOptions): Promise { + const raw = await this.transport.executeManual( + this.endpoint('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/webhooks/events'), + ); + return this.formatResult(raw, options?.format); + } + + /** Send a test webhook delivery with an example payload to a URL. */ + async triggerWebhook( + params: TriggerWebhookParams, + options?: CallOptions, + ): Promise { + const body: TriggerWebhookBody = { + url: params.url, + event: params.event, + secret: params.secret, + sample: params.documentType + ? { document_type: params.documentType } + : undefined, + }; + const raw = await this.transport.executeManual( + this.endpoint('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/webhooks/trigger'), + { + method: 'POST', + body: JSON.stringify(body), + headers: { 'Content-Type': 'application/json' }, + }, + ); + return this.formatResult(raw, options?.format); + } + /** List webhook notifications. */ async listWebhookNotifications(options?: ListOptions): Promise { const raw = await this.transport.executeManual( @@ -617,6 +703,36 @@ export class Terminal49Client { return this.formatResult(raw, options?.format); } + /** Create a party. */ + async createParty( + payload: Record, + options?: CallOptions, + ): Promise { + const raw = await this.transport.executeManual(this.endpoint('/parties'), { + method: 'POST', + body: JSON.stringify(payload), + headers: { 'Content-Type': 'application/json' }, + }); + return this.formatResult(raw, options?.format); + } + + /** Update a party. */ + async updateParty( + id: string, + payload: Record, + options?: CallOptions, + ): Promise { + const raw = await this.transport.executeManual( + this.endpoint(`/parties/${encodeURIComponent(id)}`), + { + method: 'PATCH', + body: JSON.stringify(payload), + headers: { 'Content-Type': 'application/json' }, + }, + ); + return this.formatResult(raw, options?.format); + } + /** Fetch a metro area by ID. */ async getMetroArea(id: string, options?: CallOptions): Promise { const raw = await this.transport.executeManual( @@ -626,9 +742,17 @@ export class Terminal49Client { } /** List custom field definitions. */ - async listCustomFieldDefinitions(options?: ListOptions): Promise { + async listCustomFieldDefinitions( + options?: ListOptions & { filters?: CustomFieldDefinitionListFilters }, + ): Promise { + const filters = options?.filters; const raw = await this.transport.executeManual( - this.endpoint('/custom_field_definitions', this.listQuery(options)), + this.endpoint('/custom_field_definitions', { + ...this.listQuery(options), + 'filter[entity_type]': filters?.entityType, + 'filter[data_type]': filters?.dataType, + 'filter[display_name]': filters?.displayName, + }), ); return this.formatResult(raw, options?.format); } @@ -772,9 +896,17 @@ export class Terminal49Client { } /** List custom field assignments. */ - async listCustomFields(options?: ListOptions): Promise { + async listCustomFields( + options?: ListOptions & { filters?: CustomFieldListFilters }, + ): Promise { + const filters = options?.filters; const raw = await this.transport.executeManual( - this.endpoint('/custom_fields', this.listQuery(options)), + this.endpoint('/custom_fields', { + ...this.listQuery(options), + 'filter[entity_type]': filters?.entityType, + 'filter[entity_id]': filters?.entityId, + 'filter[definition_id]': filters?.definitionId, + }), ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client.write-endpoints.test.ts b/sdks/typescript-sdk/src/client.write-endpoints.test.ts new file mode 100644 index 00000000..74ce0a5d --- /dev/null +++ b/sdks/typescript-sdk/src/client.write-endpoints.test.ts @@ -0,0 +1,311 @@ +import { describe, expect, it } from 'vite-plus/test'; +import { Terminal49Client } from './client.js'; +import { jsonResponse } from './test/mock-fetch.js'; + +interface RecordedCall { + method: string; + path: string; + query: Record; + body: any; +} + +function buildClient() { + const calls: RecordedCall[] = []; + const fetchImpl: typeof fetch = async (input, init) => { + const request = input instanceof Request ? input : new Request(input, init); + const url = new URL(request.url); + const text = await request.clone().text(); + calls.push({ + method: request.method, + path: url.pathname.replace('/v2', ''), + query: Object.fromEntries(url.searchParams), + body: text ? JSON.parse(text) : undefined, + }); + if (request.method === 'DELETE') return new Response(null, { status: 204 }); + return jsonResponse({ data: { id: 'x', type: 'stub' } }); + }; + const client = new Terminal49Client({ + apiToken: 'token-123', + apiBaseUrl: 'https://api.test/v2', + fetchImpl, + maxRetries: 0, + }); + return { client, calls }; +} + +describe('entity custom fields', () => { + it.each([ + ['containers', 'containers'], + ['shipments', 'shipments'], + ['trackingRequests', 'tracking_requests'], + ] as const)( + '%s exposes list/create/update/delete', + async (manager, collection) => { + const { client, calls } = buildClient(); + const m = client[manager]; + + await m.customFields('id-1'); + await m.setCustomField('id-1', 'po_number', 'PO-1'); + await m.updateCustomField('id-1', 'po_number', 'PO-2'); + await m.deleteCustomField('id-1', 'po_number'); + + expect(calls.map((c) => [c.method, c.path])).toEqual([ + ['GET', `/${collection}/id-1/custom_fields`], + ['POST', `/${collection}/id-1/custom_fields`], + ['PATCH', `/${collection}/id-1/custom_fields/po_number`], + ['DELETE', `/${collection}/id-1/custom_fields/po_number`], + ]); + expect(calls[0].query).toEqual({ include: 'definition' }); + expect(calls[1].body).toEqual({ + data: { + type: 'custom_field', + attributes: { api_slug: 'po_number', value: 'PO-1' }, + }, + }); + expect(calls[2].body).toEqual({ + data: { type: 'custom_field', attributes: { value: 'PO-2' } }, + }); + }, + ); +}); + +describe('party roles', () => { + it.each(['containers', 'shipments'] as const)( + '%s exposes list/add/remove', + async (collection) => { + const { client, calls } = buildClient(); + const m = client[collection]; + + await m.partyRoles('id-1'); + await m.addPartyRole('id-1', 'consignee', 'party-9'); + await m.removePartyRole('id-1', 'role-3'); + + expect(calls.map((c) => [c.method, c.path])).toEqual([ + ['GET', `/${collection}/id-1/party_roles`], + ['POST', `/${collection}/id-1/party_roles`], + ['DELETE', `/${collection}/id-1/party_roles/role-3`], + ]); + expect(calls[1].body).toEqual({ + data: { + type: 'party_role', + attributes: { role: 'consignee' }, + relationships: { party: { data: { type: 'party', id: 'party-9' } } }, + }, + }); + }, + ); +}); + +describe('containers', () => { + it('updates a container by id', async () => { + const { client, calls } = buildClient(); + await client.containers.update('c-1', { ref_numbers: ['REF-1'] }); + expect(calls[0]).toMatchObject({ + method: 'PATCH', + path: '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/containers/c-1', + body: { + data: { + type: 'container', + id: 'c-1', + attributes: { ref_numbers: ['REF-1'] }, + }, + }, + }); + }); +}); + +describe('shipping lines', () => { + it('fetches a shipping line by id', async () => { + const { client, calls } = buildClient(); + await client.shippingLines.get('sl-1'); + expect(calls[0]).toMatchObject({ + method: 'GET', + path: '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/shipping_lines/sl-1', + }); + }); +}); + +describe('documents', () => { + it('lists documents with filters and pagination', async () => { + const { client, calls } = buildClient(); + await client.documents.list( + { + filename: 'invoice', + reference: 'REF', + documentTypes: ['bill_of_lading', 'arrival_notice'], + sort: '-created_at', + include: 'shipments', + }, + { page: 2, pageSize: 10 }, + ); + expect(calls[0]).toMatchObject({ + method: 'GET', + path: '/documents', + query: { + 'filter[filename]': 'invoice', + 'filter[reference]': 'REF', + 'filter[document_types]': 'bill_of_lading,arrival_notice', + sort: '-created_at', + include: 'shipments', + 'page[number]': '2', + 'page[size]': '10', + }, + }); + }); + + it('covers every document operation', async () => { + const { client, calls } = buildClient(); + const docs = client.documents; + + await docs.create({ name: 'BOL.pdf', attachedDocument: 'blob-1' }); + await docs.get('d-1', { include: 'shipments' }); + await docs.update('d-1', { + documentTypeManual: 'bill_of_lading', + extractedDataManual: null, + }); + await docs.delete('d-1'); + await docs.types(); + await docs.downloadUrl('d-1'); + await docs.reextract('d-1'); + await docs.reclassify('d-1'); + await docs.relink('d-1'); + await docs.rotate('d-1', 90); + + expect(calls.map((c) => [c.method, c.path])).toEqual([ + ['POST', '/documents'], + ['GET', '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/documents/d-1'], + ['PATCH', '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/documents/d-1'], + ['DELETE', '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/documents/d-1'], + ['GET', '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/documents/types'], + ['GET', '/documents/d-1/download_url'], + ['POST', '/documents/d-1/reextract'], + ['POST', '/documents/d-1/reclassify'], + ['POST', '/documents/d-1/relink'], + ['POST', '/documents/d-1/rotate'], + ]); + expect(calls[0].body).toEqual({ + data: { + type: 'document', + attributes: { name: 'BOL.pdf', attached_document: 'blob-1' }, + }, + }); + expect(calls[1].query).toEqual({ include: 'shipments' }); + expect(calls[2].body).toEqual({ + data: { + type: 'document', + attributes: { + document_type_manual: 'bill_of_lading', + extracted_data_manual: null, + }, + }, + }); + expect(calls[9].body).toEqual({ degrees: 90 }); + }); + + it('rejects create without required attributes', async () => { + const { client, calls } = buildClient(); + await expect( + client.documents.create({ name: '', attachedDocument: 'blob-1' }), + ).rejects.toThrow('name is required'); + expect(calls).toHaveLength(0); + }); +}); + +describe('email submissions and document schemas', () => { + it('lists and fetches email submissions, and fetches a schema', async () => { + const { client, calls } = buildClient(); + await client.emailSubmissions.list({ include: 'documents', page: 1 }); + await client.emailSubmissions.get('e-1'); + await client.documentSchemas.get('bill_of_lading'); + + expect(calls.map((c) => [c.method, c.path])).toEqual([ + ['GET', '/email_submissions'], + ['GET', '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/email_submissions/e-1'], + ['GET', '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/document_schemas/bill_of_lading'], + ]); + expect(calls[0].query).toEqual({ + include: 'documents', + 'page[number]': '1', + }); + }); +}); + +describe('webhooks', () => { + it('lists events and triggers a test delivery', async () => { + const { client, calls } = buildClient(); + await client.webhooks.events(); + await client.webhooks.trigger({ + url: 'https://example.com/hook', + event: 'document_representation.created', + secret: 's3cret', + documentType: 'dray_delivery_order', + }); + + expect(calls[0]).toMatchObject({ method: 'GET', path: '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/webhooks/events' }); + expect(calls[1]).toMatchObject({ + method: 'POST', + path: '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/webhooks/trigger', + body: { + url: 'https://example.com/hook', + event: 'document_representation.created', + secret: 's3cret', + sample: { document_type: 'dray_delivery_order' }, + }, + }); + }); +}); + +describe('parties', () => { + it('creates and updates parties', async () => { + const { client, calls } = buildClient(); + const payload = { data: { attributes: { company_name: 'ACME' } } }; + await client.parties.create(payload); + await client.parties.update('p-1', payload); + + expect(calls.map((c) => [c.method, c.path, c.body])).toEqual([ + ['POST', '/parties', payload], + ['PATCH', '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/parties/p-1', payload], + ]); + }); +}); + +describe('custom field list filters', () => { + it('forwards custom field and definition filters', async () => { + const { client, calls } = buildClient(); + await client.customFields.list({ + filters: { + entityType: 'Container', + entityId: 'c-1', + definitionId: 'def-1', + }, + }); + await client.customFieldDefinitions.list({ + pageSize: 5, + filters: { entityType: 'Shipment', dataType: 'enum', displayName: 'PO' }, + }); + + expect(calls[0].query).toEqual({ + 'filter[entity_type]': 'Container', + 'filter[entity_id]': 'c-1', + 'filter[definition_id]': 'def-1', + }); + expect(calls[1].query).toEqual({ + 'page[size]': '5', + 'filter[entity_type]': 'Shipment', + 'filter[data_type]': 'enum', + 'filter[display_name]': 'PO', + }); + }); +}); + +describe('search', () => { + it('runs through the typed client', async () => { + const { client, calls } = buildClient(); + await client.search('MSCU1234567'); + expect(calls[0]).toMatchObject({ + method: 'GET', + path: '/search', + query: { query: 'MSCU1234567' }, + }); + }); +}); diff --git a/sdks/typescript-sdk/src/client/managers/containers.ts b/sdks/typescript-sdk/src/client/managers/containers.ts index 13cf13e0..f39f653e 100644 --- a/sdks/typescript-sdk/src/client/managers/containers.ts +++ b/sdks/typescript-sdk/src/client/managers/containers.ts @@ -20,6 +20,16 @@ import { normalizeInclude, } from '../query.js'; import { BaseManager } from './base.js'; +import { + createCustomField, + createPartyRole, + deleteCustomField, + deletePartyRole, + listCustomFields, + listPartyRoles, + type PartyRoleName, + updateCustomField, +} from './entity-subresources.js'; const DEFAULT_CONTAINER_INCLUDES = [ 'shipment', @@ -49,10 +59,26 @@ export class ContainerManager extends BaseManager { return this.formatResult(raw, options?.format); } - async customFields(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - `${this.transport.baseUrl}/containers/${encodeURIComponent(id)}/custom_fields?include=definition`, + /** Update container attributes such as `ref_numbers`. */ + async update( + id: string, + attrs: Record, + options?: CallOptions, + ): Promise { + const payload = { + data: { type: 'container' as const, id, attributes: attrs }, + }; + const raw = await this.transport.execute(() => + this.transport.client.PATCH('/containers/{id}', { + params: { path: { id } }, + body: payload as any, + }), ); + return this.formatResult(raw, options?.format); + } + + async customFields(id: string, options?: CallOptions): Promise { + const raw = await listCustomFields(this.transport, 'containers', id); return this.formatResult(raw, options?.format, mapCustomFields); } @@ -101,6 +127,11 @@ export class ContainerManager extends BaseManager { return this.formatResult(raw, options?.format, mapTransportEvents); } + /** + * @deprecated `GET /containers/{id}/route` is no longer part of the public + * Terminal49 API and is expected to return `NotFoundError`. Use + * {@link ContainerManager.map} for routing geometry instead. + */ async route(id: string, options?: CallOptions): Promise { // The route path is absent from current OpenAPI, although this SDK already // supports it. Keep the existing client/middleware path while regenerating @@ -125,29 +156,89 @@ export class ContainerManager extends BaseManager { return this.formatResult(raw, options?.format); } + /** Create a custom field value on a container. */ async setCustomField( id: string, - fieldId: string, + apiSlug: string, value: unknown, options?: CallOptions, ): Promise { - const encodedId = encodeURIComponent(id); - const payload = { - data: { - type: 'custom_field', - attributes: { - api_slug: fieldId, - value, - }, - }, - }; - const raw = await this.transport.executeManual( - `${this.transport.baseUrl}/containers/${encodedId}/custom_fields`, - { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await createCustomField( + this.transport, + 'containers', + id, + apiSlug, + value, + ); + return this.formatResult(raw, options?.format); + } + + /** Update an existing custom field value on a container. */ + async updateCustomField( + id: string, + apiSlug: string, + value: unknown, + options?: CallOptions, + ): Promise { + const raw = await updateCustomField( + this.transport, + 'containers', + id, + apiSlug, + value, + ); + return this.formatResult(raw, options?.format); + } + + /** Remove a custom field value from a container. */ + async deleteCustomField( + id: string, + apiSlug: string, + options?: CallOptions, + ): Promise { + const raw = await deleteCustomField( + this.transport, + 'containers', + id, + apiSlug, + ); + return this.formatResult(raw, options?.format); + } + + /** List the party roles (shipper, consignee, ...) assigned to a container. */ + async partyRoles(id: string, options?: CallOptions): Promise { + const raw = await listPartyRoles(this.transport, 'containers', id); + return this.formatResult(raw, options?.format); + } + + /** Assign a party to a container in the given role. */ + async addPartyRole( + id: string, + role: PartyRoleName, + partyId: string, + options?: CallOptions, + ): Promise { + const raw = await createPartyRole( + this.transport, + 'containers', + id, + role, + partyId, + ); + return this.formatResult(raw, options?.format); + } + + /** Remove a party role assignment from a container. */ + async removePartyRole( + id: string, + partyRoleId: string, + options?: CallOptions, + ): Promise { + const raw = await deletePartyRole( + this.transport, + 'containers', + id, + partyRoleId, ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client/managers/documents.ts b/sdks/typescript-sdk/src/client/managers/documents.ts new file mode 100644 index 00000000..cd7dd59c --- /dev/null +++ b/sdks/typescript-sdk/src/client/managers/documents.ts @@ -0,0 +1,252 @@ +import type { paths } from '../../generated/terminal49.js'; +import type { CallOptions, ListOptions } from '../../types/options.js'; +import { ValidationError } from '../errors.js'; +import { applyTypedPagination } from '../query.js'; +import { BaseManager } from './base.js'; + +type DocumentListQuery = NonNullable< + paths['/documents']['get']['parameters']['query'] +>; +type EmailSubmissionListQuery = NonNullable< + paths['/email_submissions']['get']['parameters']['query'] +>; +type DocumentUpdateAttributes = NonNullable< + paths['/documents/{id}']['patch']['requestBody']['content']['application/json']['data'] +>['attributes']; + +/** Filters accepted by {@link DocumentManager.list}. */ +export interface DocumentListFilters { + /** Full-text match on the document filename. */ + filename?: string; + /** Filter by reference token. */ + reference?: string; + /** One or more document types (sent comma-separated). */ + documentTypes?: readonly string[]; + /** Sort by `document_type`, `added_by`, or `created_at`; prefix with `-` for descending. */ + sort?: string; + /** Comma-separated JSON:API includes. */ + include?: string; +} + +/** Attributes accepted by {@link DocumentManager.create}. */ +export interface CreateDocumentParams { + /** Display name for the document. */ + name: string; + /** ActiveStorage signed blob id returned by a direct upload. */ + attachedDocument: string; +} + +/** Attributes accepted by {@link DocumentManager.update}. */ +export interface UpdateDocumentParams { + /** Manually override the classified document type. */ + documentTypeManual?: string; + /** Manually provide extracted key/value data. Pass `null` to clear manual values. */ + extractedDataManual?: DocumentUpdateAttributes['extracted_data_manual']; +} + +export type DocumentRotation = 90 | 180 | 270; + +export class DocumentManager extends BaseManager { + /** List documents with optional filters and pagination. */ + async list( + filters: DocumentListFilters = {}, + options?: ListOptions, + ): Promise { + const query: DocumentListQuery = { + include: filters.include, + sort: filters.sort, + 'filter[filename]': filters.filename, + 'filter[reference]': filters.reference, + 'filter[document_types]': filters.documentTypes?.join(','), + }; + applyTypedPagination(query, options); + + const raw = await this.transport.execute(() => + this.transport.client.GET('/documents', { params: { query } }), + ); + return this.formatResult(raw, options?.format); + } + + /** Fetch a document by ID. */ + async get( + id: string, + options?: CallOptions & { include?: string }, + ): Promise { + const raw = await this.transport.execute(() => + this.transport.client.GET('/documents/{id}', { + params: { + path: { id }, + query: options?.include ? { include: options.include } : undefined, + }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Create a document from a previously direct-uploaded blob. */ + async create( + params: CreateDocumentParams, + options?: CallOptions, + ): Promise { + if (!params.name) { + throw new ValidationError('name is required (/data/attributes/name)'); + } + if (!params.attachedDocument) { + throw new ValidationError( + 'attached_document is required (/data/attributes/attached_document)', + ); + } + + const raw = await this.transport.execute(() => + this.transport.client.POST('/documents', { + body: { + data: { + type: 'document', + attributes: { + name: params.name, + attached_document: params.attachedDocument, + }, + }, + }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Override a document's type or extracted data. */ + async update( + id: string, + params: UpdateDocumentParams, + options?: CallOptions, + ): Promise { + const attributes: DocumentUpdateAttributes = {}; + if (params.documentTypeManual !== undefined) { + attributes.document_type_manual = params.documentTypeManual; + } + if (params.extractedDataManual !== undefined) { + attributes.extracted_data_manual = params.extractedDataManual; + } + + const raw = await this.transport.execute(() => + this.transport.client.PATCH('/documents/{id}', { + params: { path: { id } }, + body: { data: { type: 'document', attributes } }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Delete a document. */ + async delete(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.DELETE('/documents/{id}', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** List the document types Terminal49 can classify. */ + async types(options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.GET('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/documents/types'), + ); + return this.formatResult(raw, options?.format); + } + + /** Get a short-lived download URL for a document's file. */ + async downloadUrl(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.GET('/documents/{id}/download_url', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Re-run data extraction on a document. */ + async reextract(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.POST('/documents/{id}/reextract', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Re-run classification on a document. */ + async reclassify(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.POST('/documents/{id}/reclassify', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Re-run shipment/container linking on a document. */ + async relink(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.POST('/documents/{id}/relink', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } + + /** Rotate a document's pages by 90, 180, or 270 degrees. */ + async rotate( + id: string, + degrees: DocumentRotation, + options?: CallOptions, + ): Promise { + const raw = await this.transport.execute(() => + this.transport.client.POST('/documents/{id}/rotate', { + params: { path: { id } }, + body: { degrees }, + }), + ); + return this.formatResult(raw, options?.format); + } +} + +export class EmailSubmissionManager extends BaseManager { + /** List email submissions (documents sent to your Terminal49 inbox). */ + async list(options?: ListOptions & { include?: string }): Promise { + const query: EmailSubmissionListQuery = { include: options?.include }; + applyTypedPagination(query, options); + + const raw = await this.transport.execute(() => + this.transport.client.GET('/email_submissions', { params: { query } }), + ); + return this.formatResult(raw, options?.format); + } + + /** Fetch an email submission by ID. */ + async get( + id: string, + options?: CallOptions & { include?: string }, + ): Promise { + const raw = await this.transport.execute(() => + this.transport.client.GET('/email_submissions/{id}', { + params: { + path: { id }, + query: options?.include ? { include: options.include } : undefined, + }, + }), + ); + return this.formatResult(raw, options?.format); + } +} + +export class DocumentSchemaManager extends BaseManager { + /** Fetch the extraction schema for a document type. */ + async get(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.GET('/document_schemas/{id}', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } +} diff --git a/sdks/typescript-sdk/src/client/managers/entity-subresources.ts b/sdks/typescript-sdk/src/client/managers/entity-subresources.ts new file mode 100644 index 00000000..b55c8cc6 --- /dev/null +++ b/sdks/typescript-sdk/src/client/managers/entity-subresources.ts @@ -0,0 +1,126 @@ +import type { Transport } from '../transport.js'; + +/** Collections that expose `/{collection}/{id}/custom_fields` sub-resources. */ +export type CustomFieldParent = + | 'containers' + | 'shipments' + | 'tracking_requests'; + +/** Collections that expose `/{collection}/{id}/party_roles` sub-resources. */ +export type PartyRoleParent = 'containers' | 'shipments'; + +/** Roles accepted by the `party_roles` endpoints. */ +export type PartyRoleName = + | 'shipper' + | 'consignee' + | 'notify_party' + | 'customs_broker' + | 'customer' + | 'freight_forwarder' + | 'pickup_dray_carrier'; + +const JSON_HEADERS = { 'Content-Type': 'application/json' }; + +function entityUrl( + transport: Transport, + parent: string, + id: string, + ...segments: string[] +): string { + const path = [parent, id, ...segments].map(encodeURIComponent).join('/'); + return `${transport.baseUrl}/${path}`; +} + +export function listCustomFields( + transport: Transport, + parent: CustomFieldParent, + id: string, +): Promise { + return transport.executeManual( + `${entityUrl(transport, parent, id, 'custom_fields')}?include=definition`, + ); +} + +export function createCustomField( + transport: Transport, + parent: CustomFieldParent, + id: string, + apiSlug: string, + value: unknown, +): Promise { + const payload = { + data: { type: 'custom_field', attributes: { api_slug: apiSlug, value } }, + }; + return transport.executeManual( + entityUrl(transport, parent, id, 'custom_fields'), + { method: 'POST', body: JSON.stringify(payload), headers: JSON_HEADERS }, + ); +} + +export function updateCustomField( + transport: Transport, + parent: CustomFieldParent, + id: string, + apiSlug: string, + value: unknown, +): Promise { + const payload = { data: { type: 'custom_field', attributes: { value } } }; + return transport.executeManual( + entityUrl(transport, parent, id, 'custom_fields', apiSlug), + { method: 'PATCH', body: JSON.stringify(payload), headers: JSON_HEADERS }, + ); +} + +export function deleteCustomField( + transport: Transport, + parent: CustomFieldParent, + id: string, + apiSlug: string, +): Promise { + return transport.executeManual( + entityUrl(transport, parent, id, 'custom_fields', apiSlug), + { method: 'DELETE' }, + ); +} + +export function listPartyRoles( + transport: Transport, + parent: PartyRoleParent, + id: string, +): Promise { + return transport.executeManual( + entityUrl(transport, parent, id, 'party_roles'), + ); +} + +export function createPartyRole( + transport: Transport, + parent: PartyRoleParent, + id: string, + role: PartyRoleName, + partyId: string, +): Promise { + const payload = { + data: { + type: 'party_role', + attributes: { role }, + relationships: { party: { data: { type: 'party', id: partyId } } }, + }, + }; + return transport.executeManual( + entityUrl(transport, parent, id, 'party_roles'), + { method: 'POST', body: JSON.stringify(payload), headers: JSON_HEADERS }, + ); +} + +export function deletePartyRole( + transport: Transport, + parent: PartyRoleParent, + id: string, + partyRoleId: string, +): Promise { + return transport.executeManual( + entityUrl(transport, parent, id, 'party_roles', partyRoleId), + { method: 'DELETE' }, + ); +} diff --git a/sdks/typescript-sdk/src/client/managers/index.ts b/sdks/typescript-sdk/src/client/managers/index.ts index 6ee49372..d80a54dc 100644 --- a/sdks/typescript-sdk/src/client/managers/index.ts +++ b/sdks/typescript-sdk/src/client/managers/index.ts @@ -3,3 +3,5 @@ export * from './containers.js'; export * from './shipments.js'; export * from './shipping-lines.js'; export * from './tracking-requests.js'; +export * from './documents.js'; +export type { PartyRoleName } from './entity-subresources.js'; diff --git a/sdks/typescript-sdk/src/client/managers/shipments.ts b/sdks/typescript-sdk/src/client/managers/shipments.ts index d6132855..afca6e28 100644 --- a/sdks/typescript-sdk/src/client/managers/shipments.ts +++ b/sdks/typescript-sdk/src/client/managers/shipments.ts @@ -14,6 +14,16 @@ import { normalizeIncludeWithDefault, } from '../query.js'; import { BaseManager } from './base.js'; +import { + createCustomField, + createPartyRole, + deleteCustomField, + deletePartyRole, + listCustomFields, + listPartyRoles, + type PartyRoleName, + updateCustomField, +} from './entity-subresources.js'; const DEFAULT_SHIPMENT_INCLUDES = [ 'containers', @@ -57,9 +67,7 @@ export class ShipmentManager extends BaseManager { } async customFields(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - `${this.transport.baseUrl}/shipments/${encodeURIComponent(id)}/custom_fields?include=definition`, - ); + const raw = await listCustomFields(this.transport, 'shipments', id); return this.formatResult(raw, options?.format, mapCustomFields); } @@ -145,29 +153,89 @@ export class ShipmentManager extends BaseManager { return this.formatResult(raw, options?.format, mapShipment); } + /** Create a custom field value on a shipment. */ async setCustomField( id: string, - fieldId: string, + apiSlug: string, value: unknown, options?: CallOptions, ): Promise { - const encodedId = encodeURIComponent(id); - const payload = { - data: { - type: 'custom_field', - attributes: { - api_slug: fieldId, - value, - }, - }, - }; - const raw = await this.transport.executeManual( - `${this.transport.baseUrl}/shipments/${encodedId}/custom_fields`, - { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await createCustomField( + this.transport, + 'shipments', + id, + apiSlug, + value, + ); + return this.formatResult(raw, options?.format); + } + + /** Update an existing custom field value on a shipment. */ + async updateCustomField( + id: string, + apiSlug: string, + value: unknown, + options?: CallOptions, + ): Promise { + const raw = await updateCustomField( + this.transport, + 'shipments', + id, + apiSlug, + value, + ); + return this.formatResult(raw, options?.format); + } + + /** Remove a custom field value from a shipment. */ + async deleteCustomField( + id: string, + apiSlug: string, + options?: CallOptions, + ): Promise { + const raw = await deleteCustomField( + this.transport, + 'shipments', + id, + apiSlug, + ); + return this.formatResult(raw, options?.format); + } + + /** List the party roles (shipper, consignee, ...) assigned to a shipment. */ + async partyRoles(id: string, options?: CallOptions): Promise { + const raw = await listPartyRoles(this.transport, 'shipments', id); + return this.formatResult(raw, options?.format); + } + + /** Assign a party to a shipment in the given role. */ + async addPartyRole( + id: string, + role: PartyRoleName, + partyId: string, + options?: CallOptions, + ): Promise { + const raw = await createPartyRole( + this.transport, + 'shipments', + id, + role, + partyId, + ); + return this.formatResult(raw, options?.format); + } + + /** Remove a party role assignment from a shipment. */ + async removePartyRole( + id: string, + partyRoleId: string, + options?: CallOptions, + ): Promise { + const raw = await deletePartyRole( + this.transport, + 'shipments', + id, + partyRoleId, ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client/managers/shipping-lines.ts b/sdks/typescript-sdk/src/client/managers/shipping-lines.ts index b5a5d0b8..b85bcbd5 100644 --- a/sdks/typescript-sdk/src/client/managers/shipping-lines.ts +++ b/sdks/typescript-sdk/src/client/managers/shipping-lines.ts @@ -12,4 +12,14 @@ export class ShippingLineManager extends BaseManager { ); return this.formatResult(raw, options?.format, mapShippingLines); } + + /** Fetch a shipping line by ID. */ + async get(id: string, options?: CallOptions): Promise { + const raw = await this.transport.execute(() => + this.transport.client.GET('/shipping_lines/{id}', { + params: { path: { id } }, + }), + ); + return this.formatResult(raw, options?.format); + } } diff --git a/sdks/typescript-sdk/src/client/managers/tracking-requests.ts b/sdks/typescript-sdk/src/client/managers/tracking-requests.ts index 7923d281..8ec200c8 100644 --- a/sdks/typescript-sdk/src/client/managers/tracking-requests.ts +++ b/sdks/typescript-sdk/src/client/managers/tracking-requests.ts @@ -6,9 +6,19 @@ import type { TrackingRequestInclude, } from '../../types/options.js'; import { ValidationError } from '../errors.js'; -import { mapTrackingRequest, mapTrackingRequestList } from '../mappers.js'; +import { + mapCustomFields, + mapTrackingRequest, + mapTrackingRequestList, +} from '../mappers.js'; import { copyStringParams, normalizeInclude } from '../query.js'; import { BaseManager } from './base.js'; +import { + createCustomField, + deleteCustomField, + listCustomFields, + updateCustomField, +} from './entity-subresources.js'; export type TrackingRequestType = | 'container' @@ -101,6 +111,61 @@ export class TrackingRequestManager extends BaseManager { return this.formatResult(raw, options?.format, mapTrackingRequest); } + /** List custom field values set on a tracking request, with their definitions. */ + async customFields(id: string, options?: CallOptions): Promise { + const raw = await listCustomFields(this.transport, 'tracking_requests', id); + return this.formatResult(raw, options?.format, mapCustomFields); + } + + /** Create a custom field value on a tracking request. */ + async setCustomField( + id: string, + apiSlug: string, + value: unknown, + options?: CallOptions, + ): Promise { + const raw = await createCustomField( + this.transport, + 'tracking_requests', + id, + apiSlug, + value, + ); + return this.formatResult(raw, options?.format); + } + + /** Update an existing custom field value on a tracking request. */ + async updateCustomField( + id: string, + apiSlug: string, + value: unknown, + options?: CallOptions, + ): Promise { + const raw = await updateCustomField( + this.transport, + 'tracking_requests', + id, + apiSlug, + value, + ); + return this.formatResult(raw, options?.format); + } + + /** Remove a custom field value from a tracking request. */ + async deleteCustomField( + id: string, + apiSlug: string, + options?: CallOptions, + ): Promise { + const raw = await deleteCustomField( + this.transport, + 'tracking_requests', + id, + apiSlug, + ); + return this.formatResult(raw, options?.format); + } + async create(params: { requestType: TrackingRequestType; requestNumber: string; diff --git a/sdks/typescript-sdk/src/client/transport.ts b/sdks/typescript-sdk/src/client/transport.ts index 6be66318..a9d20e85 100644 --- a/sdks/typescript-sdk/src/client/transport.ts +++ b/sdks/typescript-sdk/src/client/transport.ts @@ -81,9 +81,9 @@ export class Transport { } /** - * Run a request that has no entry in the generated OpenAPI types (currently - * only `search()`) through the same Auth -> Retry -> ErrorMapping pipeline the - * typed client uses, including the timeout-wrapped fetch. Successful bodies are + * Run a hand-built request (shared entity sub-resources, or routes absent from + * the generated OpenAPI types) through the same Auth -> Retry -> ErrorMapping + * pipeline the typed client uses, including the timeout-wrapped fetch. Successful bodies are * read with {@link readSuccessBody} so a non-JSON success body is surfaced * rather than silently collapsed to `undefined`. */ From 64c6371a1cc0a67f6637bd322e3b9d83ad795b04 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 10:40:12 -0700 Subject: [PATCH 03/14] test(sdk): pin request shapes for client resource methods Co-Authored-By: Claude Opus 5.5 --- .../src/client.write-endpoints.test.ts | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/sdks/typescript-sdk/src/client.write-endpoints.test.ts b/sdks/typescript-sdk/src/client.write-endpoints.test.ts index 74ce0a5d..96210332 100644 --- a/sdks/typescript-sdk/src/client.write-endpoints.test.ts +++ b/sdks/typescript-sdk/src/client.write-endpoints.test.ts @@ -309,3 +309,100 @@ describe('search', () => { }); }); }); + +describe('resource methods on the client', () => { + it('sends the documented method, path, query, and body', async () => { + const { client, calls } = buildClient(); + const body = { data: { attributes: { name: 'n' } } }; + + await client.webhooks.list({ page: 2, pageSize: 5 }); + await client.webhooks.get('w 1'); + await client.webhooks.create(body); + await client.webhooks.update('w-1', body); + await client.webhooks.delete('w-1'); + await client.webhooks.ips(); + await client.webhookNotifications.list({ page: 3 }); + await client.webhookNotifications.get('n-1'); + await client.webhookNotifications.examples('container.created'); + await client.webhookNotifications.examples(); + await client.vessels.get('v-1'); + await client.vessels.getByImo('9876543'); + await client.vessels.futurePositions('v-1'); + await client.vessels.futurePositionsWithCoords('v-1'); + await client.ports.get('p-1'); + await client.terminals.get('t-1'); + await client.parties.list({ pageSize: 10 }); + await client.parties.get('pa-1'); + await client.metroAreas.get('m-1'); + await client.customFieldDefinitions.get('d-1'); + await client.customFieldDefinitions.create(body); + await client.customFieldDefinitions.update('d-1', body); + await client.customFieldDefinitions.delete('d-1'); + await client.customFieldOptions.list('d-1', { page: 1, pageSize: 20 }); + await client.customFieldOptions.get('d-1', 'o-1'); + await client.customFieldOptions.create('d-1', body); + await client.customFieldOptions.update('d-1', 'o-1', body); + await client.customFieldOptions.delete('d-1', 'o-1'); + await client.customFields.get('cf-1'); + await client.customFields.create(body); + await client.customFields.update('cf-1', body); + await client.customFields.delete('cf-1'); + + expect(calls.map((c) => [c.method, c.path, c.query, c.body])).toEqual([ + [ + 'GET', + '/webhooks', + { 'page[number]': '2', 'page[size]': '5' }, + undefined, + ], + ['GET', '/webhooks/w%201', {}, undefined], + ['POST', '/webhooks', {}, body], + ['PATCH', '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/webhooks/w-1', {}, body], + ['DELETE', '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/webhooks/w-1', {}, undefined], + ['GET', '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/webhooks/ips', {}, undefined], + ['GET', '/webhook_notifications', { 'page[number]': '3' }, undefined], + ['GET', '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/webhook_notifications/n-1', {}, undefined], + [ + 'GET', + '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/webhook_notifications/examples', + { event: 'container.created' }, + undefined, + ], + ['GET', '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/webhook_notifications/examples', {}, undefined], + ['GET', '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/vessels/v-1', {}, undefined], + ['GET', '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/vessels/9876543', {}, undefined], + ['GET', '/vessels/v-1/future_positions', {}, undefined], + ['GET', '/vessels/v-1/future_positions_with_coordinates', {}, undefined], + ['GET', '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/ports/p-1', {}, undefined], + ['GET', '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/terminals/t-1', {}, undefined], + ['GET', '/parties', { 'page[size]': '10' }, undefined], + ['GET', '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/parties/pa-1', {}, undefined], + ['GET', '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/metro_areas/m-1', {}, undefined], + ['GET', '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/custom_field_definitions/d-1', {}, undefined], + ['POST', '/custom_field_definitions', {}, body], + ['PATCH', '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/custom_field_definitions/d-1', {}, body], + ['DELETE', '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/custom_field_definitions/d-1', {}, undefined], + [ + 'GET', + '/custom_field_definitions/d-1/options', + { 'page[number]': '1', 'page[size]': '20' }, + undefined, + ], + ['GET', '/custom_field_definitions/d-1/options/o-1', {}, undefined], + ['POST', '/custom_field_definitions/d-1/options', {}, body], + ['PATCH', '/custom_field_definitions/d-1/options/o-1', {}, body], + ['DELETE', '/custom_field_definitions/d-1/options/o-1', {}, undefined], + ['GET', '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/custom_fields/cf-1', {}, undefined], + ['POST', '/custom_fields', {}, body], + ['PATCH', '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/custom_fields/cf-1', {}, body], + ['DELETE', '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/custom_fields/cf-1', {}, undefined], + ]); + }); + + it('returns the response body the API served', async () => { + const { client } = buildClient(); + await expect(client.webhooks.get('w-1')).resolves.toEqual({ + data: { id: 'x', type: 'stub' }, + }); + }); +}); From 432253a7a51afc54af7a932c1a1c5274cb570e4a Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 10:44:09 -0700 Subject: [PATCH 04/14] refactor(sdk): route client resource methods through the typed client Webhooks, webhook notifications, vessels, ports, terminals, parties, metro areas, and custom field resources now call transport.client with literal spec paths, so the compiler checks path params, query keys, and bodies. Pagination goes through applyTypedPagination, which clamps page[size]. endpoint() and listQuery() are gone. Caller-owned payloads on pre-existing methods meet the spec type through one callerPayload() cast. New methods take spec-derived types: parties create/update take the request body, and the trigger and list filter params derive from the spec. Three routes stay on executeManual because the spec does not match what the pre-existing signatures send: vessel future positions (spec requires query params the methods never took) and custom field options list (spec omits the page params the CLI forwards). Co-Authored-By: Claude Opus 5.5 --- sdks/typescript-sdk/src/client.ts | 403 ++++++++++-------- .../src/client.write-endpoints.test.ts | 6 + sdks/typescript-sdk/src/client/spec.ts | 10 + 3 files changed, 235 insertions(+), 184 deletions(-) create mode 100644 sdks/typescript-sdk/src/client/spec.ts diff --git a/sdks/typescript-sdk/src/client.ts b/sdks/typescript-sdk/src/client.ts index eb2adef5..fcae6994 100644 --- a/sdks/typescript-sdk/src/client.ts +++ b/sdks/typescript-sdk/src/client.ts @@ -29,6 +29,8 @@ import type { TrackingRequestListFilters, TrackingRequestType, } from './client/managers/tracking-requests.js'; +import { applyTypedPagination } from './client/query.js'; +import { callerPayload, type JsonBody } from './client/spec.js'; import { Transport } from './client/transport.js'; import type { paths } from './generated/terminal49.js'; import type { @@ -60,32 +62,45 @@ export { ValidationError, }; -type TriggerWebhookBody = - paths['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/webhooks/trigger']['post']['requestBody']['content']['application/json']; +type WebhookEvent = NonNullable< + paths['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/webhook_notifications/examples']['get']['parameters']['query'] +>['event']; +type CustomFieldDefinitionListQuery = NonNullable< + paths['/custom_field_definitions']['get']['parameters']['query'] +>; +type CustomFieldListQuery = NonNullable< + paths['/custom_fields']['get']['parameters']['query'] +>; +type TriggerWebhookBody = JsonBody; +type CreatePartyBody = JsonBody; +type UpdatePartyBody = JsonBody; +type CustomFieldDefinitionAttributes = NonNullable< + JsonBody['data'] +>['attributes']; /** Parameters for {@link Terminal49Client.triggerWebhook}. */ export interface TriggerWebhookParams { /** HTTPS destination URL for the test delivery. */ - url: string; + url: TriggerWebhookBody['url']; /** Webhook event name used to generate the example payload, e.g. `tracking_request.succeeded`. */ - event: string; + event: TriggerWebhookBody['event']; /** Optional secret used to sign the request in `X-T49-Webhook-Signature`. */ - secret?: string; + secret?: TriggerWebhookBody['secret']; /** Document type for `document_representation.*` example payloads. */ - documentType?: string; + documentType?: NonNullable['document_type']; } /** Filters accepted by `customFields.list`. */ export interface CustomFieldListFilters { - entityType?: 'Shipment' | 'Container'; + entityType?: CustomFieldDefinitionAttributes['entity_type']; entityId?: string; definitionId?: string; } /** Filters accepted by `customFieldDefinitions.list`. */ export interface CustomFieldDefinitionListFilters { - entityType?: 'Shipment' | 'Container'; - dataType?: string; + entityType?: CustomFieldDefinitionAttributes['entity_type']; + dataType?: CustomFieldDefinitionAttributes['data_type']; displayName?: string; } @@ -193,13 +208,10 @@ export class Terminal49Client { public parties = { list: (options?: ListOptions) => this.listParties(options), get: (id: string, options?: CallOptions) => this.getParty(id, options), - create: (payload: Record, options?: CallOptions) => + create: (payload: CreatePartyBody, options?: CallOptions) => this.createParty(payload, options), - update: ( - id: string, - payload: Record, - options?: CallOptions, - ) => this.updateParty(id, payload, options), + update: (id: string, payload: UpdatePartyBody, options?: CallOptions) => + this.updateParty(id, payload, options), }; public metroAreas = { @@ -508,16 +520,20 @@ export class Terminal49Client { /** List webhooks. */ async listWebhooks(options?: ListOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint('/webhooks', this.listQuery(options)), + const raw = await this.transport.execute(() => + this.transport.client.GET('/webhooks', { + params: { query: applyTypedPagination({}, options) }, + }), ); return this.formatResult(raw, options?.format); } /** Fetch a webhook by ID. */ async getWebhook(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/webhooks/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/webhooks/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -527,11 +543,11 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual(this.endpoint('/webhooks'), { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }); + const raw = await this.transport.execute(() => + this.transport.client.POST('/webhooks', { + body: callerPayload>(payload), + }), + ); return this.formatResult(raw, options?.format); } @@ -541,38 +557,39 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/webhooks/${encodeURIComponent(id)}`), - { - method: 'PATCH', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.PATCH('/webhooks/{id}', { + params: { path: { id } }, + body: callerPayload>( + payload, + ), + }), ); return this.formatResult(raw, options?.format); } /** Delete a webhook. */ async deleteWebhook(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/webhooks/${encodeURIComponent(id)}`), - { method: 'DELETE' }, + const raw = await this.transport.execute(() => + this.transport.client.DELETE('/webhooks/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } /** List webhook source IP ranges. */ async getWebhookIps(options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint('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/webhooks/ips'), + const raw = await this.transport.execute(() => + this.transport.client.GET('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/webhooks/ips'), ); return this.formatResult(raw, options?.format); } /** List the event names a webhook can subscribe to. */ async listWebhookEvents(options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint('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/webhooks/events'), + const raw = await this.transport.execute(() => + this.transport.client.GET('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/webhooks/events'), ); return this.formatResult(raw, options?.format); } @@ -582,29 +599,27 @@ export class Terminal49Client { params: TriggerWebhookParams, options?: CallOptions, ): Promise { - const body: TriggerWebhookBody = { - url: params.url, - event: params.event, - secret: params.secret, - sample: params.documentType - ? { document_type: params.documentType } - : undefined, - }; - const raw = await this.transport.executeManual( - this.endpoint('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/webhooks/trigger'), - { - method: 'POST', - body: JSON.stringify(body), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.POST('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/webhooks/trigger', { + body: { + url: params.url, + event: params.event, + secret: params.secret, + sample: params.documentType + ? { document_type: params.documentType } + : undefined, + }, + }), ); return this.formatResult(raw, options?.format); } /** List webhook notifications. */ async listWebhookNotifications(options?: ListOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint('/webhook_notifications', this.listQuery(options)), + const raw = await this.transport.execute(() => + this.transport.client.GET('/webhook_notifications', { + params: { query: applyTypedPagination({}, options) }, + }), ); return this.formatResult(raw, options?.format); } @@ -614,8 +629,10 @@ export class Terminal49Client { id: string, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/webhook_notifications/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/webhook_notifications/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -625,24 +642,30 @@ export class Terminal49Client { event?: string, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint('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/webhook_notifications/examples', { event }), + const raw = await this.transport.execute(() => + this.transport.client.GET('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/webhook_notifications/examples', { + params: { query: { event: callerPayload(event) } }, + }), ); return this.formatResult(raw, options?.format); } /** Fetch a vessel by ID. */ async getVessel(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/vessels/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/vessels/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } /** Fetch a vessel by IMO number. */ async getVesselByImo(imo: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/vessels/${encodeURIComponent(imo)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/vessels/{imo}', { + params: { path: { imo } }, + }), ); return this.formatResult(raw, options?.format); } @@ -652,8 +675,9 @@ export class Terminal49Client { id: string, options?: CallOptions, ): Promise { + // The spec marks port_id and previous_port_id required; this signature never accepted them. const raw = await this.transport.executeManual( - this.endpoint(`/vessels/${encodeURIComponent(id)}/future_positions`), + `${this.transport.baseUrl}/vessels/${encodeURIComponent(id)}/future_positions`, ); return this.formatResult(raw, options?.format); } @@ -663,80 +687,81 @@ export class Terminal49Client { id: string, options?: CallOptions, ): Promise { + // The spec marks port and coordinate params required; this signature never accepted them. const raw = await this.transport.executeManual( - this.endpoint( - `/vessels/${encodeURIComponent(id)}/future_positions_with_coordinates`, - ), + `${this.transport.baseUrl}/vessels/${encodeURIComponent(id)}/future_positions_with_coordinates`, ); return this.formatResult(raw, options?.format); } /** Fetch a port by ID. */ async getPort(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/ports/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/ports/{id}', { params: { path: { id } } }), ); return this.formatResult(raw, options?.format); } /** Fetch a terminal by ID. */ async getTerminal(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/terminals/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/terminals/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } /** List parties. */ async listParties(options?: ListOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint('/parties', this.listQuery(options)), + const raw = await this.transport.execute(() => + this.transport.client.GET('/parties', { + params: { query: applyTypedPagination({}, options) }, + }), ); return this.formatResult(raw, options?.format); } /** Fetch a party by ID. */ async getParty(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/parties/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/parties/{id}', { params: { path: { id } } }), ); return this.formatResult(raw, options?.format); } /** Create a party. */ async createParty( - payload: Record, + payload: CreatePartyBody, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual(this.endpoint('/parties'), { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }); + const raw = await this.transport.execute(() => + this.transport.client.POST('/parties', { body: payload }), + ); return this.formatResult(raw, options?.format); } /** Update a party. */ async updateParty( id: string, - payload: Record, + payload: UpdatePartyBody, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/parties/${encodeURIComponent(id)}`), - { - method: 'PATCH', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.PATCH('/parties/{id}', { + params: { path: { id } }, + body: payload, + }), ); return this.formatResult(raw, options?.format); } /** Fetch a metro area by ID. */ async getMetroArea(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/metro_areas/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/metro_areas/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -746,12 +771,17 @@ export class Terminal49Client { options?: ListOptions & { filters?: CustomFieldDefinitionListFilters }, ): Promise { const filters = options?.filters; - const raw = await this.transport.executeManual( - this.endpoint('/custom_field_definitions', { - ...this.listQuery(options), + const query = applyTypedPagination( + { 'filter[entity_type]': filters?.entityType, 'filter[data_type]': filters?.dataType, 'filter[display_name]': filters?.displayName, + }, + options, + ); + const raw = await this.transport.execute(() => + this.transport.client.GET('/custom_field_definitions', { + params: { query }, }), ); return this.formatResult(raw, options?.format); @@ -762,8 +792,10 @@ export class Terminal49Client { id: string, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/custom_field_definitions/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/custom_field_definitions/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -773,13 +805,12 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint('/custom_field_definitions'), - { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.POST('/custom_field_definitions', { + body: callerPayload< + JsonBody + >(payload), + }), ); return this.formatResult(raw, options?.format); } @@ -790,13 +821,13 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/custom_field_definitions/${encodeURIComponent(id)}`), - { - method: 'PATCH', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.PATCH('/custom_field_definitions/{id}', { + params: { path: { id } }, + body: callerPayload< + JsonBody + >(payload), + }), ); return this.formatResult(raw, options?.format); } @@ -806,9 +837,10 @@ export class Terminal49Client { id: string, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/custom_field_definitions/${encodeURIComponent(id)}`), - { method: 'DELETE' }, + const raw = await this.transport.execute(() => + this.transport.client.DELETE('/custom_field_definitions/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -818,12 +850,16 @@ export class Terminal49Client { definitionId: string, options?: ListOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint( - `/custom_field_definitions/${encodeURIComponent(definitionId)}/options`, - this.listQuery(options), + // The spec omits page[*] on this route, but the response is paginated and the CLI forwards --page. + const query = new URLSearchParams( + Object.entries(applyTypedPagination({}, options)).map( + ([key, value]): [string, string] => [key, String(value)], ), ); + const suffix = query.size > 0 ? `?${query}` : ''; + const raw = await this.transport.executeManual( + `${this.transport.baseUrl}/custom_field_definitions/${encodeURIComponent(definitionId)}/options${suffix}`, + ); return this.formatResult(raw, options?.format); } @@ -833,9 +869,14 @@ export class Terminal49Client { optionId: string, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint( - `/custom_field_definitions/${encodeURIComponent(definitionId)}/options/${encodeURIComponent(optionId)}`, + const raw = await this.transport.execute(() => + this.transport.client.GET( + '/custom_field_definitions/{definition_id}/options/{option_id}', + { + params: { + path: { definition_id: definitionId, option_id: optionId }, + }, + }, ), ); return this.formatResult(raw, options?.format); @@ -847,15 +888,18 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint( - `/custom_field_definitions/${encodeURIComponent(definitionId)}/options`, + const raw = await this.transport.execute(() => + this.transport.client.POST( + '/custom_field_definitions/{definition_id}/options', + { + params: { path: { definition_id: definitionId } }, + body: callerPayload< + JsonBody< + paths['/custom_field_definitions/{definition_id}/options']['post'] + > + >(payload), + }, ), - { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, ); return this.formatResult(raw, options?.format); } @@ -867,15 +911,20 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint( - `/custom_field_definitions/${encodeURIComponent(definitionId)}/options/${encodeURIComponent(optionId)}`, + const raw = await this.transport.execute(() => + this.transport.client.PATCH( + '/custom_field_definitions/{definition_id}/options/{option_id}', + { + params: { + path: { definition_id: definitionId, option_id: optionId }, + }, + body: callerPayload< + JsonBody< + paths['/custom_field_definitions/{definition_id}/options/{option_id}']['patch'] + > + >(payload), + }, ), - { - method: 'PATCH', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, ); return this.formatResult(raw, options?.format); } @@ -886,11 +935,15 @@ export class Terminal49Client { optionId: string, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint( - `/custom_field_definitions/${encodeURIComponent(definitionId)}/options/${encodeURIComponent(optionId)}`, + const raw = await this.transport.execute(() => + this.transport.client.DELETE( + '/custom_field_definitions/{definition_id}/options/{option_id}', + { + params: { + path: { definition_id: definitionId, option_id: optionId }, + }, + }, ), - { method: 'DELETE' }, ); return this.formatResult(raw, options?.format); } @@ -900,21 +953,26 @@ export class Terminal49Client { options?: ListOptions & { filters?: CustomFieldListFilters }, ): Promise { const filters = options?.filters; - const raw = await this.transport.executeManual( - this.endpoint('/custom_fields', { - ...this.listQuery(options), + const query = applyTypedPagination( + { 'filter[entity_type]': filters?.entityType, 'filter[entity_id]': filters?.entityId, 'filter[definition_id]': filters?.definitionId, - }), + }, + options, + ); + const raw = await this.transport.execute(() => + this.transport.client.GET('/custom_fields', { params: { query } }), ); return this.formatResult(raw, options?.format); } /** Fetch a custom field assignment by ID. */ async getCustomField(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/custom_fields/${encodeURIComponent(id)}`), + const raw = await this.transport.execute(() => + this.transport.client.GET('/custom_fields/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -924,13 +982,10 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint('/custom_fields'), - { - method: 'POST', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.POST('/custom_fields', { + body: callerPayload>(payload), + }), ); return this.formatResult(raw, options?.format); } @@ -941,22 +996,23 @@ export class Terminal49Client { payload: Record, options?: CallOptions, ): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/custom_fields/${encodeURIComponent(id)}`), - { - method: 'PATCH', - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }, + const raw = await this.transport.execute(() => + this.transport.client.PATCH('/custom_fields/{id}', { + params: { path: { id } }, + body: callerPayload>( + payload, + ), + }), ); return this.formatResult(raw, options?.format); } /** Delete a custom field assignment. */ async deleteCustomField(id: string, options?: CallOptions): Promise { - const raw = await this.transport.executeManual( - this.endpoint(`/custom_fields/${encodeURIComponent(id)}`), - { method: 'DELETE' }, + const raw = await this.transport.execute(() => + this.transport.client.DELETE('/custom_fields/{id}', { + params: { path: { id } }, + }), ); return this.formatResult(raw, options?.format); } @@ -994,27 +1050,6 @@ export class Terminal49Client { return this.trackingRequests.update(id, attrs, options); } - private endpoint( - path: string, - query?: Record, - ): string { - const params = new URLSearchParams(); - for (const [key, value] of Object.entries(query ?? {})) { - if (value !== undefined) params.set(key, String(value)); - } - const suffix = params.toString(); - return `${this.transport.baseUrl}${path}${suffix ? `?${suffix}` : ''}`; - } - - private listQuery( - options?: ListOptions, - ): Record { - return { - 'page[number]': options?.page, - 'page[size]': options?.pageSize, - }; - } - private formatResult( raw: TDoc, format: ResponseFormat | undefined, diff --git a/sdks/typescript-sdk/src/client.write-endpoints.test.ts b/sdks/typescript-sdk/src/client.write-endpoints.test.ts index 96210332..b0eeefa7 100644 --- a/sdks/typescript-sdk/src/client.write-endpoints.test.ts +++ b/sdks/typescript-sdk/src/client.write-endpoints.test.ts @@ -399,6 +399,12 @@ describe('resource methods on the client', () => { ]); }); + it('clamps page[size] to the API maximum', async () => { + const { client, calls } = buildClient(); + await client.parties.list({ pageSize: 500 }); + expect(calls[0].query).toEqual({ 'page[size]': '100' }); + }); + it('returns the response body the API served', async () => { const { client } = buildClient(); await expect(client.webhooks.get('w-1')).resolves.toEqual({ diff --git a/sdks/typescript-sdk/src/client/spec.ts b/sdks/typescript-sdk/src/client/spec.ts new file mode 100644 index 00000000..4f79bf3e --- /dev/null +++ b/sdks/typescript-sdk/src/client/spec.ts @@ -0,0 +1,10 @@ +export type JsonBody = TOperation extends { + requestBody?: { content: { 'application/json': infer TBody } }; +} + ? TBody + : never; + +export function callerPayload(value: unknown): TSpec { + // SAFETY: the value is forwarded as-is and validated server-side; the SDK never reads it. + return value as TSpec; +} From 19fbf927bdf663ad9d975a227a5413701e894fc8 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 14:02:47 -0700 Subject: [PATCH 05/14] refactor(sdk): type entity custom field and party role routes per manager Containers, shipments, and tracking requests call their own literal spec paths (container_id, shipment_id, tracking_request_id) instead of the shared string-URL helpers, and entity-subresources.ts is deleted. Methods added in the previous commit are now strict. updateCustomField and the tracking request setCustomField take the spec custom_field_value type. addPartyRole takes { role, partyId } with role derived per route, so containers accept only pickup_dray_carrier as the spec documents. The hand-written PartyRoleName export is dropped. containers.update takes the spec attributes and loses its as-any cast. The custom_fields list GETs stay on executeManual: include=definition is absent from the spec. Co-Authored-By: Claude Opus 5.5 --- .../client/transport/classes/Transport.mdx | 6 +- .../src/client.write-endpoints.test.ts | 29 +++- .../src/client/managers/containers.ts | 122 ++++++++++------- .../client/managers/entity-subresources.ts | 126 ------------------ .../src/client/managers/index.ts | 1 - .../src/client/managers/shipments.ts | 115 ++++++++++------ .../src/client/managers/tracking-requests.ts | 63 +++++---- sdks/typescript-sdk/src/client/transport.ts | 6 +- 8 files changed, 214 insertions(+), 254 deletions(-) delete mode 100644 sdks/typescript-sdk/src/client/managers/entity-subresources.ts diff --git a/docs/sdk/reference/client/transport/classes/Transport.mdx b/docs/sdk/reference/client/transport/classes/Transport.mdx index ca7090a4..3cbcb6db 100644 --- a/docs/sdk/reference/client/transport/classes/Transport.mdx +++ b/docs/sdk/reference/client/transport/classes/Transport.mdx @@ -56,9 +56,9 @@ description: "Transport class in the Terminal49 TypeScript SDK, the low-level HT > **executeManual**\<`T`\>(`input`, `init?`): `Promise`\<`T`\> -Run a request that has no entry in the generated OpenAPI types (currently -only `search()`) through the same Auth -> Retry -> ErrorMapping pipeline the -typed client uses, including the timeout-wrapped fetch. Successful bodies are +Run a hand-built request (routes or query params the OpenAPI spec does not +describe) through the same Auth -> Retry -> ErrorMapping pipeline the typed +client uses, including the timeout-wrapped fetch. Successful bodies are read with readSuccessBody so a non-JSON success body is surfaced rather than silently collapsed to `undefined`. diff --git a/sdks/typescript-sdk/src/client.write-endpoints.test.ts b/sdks/typescript-sdk/src/client.write-endpoints.test.ts index b0eeefa7..4cb62ed2 100644 --- a/sdks/typescript-sdk/src/client.write-endpoints.test.ts +++ b/sdks/typescript-sdk/src/client.write-endpoints.test.ts @@ -70,14 +70,33 @@ describe('entity custom fields', () => { }); describe('party roles', () => { - it.each(['containers', 'shipments'] as const)( - '%s exposes list/add/remove', - async (collection) => { + it.each([ + { + collection: 'containers', + role: 'pickup_dray_carrier', + addRole: (client: Terminal49Client) => + client.containers.addPartyRole('id-1', { + role: 'pickup_dray_carrier', + partyId: 'party-9', + }), + }, + { + collection: 'shipments', + role: 'consignee', + addRole: (client: Terminal49Client) => + client.shipments.addPartyRole('id-1', { + role: 'consignee', + partyId: 'party-9', + }), + }, + ] as const)( + '$collection exposes list/add/remove', + async ({ collection, role, addRole }) => { const { client, calls } = buildClient(); const m = client[collection]; await m.partyRoles('id-1'); - await m.addPartyRole('id-1', 'consignee', 'party-9'); + await addRole(client); await m.removePartyRole('id-1', 'role-3'); expect(calls.map((c) => [c.method, c.path])).toEqual([ @@ -88,7 +107,7 @@ describe('party roles', () => { expect(calls[1].body).toEqual({ data: { type: 'party_role', - attributes: { role: 'consignee' }, + attributes: { role }, relationships: { party: { data: { type: 'party', id: 'party-9' } } }, }, }); diff --git a/sdks/typescript-sdk/src/client/managers/containers.ts b/sdks/typescript-sdk/src/client/managers/containers.ts index f39f653e..18b364e7 100644 --- a/sdks/typescript-sdk/src/client/managers/containers.ts +++ b/sdks/typescript-sdk/src/client/managers/containers.ts @@ -1,5 +1,6 @@ import type { ContainerListFilters } from '../../generated/list-filters.js'; import { serializeListQuery } from '../filter-validation.js'; +import type { components, paths } from '../../generated/terminal49.js'; import type { Container } from '../../types/models.js'; import type { CallOptions, @@ -19,17 +20,22 @@ import { MAX_CONTAINER_PAGE_SIZE, normalizeInclude, } from '../query.js'; +import { callerPayload, type JsonBody } from '../spec.js'; import { BaseManager } from './base.js'; -import { - createCustomField, - createPartyRole, - deleteCustomField, - deletePartyRole, - listCustomFields, - listPartyRoles, - type PartyRoleName, - updateCustomField, -} from './entity-subresources.js'; + +type ContainerUpdateAttributes = NonNullable< + JsonBody['data'] +>['attributes']; +type CustomFieldValue = components['schemas']['custom_field_value']; +type PartyRoleData = JsonBody< + paths['/containers/{container_id}/party_roles']['post'] +>['data']; + +/** Parameters for `addPartyRole`; `role` is limited to what the spec accepts on this route. */ +interface AddPartyRoleParams { + role: PartyRoleData['attributes']['role']; + partyId: PartyRoleData['relationships']['party']['data']['id']; +} const DEFAULT_CONTAINER_INCLUDES = [ 'shipment', @@ -62,7 +68,7 @@ export class ContainerManager extends BaseManager { /** Update container attributes such as `ref_numbers`. */ async update( id: string, - attrs: Record, + attrs: ContainerUpdateAttributes, options?: CallOptions, ): Promise { const payload = { @@ -71,14 +77,17 @@ export class ContainerManager extends BaseManager { const raw = await this.transport.execute(() => this.transport.client.PATCH('/containers/{id}', { params: { path: { id } }, - body: payload as any, + body: payload, }), ); return this.formatResult(raw, options?.format); } async customFields(id: string, options?: CallOptions): Promise { - const raw = await listCustomFields(this.transport, 'containers', id); + // The spec omits include=definition, but mapCustomFields reads the included definitions. + const raw = await this.transport.executeManual( + `${this.transport.baseUrl}/containers/${encodeURIComponent(id)}/custom_fields?include=definition`, + ); return this.formatResult(raw, options?.format, mapCustomFields); } @@ -163,12 +172,19 @@ export class ContainerManager extends BaseManager { value: unknown, options?: CallOptions, ): Promise { - const raw = await createCustomField( - this.transport, - 'containers', - id, - apiSlug, - value, + const raw = await this.transport.execute(() => + this.transport.client.POST('/containers/{container_id}/custom_fields', { + params: { path: { container_id: id } }, + body: { + data: { + type: 'custom_field', + attributes: { + api_slug: apiSlug, + value: callerPayload(value), + }, + }, + }, + }), ); return this.formatResult(raw, options?.format); } @@ -177,15 +193,17 @@ export class ContainerManager extends BaseManager { async updateCustomField( id: string, apiSlug: string, - value: unknown, + value: CustomFieldValue, options?: CallOptions, ): Promise { - const raw = await updateCustomField( - this.transport, - 'containers', - id, - apiSlug, - value, + const raw = await this.transport.execute(() => + this.transport.client.PATCH( + '/containers/{container_id}/custom_fields/{api_slug}', + { + params: { path: { container_id: id, api_slug: apiSlug } }, + body: { data: { type: 'custom_field', attributes: { value } } }, + }, + ), ); return this.formatResult(raw, options?.format); } @@ -196,34 +214,44 @@ export class ContainerManager extends BaseManager { apiSlug: string, options?: CallOptions, ): Promise { - const raw = await deleteCustomField( - this.transport, - 'containers', - id, - apiSlug, + const raw = await this.transport.execute(() => + this.transport.client.DELETE( + '/containers/{container_id}/custom_fields/{api_slug}', + { + params: { path: { container_id: id, api_slug: apiSlug } }, + }, + ), ); return this.formatResult(raw, options?.format); } - /** List the party roles (shipper, consignee, ...) assigned to a container. */ + /** List the party roles assigned to a container. */ async partyRoles(id: string, options?: CallOptions): Promise { - const raw = await listPartyRoles(this.transport, 'containers', id); + const raw = await this.transport.execute(() => + this.transport.client.GET('/containers/{container_id}/party_roles', { + params: { path: { container_id: id } }, + }), + ); return this.formatResult(raw, options?.format); } /** Assign a party to a container in the given role. */ async addPartyRole( id: string, - role: PartyRoleName, - partyId: string, + { role, partyId }: AddPartyRoleParams, options?: CallOptions, ): Promise { - const raw = await createPartyRole( - this.transport, - 'containers', - id, - role, - partyId, + const raw = await this.transport.execute(() => + this.transport.client.POST('/containers/{container_id}/party_roles', { + params: { path: { container_id: id } }, + body: { + data: { + type: 'party_role', + attributes: { role }, + relationships: { party: { data: { type: 'party', id: partyId } } }, + }, + }, + }), ); return this.formatResult(raw, options?.format); } @@ -234,11 +262,13 @@ export class ContainerManager extends BaseManager { partyRoleId: string, options?: CallOptions, ): Promise { - const raw = await deletePartyRole( - this.transport, - 'containers', - id, - partyRoleId, + const raw = await this.transport.execute(() => + this.transport.client.DELETE( + '/containers/{container_id}/party_roles/{id}', + { + params: { path: { container_id: id, id: partyRoleId } }, + }, + ), ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client/managers/entity-subresources.ts b/sdks/typescript-sdk/src/client/managers/entity-subresources.ts deleted file mode 100644 index b55c8cc6..00000000 --- a/sdks/typescript-sdk/src/client/managers/entity-subresources.ts +++ /dev/null @@ -1,126 +0,0 @@ -import type { Transport } from '../transport.js'; - -/** Collections that expose `/{collection}/{id}/custom_fields` sub-resources. */ -export type CustomFieldParent = - | 'containers' - | 'shipments' - | 'tracking_requests'; - -/** Collections that expose `/{collection}/{id}/party_roles` sub-resources. */ -export type PartyRoleParent = 'containers' | 'shipments'; - -/** Roles accepted by the `party_roles` endpoints. */ -export type PartyRoleName = - | 'shipper' - | 'consignee' - | 'notify_party' - | 'customs_broker' - | 'customer' - | 'freight_forwarder' - | 'pickup_dray_carrier'; - -const JSON_HEADERS = { 'Content-Type': 'application/json' }; - -function entityUrl( - transport: Transport, - parent: string, - id: string, - ...segments: string[] -): string { - const path = [parent, id, ...segments].map(encodeURIComponent).join('/'); - return `${transport.baseUrl}/${path}`; -} - -export function listCustomFields( - transport: Transport, - parent: CustomFieldParent, - id: string, -): Promise { - return transport.executeManual( - `${entityUrl(transport, parent, id, 'custom_fields')}?include=definition`, - ); -} - -export function createCustomField( - transport: Transport, - parent: CustomFieldParent, - id: string, - apiSlug: string, - value: unknown, -): Promise { - const payload = { - data: { type: 'custom_field', attributes: { api_slug: apiSlug, value } }, - }; - return transport.executeManual( - entityUrl(transport, parent, id, 'custom_fields'), - { method: 'POST', body: JSON.stringify(payload), headers: JSON_HEADERS }, - ); -} - -export function updateCustomField( - transport: Transport, - parent: CustomFieldParent, - id: string, - apiSlug: string, - value: unknown, -): Promise { - const payload = { data: { type: 'custom_field', attributes: { value } } }; - return transport.executeManual( - entityUrl(transport, parent, id, 'custom_fields', apiSlug), - { method: 'PATCH', body: JSON.stringify(payload), headers: JSON_HEADERS }, - ); -} - -export function deleteCustomField( - transport: Transport, - parent: CustomFieldParent, - id: string, - apiSlug: string, -): Promise { - return transport.executeManual( - entityUrl(transport, parent, id, 'custom_fields', apiSlug), - { method: 'DELETE' }, - ); -} - -export function listPartyRoles( - transport: Transport, - parent: PartyRoleParent, - id: string, -): Promise { - return transport.executeManual( - entityUrl(transport, parent, id, 'party_roles'), - ); -} - -export function createPartyRole( - transport: Transport, - parent: PartyRoleParent, - id: string, - role: PartyRoleName, - partyId: string, -): Promise { - const payload = { - data: { - type: 'party_role', - attributes: { role }, - relationships: { party: { data: { type: 'party', id: partyId } } }, - }, - }; - return transport.executeManual( - entityUrl(transport, parent, id, 'party_roles'), - { method: 'POST', body: JSON.stringify(payload), headers: JSON_HEADERS }, - ); -} - -export function deletePartyRole( - transport: Transport, - parent: PartyRoleParent, - id: string, - partyRoleId: string, -): Promise { - return transport.executeManual( - entityUrl(transport, parent, id, 'party_roles', partyRoleId), - { method: 'DELETE' }, - ); -} diff --git a/sdks/typescript-sdk/src/client/managers/index.ts b/sdks/typescript-sdk/src/client/managers/index.ts index d80a54dc..6e35d9c9 100644 --- a/sdks/typescript-sdk/src/client/managers/index.ts +++ b/sdks/typescript-sdk/src/client/managers/index.ts @@ -4,4 +4,3 @@ export * from './shipments.js'; export * from './shipping-lines.js'; export * from './tracking-requests.js'; export * from './documents.js'; -export type { PartyRoleName } from './entity-subresources.js'; diff --git a/sdks/typescript-sdk/src/client/managers/shipments.ts b/sdks/typescript-sdk/src/client/managers/shipments.ts index afca6e28..9c649684 100644 --- a/sdks/typescript-sdk/src/client/managers/shipments.ts +++ b/sdks/typescript-sdk/src/client/managers/shipments.ts @@ -1,5 +1,6 @@ import type { ShipmentListFilters } from '../../generated/list-filters.js'; import { serializeListQuery } from '../filter-validation.js'; +import type { components, paths } from '../../generated/terminal49.js'; import type { Shipment } from '../../types/models.js'; import type { CallOptions, @@ -13,17 +14,19 @@ import { buildShipmentListQuery, normalizeIncludeWithDefault, } from '../query.js'; +import { callerPayload, type JsonBody } from '../spec.js'; import { BaseManager } from './base.js'; -import { - createCustomField, - createPartyRole, - deleteCustomField, - deletePartyRole, - listCustomFields, - listPartyRoles, - type PartyRoleName, - updateCustomField, -} from './entity-subresources.js'; + +type CustomFieldValue = components['schemas']['custom_field_value']; +type PartyRoleData = JsonBody< + paths['/shipments/{shipment_id}/party_roles']['post'] +>['data']; + +/** Parameters for `addPartyRole`; `role` is limited to what the spec accepts on this route. */ +interface AddPartyRoleParams { + role: PartyRoleData['attributes']['role']; + partyId: PartyRoleData['relationships']['party']['data']['id']; +} const DEFAULT_SHIPMENT_INCLUDES = [ 'containers', @@ -67,7 +70,10 @@ export class ShipmentManager extends BaseManager { } async customFields(id: string, options?: CallOptions): Promise { - const raw = await listCustomFields(this.transport, 'shipments', id); + // The spec omits include=definition, but mapCustomFields reads the included definitions. + const raw = await this.transport.executeManual( + `${this.transport.baseUrl}/shipments/${encodeURIComponent(id)}/custom_fields?include=definition`, + ); return this.formatResult(raw, options?.format, mapCustomFields); } @@ -160,12 +166,19 @@ export class ShipmentManager extends BaseManager { value: unknown, options?: CallOptions, ): Promise { - const raw = await createCustomField( - this.transport, - 'shipments', - id, - apiSlug, - value, + const raw = await this.transport.execute(() => + this.transport.client.POST('/shipments/{shipment_id}/custom_fields', { + params: { path: { shipment_id: id } }, + body: { + data: { + type: 'custom_field', + attributes: { + api_slug: apiSlug, + value: callerPayload(value), + }, + }, + }, + }), ); return this.formatResult(raw, options?.format); } @@ -174,15 +187,17 @@ export class ShipmentManager extends BaseManager { async updateCustomField( id: string, apiSlug: string, - value: unknown, + value: CustomFieldValue, options?: CallOptions, ): Promise { - const raw = await updateCustomField( - this.transport, - 'shipments', - id, - apiSlug, - value, + const raw = await this.transport.execute(() => + this.transport.client.PATCH( + '/shipments/{shipment_id}/custom_fields/{api_slug}', + { + params: { path: { shipment_id: id, api_slug: apiSlug } }, + body: { data: { type: 'custom_field', attributes: { value } } }, + }, + ), ); return this.formatResult(raw, options?.format); } @@ -193,34 +208,44 @@ export class ShipmentManager extends BaseManager { apiSlug: string, options?: CallOptions, ): Promise { - const raw = await deleteCustomField( - this.transport, - 'shipments', - id, - apiSlug, + const raw = await this.transport.execute(() => + this.transport.client.DELETE( + '/shipments/{shipment_id}/custom_fields/{api_slug}', + { + params: { path: { shipment_id: id, api_slug: apiSlug } }, + }, + ), ); return this.formatResult(raw, options?.format); } - /** List the party roles (shipper, consignee, ...) assigned to a shipment. */ + /** List the party roles assigned to a shipment. */ async partyRoles(id: string, options?: CallOptions): Promise { - const raw = await listPartyRoles(this.transport, 'shipments', id); + const raw = await this.transport.execute(() => + this.transport.client.GET('/shipments/{shipment_id}/party_roles', { + params: { path: { shipment_id: id } }, + }), + ); return this.formatResult(raw, options?.format); } /** Assign a party to a shipment in the given role. */ async addPartyRole( id: string, - role: PartyRoleName, - partyId: string, + { role, partyId }: AddPartyRoleParams, options?: CallOptions, ): Promise { - const raw = await createPartyRole( - this.transport, - 'shipments', - id, - role, - partyId, + const raw = await this.transport.execute(() => + this.transport.client.POST('/shipments/{shipment_id}/party_roles', { + params: { path: { shipment_id: id } }, + body: { + data: { + type: 'party_role', + attributes: { role }, + relationships: { party: { data: { type: 'party', id: partyId } } }, + }, + }, + }), ); return this.formatResult(raw, options?.format); } @@ -231,11 +256,13 @@ export class ShipmentManager extends BaseManager { partyRoleId: string, options?: CallOptions, ): Promise { - const raw = await deletePartyRole( - this.transport, - 'shipments', - id, - partyRoleId, + const raw = await this.transport.execute(() => + this.transport.client.DELETE( + '/shipments/{shipment_id}/party_roles/{id}', + { + params: { path: { shipment_id: id, id: partyRoleId } }, + }, + ), ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client/managers/tracking-requests.ts b/sdks/typescript-sdk/src/client/managers/tracking-requests.ts index 8ec200c8..f27330b1 100644 --- a/sdks/typescript-sdk/src/client/managers/tracking-requests.ts +++ b/sdks/typescript-sdk/src/client/managers/tracking-requests.ts @@ -1,3 +1,4 @@ +import type { components } from '../../generated/terminal49.js'; import type { TrackingRequest } from '../../types/models.js'; import type { CallOptions, @@ -13,12 +14,8 @@ import { } from '../mappers.js'; import { copyStringParams, normalizeInclude } from '../query.js'; import { BaseManager } from './base.js'; -import { - createCustomField, - deleteCustomField, - listCustomFields, - updateCustomField, -} from './entity-subresources.js'; + +type CustomFieldValue = components['schemas']['custom_field_value']; export type TrackingRequestType = | 'container' @@ -113,7 +110,10 @@ export class TrackingRequestManager extends BaseManager { /** List custom field values set on a tracking request, with their definitions. */ async customFields(id: string, options?: CallOptions): Promise { - const raw = await listCustomFields(this.transport, 'tracking_requests', id); + // The spec omits include=definition, but mapCustomFields reads the included definitions. + const raw = await this.transport.executeManual( + `${this.transport.baseUrl}/tracking_requests/${encodeURIComponent(id)}/custom_fields?include=definition`, + ); return this.formatResult(raw, options?.format, mapCustomFields); } @@ -121,15 +121,22 @@ export class TrackingRequestManager extends BaseManager { async setCustomField( id: string, apiSlug: string, - value: unknown, + value: CustomFieldValue, options?: CallOptions, ): Promise { - const raw = await createCustomField( - this.transport, - 'tracking_requests', - id, - apiSlug, - value, + const raw = await this.transport.execute(() => + this.transport.client.POST( + '/tracking_requests/{tracking_request_id}/custom_fields', + { + params: { path: { tracking_request_id: id } }, + body: { + data: { + type: 'custom_field', + attributes: { api_slug: apiSlug, value }, + }, + }, + }, + ), ); return this.formatResult(raw, options?.format); } @@ -138,15 +145,17 @@ export class TrackingRequestManager extends BaseManager { async updateCustomField( id: string, apiSlug: string, - value: unknown, + value: CustomFieldValue, options?: CallOptions, ): Promise { - const raw = await updateCustomField( - this.transport, - 'tracking_requests', - id, - apiSlug, - value, + const raw = await this.transport.execute(() => + this.transport.client.PATCH( + '/tracking_requests/{tracking_request_id}/custom_fields/{api_slug}', + { + params: { path: { tracking_request_id: id, api_slug: apiSlug } }, + body: { data: { type: 'custom_field', attributes: { value } } }, + }, + ), ); return this.formatResult(raw, options?.format); } @@ -157,11 +166,13 @@ export class TrackingRequestManager extends BaseManager { apiSlug: string, options?: CallOptions, ): Promise { - const raw = await deleteCustomField( - this.transport, - 'tracking_requests', - id, - apiSlug, + const raw = await this.transport.execute(() => + this.transport.client.DELETE( + '/tracking_requests/{tracking_request_id}/custom_fields/{api_slug}', + { + params: { path: { tracking_request_id: id, api_slug: apiSlug } }, + }, + ), ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client/transport.ts b/sdks/typescript-sdk/src/client/transport.ts index a9d20e85..e29c78aa 100644 --- a/sdks/typescript-sdk/src/client/transport.ts +++ b/sdks/typescript-sdk/src/client/transport.ts @@ -81,9 +81,9 @@ export class Transport { } /** - * Run a hand-built request (shared entity sub-resources, or routes absent from - * the generated OpenAPI types) through the same Auth -> Retry -> ErrorMapping - * pipeline the typed client uses, including the timeout-wrapped fetch. Successful bodies are + * Run a hand-built request (routes or query params the OpenAPI spec does not + * describe) through the same Auth -> Retry -> ErrorMapping pipeline the typed + * client uses, including the timeout-wrapped fetch. Successful bodies are * read with {@link readSuccessBody} so a non-JSON success body is surfaced * rather than silently collapsed to `undefined`. */ From 4bfe5218e6fbce7b6256b8cafb8ce1d79fa3e6c4 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 14:03:13 -0700 Subject: [PATCH 06/14] feat(sdk)!: serve containers.route from GET /containers/{id}/map_geojson The legacy GET /containers/{id}/route endpoint is gone from the API. map_geojson is its replacement, so containers.route() now calls it through the typed client and keeps the "route" name users know. The raw format is the GeoJSON FeatureCollection. The mapped format is a new ContainerRoute: ports in ports_sequence order (name, country code, POL/POD/TS label, coordinates, inbound eta/ata, outbound etd/atd), the current vessel when it is at sea, and totalPorts. Absent properties map to null. Track LineStrings stay in the raw format only. containers.map() becomes a deprecated alias of route(), and getContainerRoute() keeps delegating to route(). The mapping tests use a fixture copied from the spec example. BREAKING CHANGE: the exported Route type and mapRoute are removed. The mapped result of containers.route() / getContainerRoute() is now ContainerRoute ({ ports, currentVessel, totalPorts }) instead of Route ({ id, totalLegs, locations, createdAt, updatedAt }). Port code/city, transport mode, carrier SCAC and per-leg vessels are no longer available because map_geojson does not return them. Co-Authored-By: Claude Opus 5.5 --- .../scripts/generate-fixtures.mjs | 9 - .../typescript-sdk/src/client.mapping.test.ts | 271 +++++++++--------- sdks/typescript-sdk/src/client.test.ts | 22 +- .../src/client.transport.test.ts | 13 +- sdks/typescript-sdk/src/client.ts | 2 +- .../src/client/managers/containers.ts | 29 +- sdks/typescript-sdk/src/client/mappers.ts | 151 ++++++---- .../src/fixtures/containers.map_geojson.json | 232 +++++++++++++++ .../src/fixtures/containers.route.json | 108 ------- sdks/typescript-sdk/src/scripts/smoke.ts | 2 +- sdks/typescript-sdk/src/types/models.ts | 67 +++-- 11 files changed, 529 insertions(+), 377 deletions(-) create mode 100644 sdks/typescript-sdk/src/fixtures/containers.map_geojson.json delete mode 100644 sdks/typescript-sdk/src/fixtures/containers.route.json diff --git a/sdks/typescript-sdk/scripts/generate-fixtures.mjs b/sdks/typescript-sdk/scripts/generate-fixtures.mjs index 0049ad7a..64340c36 100644 --- a/sdks/typescript-sdk/scripts/generate-fixtures.mjs +++ b/sdks/typescript-sdk/scripts/generate-fixtures.mjs @@ -293,15 +293,6 @@ async function main() { ); writeFixture('containers.get.include', containerGetInclude); - try { - const route = await fetchJson( - `/containers/${containerId}/route?include=port,vessel,route_location`, - ); - writeFixture('containers.route', route); - } catch (error) { - console.warn(`Skipping route fixture: ${error.message}`); - } - try { const events = await fetchJson( `/containers/${containerId}/transport_events?include=location,terminal`, diff --git a/sdks/typescript-sdk/src/client.mapping.test.ts b/sdks/typescript-sdk/src/client.mapping.test.ts index c403adde..89bf45f3 100644 --- a/sdks/typescript-sdk/src/client.mapping.test.ts +++ b/sdks/typescript-sdk/src/client.mapping.test.ts @@ -3,6 +3,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vite-plus/test'; import { Terminal49Client } from './client.js'; +import { mapContainerRoute } from './client/mappers.js'; import { createMockFetch, jsonResponse } from './test/mock-fetch.js'; const baseUrl = 'https://api.test/v2'; @@ -113,120 +114,6 @@ describe('Terminal49Client mapping helpers', () => { } }); - itIf(hasFixture('containers.route'))( - 'maps container route with ports and vessel legs', - async () => { - const fixture = loadFixture('containers.route'); - const { fetchImpl } = createMockFetch({ - '/containers/cont-1/route?include=port,vessel,route_location': () => - jsonResponse(fixture), - }); - - const client = new Terminal49Client({ - apiToken: 'token-123', - apiBaseUrl: baseUrl, - fetchImpl, - }); - - const result = (await client.getContainerRoute('cont-1', { - format: 'mapped', - })) as any; - - expect(result.totalLegs).toBe(result.locations.length); - - const routeLocationRef = - fixture?.data?.relationships?.route_locations?.data?.[0]; - const routeLocation = routeLocationRef - ? findIncluded(fixture, 'route_location', routeLocationRef.id) - : null; - if (!routeLocation) return; - - // The port for a route leg lives under the `location` relationship of a - // route_location (type port|terminal), NOT a `port` relationship. - const locationId = routeLocation?.relationships?.location?.data?.id; - const port = locationId - ? findIncluded(fixture, 'port', locationId) - : null; - if (port) { - // Regression guard: the leg must resolve its port, not be null. - expect(result.locations[0]?.port).toBeTruthy(); - expectIfDefined(result.locations[0]?.port?.code, port.attributes?.code); - expectIfDefined(result.locations[0]?.port?.name, port.attributes?.name); - expectIfDefined(result.locations[0]?.port?.city, port.attributes?.city); - expectIfDefined( - result.locations[0]?.port?.countryCode, - port.attributes?.country_code, - ); - } - - expectIfDefined( - result.locations[0]?.inbound?.mode, - routeLocation.attributes?.inbound_mode, - ); - expectIfDefined( - result.locations[0]?.inbound?.carrierScac, - routeLocation.attributes?.inbound_scac, - ); - expectIfDefined( - result.locations[0]?.inbound?.eta, - routeLocation.attributes?.inbound_eta_at, - ); - expectIfDefined( - result.locations[0]?.inbound?.ata, - routeLocation.attributes?.inbound_ata_at, - ); - - expectIfDefined( - result.locations[0]?.outbound?.mode, - routeLocation.attributes?.outbound_mode, - ); - expectIfDefined( - result.locations[0]?.outbound?.carrierScac, - routeLocation.attributes?.outbound_scac, - ); - expectIfDefined( - result.locations[0]?.outbound?.etd, - routeLocation.attributes?.outbound_etd_at, - ); - expectIfDefined( - result.locations[0]?.outbound?.atd, - routeLocation.attributes?.outbound_atd_at, - ); - - const inboundVesselId = - routeLocation?.relationships?.inbound_vessel?.data?.id; - const inboundVessel = inboundVesselId - ? findIncluded(fixture, 'vessel', inboundVesselId) - : null; - if (inboundVessel) { - expectIfDefined( - result.locations[0]?.inbound?.vessel?.name, - inboundVessel.attributes?.name, - ); - expectIfDefined( - result.locations[0]?.inbound?.vessel?.imo, - inboundVessel.attributes?.imo, - ); - } - - const outboundVesselId = - routeLocation?.relationships?.outbound_vessel?.data?.id; - const outboundVessel = outboundVesselId - ? findIncluded(fixture, 'vessel', outboundVesselId) - : null; - if (outboundVessel) { - expectIfDefined( - result.locations[0]?.outbound?.vessel?.name, - outboundVessel.attributes?.name, - ); - expectIfDefined( - result.locations[0]?.outbound?.vessel?.imo, - outboundVessel.attributes?.imo, - ); - } - }, - ); - it('maps tracking request fields from base response', async () => { const fixture = loadFixture('tracking-requests.get.base'); const trackingId = fixture?.data?.id || 'tr-1'; @@ -623,42 +510,152 @@ describe('Terminal49Client mapping helpers', () => { expect(shipments.items).toEqual([]); }); - it('resolves every route leg port from the `location` relationship', async () => { - const fixture = loadFixture('containers.route'); + it('maps the map_geojson route into ordered ports and the current vessel', async () => { + const fixture = loadFixture('containers.map_geojson'); const { fetchImpl } = createMockFetch({ - '/containers/cont-1/route?include=port,vessel,route_location': () => - jsonResponse(fixture), + '/containers/cont-1/map_geojson': () => jsonResponse(fixture), }); - const client = new Terminal49Client({ apiToken: 'token-123', apiBaseUrl: baseUrl, fetchImpl, }); - const result = (await client.getContainerRoute('cont-1', { + const result = await client.containers.route('cont-1', { format: 'mapped', - })) as any; + }); - expect(result.totalLegs).toBe(2); - expect(result.locations.length).toBe(2); + expect(result).toEqual({ + ports: [ + { + locationId: 'c5adae24-6fd4-4720-8813-976cf206feb1', + name: 'Laem Chabang', + countryCode: 'TH', + label: 'POL', + sequence: 1, + coordinates: { longitude: 100.896831042, latitude: 13.065302386 }, + inbound: { eta: null, ata: null }, + outbound: { etd: null, atd: '2025-11-08T00:44:52Z' }, + }, + { + locationId: 'ed64d446-9098-420c-ab08-c127e62509fe', + name: 'Xiamen', + countryCode: 'CN', + label: 'TS1', + sequence: 2, + coordinates: { longitude: 118.0293, latitude: 24.50318 }, + inbound: { eta: null, ata: '2025-11-15T16:00:00Z' }, + outbound: { etd: null, atd: '2025-11-19T16:00:00Z' }, + }, + { + locationId: '6129528d-846e-4571-ae16-b5328a4285ab', + name: 'Savannah', + countryCode: 'US', + label: 'POD', + sequence: 3, + coordinates: { longitude: -81.140998396, latitude: 32.128923976 }, + inbound: { eta: '2025-12-31T05:00:00Z', ata: null }, + outbound: { etd: null, atd: null }, + }, + ], + currentVessel: { + name: 'ZIM BANGKOK', + imo: '9936525', + voyage: '13E', + coordinates: { longitude: -131.128473333, latitude: 31.023033333 }, + heading: 108, + speed: 21, + departurePortId: 'ed64d446-9098-420c-ab08-c127e62509fe', + arrivalPortId: '6129528d-846e-4571-ae16-b5328a4285ab', + }, + totalPorts: 3, + }); + }); - // Each leg must carry a non-null port resolved via `location`. - expect(result.locations[0]?.port?.code).toBe('CNSHA'); - expect(result.locations[0]?.port?.name).toBe('Shanghai'); - expect(result.locations[0]?.port?.city).toBe('Shanghai'); - expect(result.locations[0]?.port?.countryCode).toBe('CN'); + it('keeps the GeoJSON body as the raw half and serves map() as an alias', async () => { + const fixture = loadFixture('containers.map_geojson'); + const { fetchImpl, calls } = createMockFetch({ + '/containers/cont-1/map_geojson': () => jsonResponse(fixture), + }); + const client = new Terminal49Client({ + apiToken: 'token-123', + apiBaseUrl: baseUrl, + fetchImpl, + }); - expect(result.locations[1]?.port?.code).toBe('USLAX'); - expect(result.locations[1]?.port?.name).toBe('Los Angeles'); - expect(result.locations[1]?.port?.countryCode).toBe('US'); + const both = await client.containers.route('cont-1', { format: 'both' }); + const viaMap = await client.containers.map('cont-1', { format: 'mapped' }); - // Outbound leg + vessel resolution sanity. - expect(result.locations[0]?.outbound?.carrierScac).toBe('MAEU'); - expect(result.locations[0]?.outbound?.vessel?.name).toBe( - 'MAERSK EDINBURGH', - ); - expect(result.locations[1]?.inbound?.vessel?.imo).toBe('9456769'); + expect(both.raw).toEqual(fixture); + expect(viaMap).toEqual(both.mapped); + expect(calls.map((c) => c.url.pathname)).toEqual([ + '/v2/containers/cont-1/map_geojson', + '/v2/containers/cont-1/map_geojson', + ]); + }); + + it('orders ports by sequence and maps absent properties to null', () => { + const result = mapContainerRoute({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [-81.1, 32.1] }, + properties: { feature_type: 'port', ports_sequence: 2, name: 'B' }, + }, + { + type: 'Feature', + geometry: { + type: 'LineString', + coordinates: [ + [1, 2], + [3, 4], + ], + }, + properties: { feature_type: 'port' }, + }, + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [] }, + properties: { feature_type: 'port', ports_sequence: 1, name: 'A' }, + }, + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [10, 20] }, + properties: { feature_type: 'current_vessel' }, + }, + ], + }); + + expect(result.ports.map((p) => p.name)).toEqual(['A', 'B', null]); + expect(result.ports[0].coordinates).toBeNull(); + expect(result.ports[2]).toEqual({ + locationId: null, + name: null, + countryCode: null, + label: null, + sequence: null, + coordinates: null, + inbound: { eta: null, ata: null }, + outbound: { etd: null, atd: null }, + }); + expect(result.currentVessel).toEqual({ + name: null, + imo: null, + voyage: null, + coordinates: { longitude: 10, latitude: 20 }, + heading: null, + speed: null, + departurePortId: null, + arrivalPortId: null, + }); + expect(result.totalPorts).toBe(3); + }); + + it('maps an empty FeatureCollection to an empty route', () => { + expect( + mapContainerRoute({ type: 'FeatureCollection', features: [] }), + ).toEqual({ ports: [], currentVessel: null, totalPorts: 0 }); }); it('maps port `code` into the shipment locode fields', async () => { diff --git a/sdks/typescript-sdk/src/client.test.ts b/sdks/typescript-sdk/src/client.test.ts index d8ef5191..47d159e0 100644 --- a/sdks/typescript-sdk/src/client.test.ts +++ b/sdks/typescript-sdk/src/client.test.ts @@ -9,18 +9,19 @@ import { import { createMockFetch, jsonResponse } from './test/mock-fetch.js'; const baseUrl = 'https://api.test/v2'; +const EMPTY_ROUTE = { type: 'FeatureCollection', features: [] }; describe('Terminal49Client', () => { it('retries on 500 and succeeds on second attempt', async () => { vi.useFakeTimers(); let attempt = 0; const { fetchImpl, calls } = createMockFetch({ - '/containers/abc/route?include=port,vessel,route_location': () => { + '/containers/abc/map_geojson': () => { attempt += 1; if (attempt === 1) { return jsonResponse({ errors: [{ detail: 'server error' }] }, 500); } - return jsonResponse({ data: { id: 'route-1' } }); + return jsonResponse(EMPTY_ROUTE); }, }); @@ -36,7 +37,7 @@ describe('Terminal49Client', () => { await vi.advanceTimersByTimeAsync(500); const result = await resultPromise; - expect(result.data.id).toBe('route-1'); + expect(result).toEqual(EMPTY_ROUTE); expect(calls.length).toBe(2); } finally { vi.useRealTimers(); @@ -405,8 +406,19 @@ describe('Terminal49Client', () => { it('maps 403 feature gating to FeatureNotEnabledError', async () => { const { fetchImpl } = createMockFetch({ - '/containers/abc/route?include=port,vessel,route_location': () => - jsonResponse({ errors: [{ detail: 'Feature not enabled' }] }, 403), + '/containers/abc/map_geojson': () => + jsonResponse( + { + errors: [ + { + status: '403', + title: 'Forbidden', + detail: 'Routing data feature is not enabled for this account', + }, + ], + }, + 403, + ), }); const client = new Terminal49Client({ diff --git a/sdks/typescript-sdk/src/client.transport.test.ts b/sdks/typescript-sdk/src/client.transport.test.ts index ae571c22..aed1744a 100644 --- a/sdks/typescript-sdk/src/client.transport.test.ts +++ b/sdks/typescript-sdk/src/client.transport.test.ts @@ -9,6 +9,7 @@ import { import { jsonResponse } from './test/mock-fetch.js'; const baseUrl = 'https://api.test/v2'; +const EMPTY_ROUTE = { type: 'FeatureCollection', features: [] }; describe('Terminal49Client transport resilience', () => { it('normalizes a thrown network error and retries it like a 5xx', async () => { @@ -20,7 +21,7 @@ describe('Terminal49Client transport resilience', () => { if (attempt === 1) { throw new TypeError('fetch failed'); } - return jsonResponse({ data: { id: 'route-1' } }); + return jsonResponse(EMPTY_ROUTE); }); const client = new Terminal49Client({ @@ -34,7 +35,7 @@ describe('Terminal49Client transport resilience', () => { await vi.advanceTimersByTimeAsync(500); const result = await resultPromise; - expect(result.data.id).toBe('route-1'); + expect(result).toEqual(EMPTY_ROUTE); expect(attempt).toBe(2); } finally { vi.useRealTimers(); @@ -114,7 +115,7 @@ describe('Terminal49Client transport resilience', () => { if (attempt === 2) { return jsonResponse({ errors: [{ detail: 'server error' }] }, 500); } - return jsonResponse({ data: { id: 'route-1' } }); + return jsonResponse(EMPTY_ROUTE); }); const client = new Terminal49Client({ @@ -128,7 +129,7 @@ describe('Terminal49Client transport resilience', () => { await vi.advanceTimersByTimeAsync(2000); const result = await resultPromise; - expect(result.data.id).toBe('route-1'); + expect(result).toEqual(EMPTY_ROUTE); expect(attempt).toBe(3); } finally { vi.useRealTimers(); @@ -146,7 +147,7 @@ describe('Terminal49Client transport resilience', () => { 'Retry-After': '3', }); } - return jsonResponse({ data: { id: 'route-1' } }); + return jsonResponse(EMPTY_ROUTE); }); const client = new Terminal49Client({ @@ -165,7 +166,7 @@ describe('Terminal49Client transport resilience', () => { await vi.advanceTimersByTimeAsync(1000); const result = await resultPromise; - expect(result.data.id).toBe('route-1'); + expect(result).toEqual(EMPTY_ROUTE); expect(attempt).toBe(2); } finally { vi.useRealTimers(); diff --git a/sdks/typescript-sdk/src/client.ts b/sdks/typescript-sdk/src/client.ts index fcae6994..421e77df 100644 --- a/sdks/typescript-sdk/src/client.ts +++ b/sdks/typescript-sdk/src/client.ts @@ -462,7 +462,7 @@ export class Terminal49Client { return this.containers.events(id, options); } - /** Fetch routing details for a container. This may require a paid Terminal49 feature. */ + /** Fetch a container's route (ports, current vessel, tracks). Requires the Routing Data feature. */ async getContainerRoute(id: string, options?: CallOptions): Promise { return this.containers.route(id, options); } diff --git a/sdks/typescript-sdk/src/client/managers/containers.ts b/sdks/typescript-sdk/src/client/managers/containers.ts index 18b364e7..48ab8490 100644 --- a/sdks/typescript-sdk/src/client/managers/containers.ts +++ b/sdks/typescript-sdk/src/client/managers/containers.ts @@ -10,8 +10,8 @@ import type { } from '../../types/options.js'; import { mapContainerList, + mapContainerRoute, mapCustomFields, - mapRoute, mapTransportEvents, } from '../mappers.js'; import { @@ -137,32 +137,23 @@ export class ContainerManager extends BaseManager { } /** - * @deprecated `GET /containers/{id}/route` is no longer part of the public - * Terminal49 API and is expected to return `NotFoundError`. Use - * {@link ContainerManager.map} for routing geometry instead. + * Fetch the container's route: ports, the current vessel, and vessel tracks. + * The raw format is the GeoJSON FeatureCollection; the mapped format is a + * `ContainerRoute`. Requires the Routing Data feature, otherwise the API + * returns 403. */ async route(id: string, options?: CallOptions): Promise { - // The route path is absent from current OpenAPI, although this SDK already - // supports it. Keep the existing client/middleware path while regenerating - // types from the actual source, rather than hand-editing generated types. const raw = await this.transport.execute(() => - this.transport.client.GET('/containers/{id}/route' as any, { - params: { - path: { id }, - query: { include: 'port,vessel,route_location' } as any, - }, + this.transport.client.GET('/containers/{id}/map_geojson', { + params: { path: { id } }, }), ); - return this.formatResult(raw, options?.format, mapRoute); + return this.formatResult(raw, options?.format, mapContainerRoute); } + /** @deprecated Use {@link ContainerManager.route}. */ async map(id: string, options?: CallOptions): Promise { - const raw = await this.transport.execute(() => - this.transport.client.GET('/containers/{id}/map_geojson', { - params: { path: { id } }, - }), - ); - return this.formatResult(raw, options?.format); + return this.route(id, options); } /** Create a custom field value on a container. */ diff --git a/sdks/typescript-sdk/src/client/mappers.ts b/sdks/typescript-sdk/src/client/mappers.ts index e425e30e..f475aa5d 100644 --- a/sdks/typescript-sdk/src/client/mappers.ts +++ b/sdks/typescript-sdk/src/client/mappers.ts @@ -1,7 +1,11 @@ +import type { paths } from '../generated/terminal49.js'; import type { Container, + ContainerRoute, CustomField, - Route, + RouteCoordinates, + RoutePort, + RouteVessel, Shipment, ShippingLine, TrackingRequest, @@ -74,74 +78,95 @@ export function mapTransportEvents(doc: any) { }); } -export function mapRoute(doc: any): Route { - const apiDoc = new JsonApiDocument(doc); - const route = apiDoc.getAttributes(apiDoc.data, false); - const routeLocations = - apiDoc.getRelationship(apiDoc.data, 'route_locations') || []; - - const locations = ( - Array.isArray(routeLocations) ? routeLocations : [routeLocations] - ) - .map((location: any) => { - if (!location) return null; - - const attrs = location.attributes || {}; - // A route leg's port lives under the `location` relationship - // (type port|terminal); there is no `port` relationship. - const port = apiDoc.getRelationship(location, 'location'); - const inboundVessel = apiDoc.getRelationship(location, 'inbound_vessel'); - const outboundVessel = apiDoc.getRelationship( - location, - 'outbound_vessel', - ); +type ContainerMapGeojson = + paths['/containers/{id}/map_geojson']['get']['responses'][200]['content']['application/json']; +type RouteFeature = ContainerMapGeojson['features'][number]; +type RouteFeatureProperties = RouteFeature['properties']; +type FeatureProperties = + Extract; - return { - port: port - ? { - code: port.attributes?.code, - name: port.attributes?.name, - city: port.attributes?.city, - countryCode: port.attributes?.country_code, - } - : null, - inbound: { - mode: attrs.inbound_mode, - carrierScac: attrs.inbound_scac, - eta: attrs.inbound_eta_at, - ata: attrs.inbound_ata_at, - vessel: inboundVessel - ? { - name: inboundVessel.attributes?.name, - imo: inboundVessel.attributes?.imo, - } - : null, - }, - outbound: { - mode: attrs.outbound_mode, - carrierScac: attrs.outbound_scac, - etd: attrs.outbound_etd_at, - atd: attrs.outbound_atd_at, - vessel: outboundVessel - ? { - name: outboundVessel.attributes?.name, - imo: outboundVessel.attributes?.imo, - } - : null, - }, - }; - }) - .filter((loc: any) => loc !== null); +function pointCoordinates( + geometry: RouteFeature['geometry'], +): RouteCoordinates | null { + if (geometry.type !== 'Point' || geometry.coordinates.length < 2) { + return null; + } + const [longitude, latitude] = geometry.coordinates; + return { longitude, latitude }; +} +function mapRoutePort( + props: FeatureProperties<'port'>, + geometry: RouteFeature['geometry'], +): RoutePort { return { - id: apiDoc.data?.id, - totalLegs: locations.length, - locations: locations as any, - createdAt: route.created_at, - updatedAt: route.updated_at, + locationId: props.location_id ?? null, + name: props.name ?? null, + countryCode: props.country_code ?? null, + label: props.label ?? null, + sequence: props.ports_sequence ?? null, + coordinates: pointCoordinates(geometry), + inbound: { + eta: props.inbound_eta_at ?? null, + ata: props.inbound_ata_at ?? null, + }, + outbound: { + etd: props.outbound_etd_at ?? null, + atd: props.outbound_atd_at ?? null, + }, + }; +} + +function mapRouteVessel( + props: FeatureProperties<'current_vessel'>, + geometry: RouteFeature['geometry'], +): RouteVessel { + return { + name: props.vessel_name ?? null, + imo: props.vessel_imo ?? null, + voyage: props.voyage_number ?? null, + coordinates: pointCoordinates(geometry), + heading: props.vessel_location_heading ?? null, + speed: props.vessel_location_speed ?? null, + departurePortId: props.departure_port_id ?? null, + arrivalPortId: props.arrival_port_id ?? null, }; } +/** Map a `map_geojson` FeatureCollection to ports in route order plus the current vessel. */ +export function mapContainerRoute(doc: ContainerMapGeojson): ContainerRoute { + const ports: RoutePort[] = []; + let currentVessel: RouteVessel | null = null; + + for (const feature of doc.features) { + const props = feature.properties; + switch (props.feature_type) { + case 'port': + ports.push(mapRoutePort(props, feature.geometry)); + break; + case 'current_vessel': + currentVessel = mapRouteVessel(props, feature.geometry); + break; + case 'past_vessel_locations': + case 'estimated_full_legs': + case 'estimated_partial_leg': + break; + default: { + const _exhaustive: never = props; + void _exhaustive; + } + } + } + + ports.sort( + (a, b) => + (a.sequence ?? Number.MAX_SAFE_INTEGER) - + (b.sequence ?? Number.MAX_SAFE_INTEGER), + ); + + return { ports, currentVessel, totalPorts: ports.length }; +} + export function mapShippingLines(doc: any): ShippingLine[] { const data = Array.isArray(doc?.data) ? doc.data : []; return data diff --git a/sdks/typescript-sdk/src/fixtures/containers.map_geojson.json b/sdks/typescript-sdk/src/fixtures/containers.map_geojson.json new file mode 100644 index 00000000..5deb6eb4 --- /dev/null +++ b/sdks/typescript-sdk/src/fixtures/containers.map_geojson.json @@ -0,0 +1,232 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 100.896831042, + 13.065302386 + ] + }, + "properties": { + "feature_type": "port", + "ports_sequence": 1, + "ports_total": 3, + "location_id": "c5adae24-6fd4-4720-8813-976cf206feb1", + "location_type": "Port", + "name": "Laem Chabang", + "state_abbr": "20", + "state": null, + "country_code": "TH", + "country": "Thailand", + "time_zone": "Asia/Bangkok", + "inbound_eta_at": null, + "inbound_ata_at": null, + "outbound_etd_at": null, + "outbound_atd_at": "2025-11-08T00:44:52Z", + "label": "POL", + "updated_at": "2025-12-11T09:01:08Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 100.868768333, + 13.07306 + ], + [ + 100.839155, + 13.079318333 + ], + [ + 118.038213333, + 24.43842 + ], + [ + 118.03862, + 24.440998333 + ] + ] + }, + "properties": { + "feature_type": "past_vessel_locations", + "ports_sequence": 1, + "vessel_id": "87a12f43-766c-4078-89bc-ac6595082f7b", + "start_time": "2025-11-08T00:44:52Z", + "end_time": "2025-11-15T16:00:00Z", + "point_count": 546, + "outbound_atd_at": "2025-11-08T00:44:52Z", + "inbound_ata_at": "2025-11-15T16:00:00Z", + "inbound_eta_at": null + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 118.0293, + 24.50318 + ] + }, + "properties": { + "feature_type": "port", + "ports_sequence": 2, + "ports_total": 3, + "location_id": "ed64d446-9098-420c-ab08-c127e62509fe", + "location_type": "Port", + "name": "Xiamen", + "state_abbr": "FJ", + "state": null, + "country_code": "CN", + "country": "China", + "time_zone": "Asia/Shanghai", + "inbound_eta_at": null, + "inbound_ata_at": "2025-11-15T16:00:00Z", + "outbound_etd_at": null, + "outbound_atd_at": "2025-11-19T16:00:00Z", + "label": "TS1", + "updated_at": "2025-12-11T09:01:08Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -131.128473333, + 31.023033333 + ] + }, + "properties": { + "feature_type": "current_vessel", + "ports_sequence": 2, + "vessel_id": "93fc5dce-4c7f-4089-bd28-f20cd9202ab0", + "vessel_name": "ZIM BANGKOK", + "vessel_imo": "9936525", + "voyage_number": "13E", + "vessel_location_timestamp": "2025-12-11T11:46:03Z", + "vessel_location_heading": 108, + "vessel_location_speed": 21, + "departure_port_id": "ed64d446-9098-420c-ab08-c127e62509fe", + "departure_port_name": "Xiamen", + "departure_port_state_abbr": "FJ", + "departure_port_state": null, + "departure_port_country_code": "CN", + "departure_port_country": "China", + "departure_port_label": "TS1", + "departure_port_atd": "2025-11-19T16:00:00Z", + "departure_port_time_zone": "Asia/Shanghai", + "arrival_port_id": "6129528d-846e-4571-ae16-b5328a4285ab", + "arrival_port_name": "Savannah", + "arrival_port_state_abbr": "GA", + "arrival_port_state": "Georgia", + "arrival_port_country_code": "US", + "arrival_port_country": "United States", + "arrival_port_label": "POD", + "arrival_port_eta": "2025-12-31T05:00:00Z", + "arrival_port_time_zone": "America/New_York" + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 118.045325, + 23.518831667 + ], + [ + 118.076886667, + 23.556158333 + ], + [ + -131.583741667, + 31.153668333 + ], + [ + -131.128473333, + 31.023033333 + ] + ] + }, + "properties": { + "feature_type": "past_vessel_locations", + "ports_sequence": 2, + "vessel_id": "93fc5dce-4c7f-4089-bd28-f20cd9202ab0", + "start_time": "2025-11-19T16:00:00Z", + "end_time": "2026-01-07T05:00:00Z", + "point_count": 1402, + "outbound_atd_at": "2025-11-19T16:00:00Z", + "inbound_ata_at": null, + "inbound_eta_at": "2025-12-31T05:00:00Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -131.128473333, + 31.023033333 + ], + [ + -130.9177, + 30.67224 + ], + [ + -80.70766, + 31.96363 + ], + [ + -80.91232, + 32.03728 + ] + ] + }, + "properties": { + "feature_type": "estimated_partial_leg", + "ports_sequence": 2, + "current_port_id": "ed64d446-9098-420c-ab08-c127e62509fe", + "next_port_id": "6129528d-846e-4571-ae16-b5328a4285ab", + "point_count": 364 + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -81.140998396, + 32.128923976 + ] + }, + "properties": { + "feature_type": "port", + "ports_sequence": 3, + "ports_total": 3, + "location_id": "6129528d-846e-4571-ae16-b5328a4285ab", + "location_type": "Port", + "name": "Savannah", + "state_abbr": "GA", + "state": "Georgia", + "country_code": "US", + "country": "United States", + "time_zone": "America/New_York", + "inbound_eta_at": "2025-12-31T05:00:00Z", + "inbound_ata_at": null, + "outbound_etd_at": null, + "outbound_atd_at": null, + "label": "POD", + "updated_at": "2025-12-11T09:01:08Z" + } + } + ] +} diff --git a/sdks/typescript-sdk/src/fixtures/containers.route.json b/sdks/typescript-sdk/src/fixtures/containers.route.json deleted file mode 100644 index 0c18fcf2..00000000 --- a/sdks/typescript-sdk/src/fixtures/containers.route.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "data": { - "id": "route-1", - "type": "route", - "attributes": { - "created_at": "2026-06-01T10:00:00Z", - "updated_at": "2026-06-10T12:30:00Z" - }, - "relationships": { - "route_locations": { - "data": [ - { "id": "rl-1", "type": "route_location" }, - { "id": "rl-2", "type": "route_location" } - ] - } - } - }, - "included": [ - { - "id": "rl-1", - "type": "route_location", - "attributes": { - "id": "rl-1", - "inbound_scac": null, - "inbound_mode": null, - "inbound_eta_at": null, - "inbound_ata_at": null, - "inbound_voyage_number": null, - "outbound_scac": "MAEU", - "outbound_mode": "vessel", - "outbound_etd_at": "2026-06-02T08:00:00Z", - "outbound_atd_at": "2026-06-02T09:15:00Z", - "outbound_voyage_number": "123W", - "created_at": "2026-06-01T10:00:00Z", - "updated_at": "2026-06-10T12:30:00Z" - }, - "relationships": { - "route": { "data": { "id": "route-1", "type": "route" } }, - "location": { "data": { "id": "port-cnsha", "type": "port" } }, - "inbound_vessel": { "data": null }, - "outbound_vessel": { "data": { "id": "vessel-1", "type": "vessel" } } - } - }, - { - "id": "rl-2", - "type": "route_location", - "attributes": { - "id": "rl-2", - "inbound_scac": "MAEU", - "inbound_mode": "vessel", - "inbound_eta_at": "2026-06-20T14:00:00Z", - "inbound_ata_at": null, - "inbound_voyage_number": "123W", - "outbound_scac": null, - "outbound_mode": null, - "outbound_etd_at": null, - "outbound_atd_at": null, - "outbound_voyage_number": null, - "created_at": "2026-06-01T10:00:00Z", - "updated_at": "2026-06-10T12:30:00Z" - }, - "relationships": { - "route": { "data": { "id": "route-1", "type": "route" } }, - "location": { "data": { "id": "port-uslax", "type": "port" } }, - "inbound_vessel": { "data": { "id": "vessel-1", "type": "vessel" } }, - "outbound_vessel": { "data": null } - } - }, - { - "id": "port-cnsha", - "type": "port", - "attributes": { - "id": "port-cnsha", - "name": "Shanghai", - "code": "CNSHA", - "state_abbr": "SH", - "city": "Shanghai", - "country_code": "CN", - "latitude": "31.22222", - "longitude": "121.45806", - "time_zone": "Asia/Shanghai" - } - }, - { - "id": "port-uslax", - "type": "port", - "attributes": { - "id": "port-uslax", - "name": "Los Angeles", - "code": "USLAX", - "state_abbr": "CA", - "city": "Los Angeles", - "country_code": "US", - "latitude": "33.74537", - "longitude": "-118.27370", - "time_zone": "America/Los_Angeles" - } - }, - { - "id": "vessel-1", - "type": "vessel", - "attributes": { - "name": "MAERSK EDINBURGH", - "imo": "9456769" - } - } - ] -} diff --git a/sdks/typescript-sdk/src/scripts/smoke.ts b/sdks/typescript-sdk/src/scripts/smoke.ts index db36337a..7c08f21d 100644 --- a/sdks/typescript-sdk/src/scripts/smoke.ts +++ b/sdks/typescript-sdk/src/scripts/smoke.ts @@ -36,7 +36,7 @@ async function main() { const route = await client.containers.route(containerId, { format: 'mapped', }); - console.log('Route legs:', (route as any)?.totalLegs ?? 'n/a'); + console.log('Route ports:', route?.totalPorts ?? 'n/a'); } if (shipmentId) { diff --git a/sdks/typescript-sdk/src/types/models.ts b/sdks/typescript-sdk/src/types/models.ts index 0a4095e9..a2b25c2f 100644 --- a/sdks/typescript-sdk/src/types/models.ts +++ b/sdks/typescript-sdk/src/types/models.ts @@ -136,34 +136,45 @@ export interface Shipment { [key: string]: any; } -/** Simplified container route model returned by mapped SDK responses. */ -export interface Route { - id?: string; - totalLegs: number; - locations: Array<{ - port?: { - code?: string | null; - name?: string | null; - city?: string | null; - countryCode?: string | null; - } | null; - inbound: { - mode?: string | null; - carrierScac?: string | null; - eta?: string | null; - ata?: string | null; - vessel?: { name?: string | null; imo?: string | null } | null; - }; - outbound: { - mode?: string | null; - carrierScac?: string | null; - etd?: string | null; - atd?: string | null; - vessel?: { name?: string | null; imo?: string | null } | null; - }; - }>; - createdAt?: string | null; - updatedAt?: string | null; +/** A `[longitude, latitude]` GeoJSON point, named so the axis order cannot be swapped. */ +export interface RouteCoordinates { + longitude: number; + latitude: number; +} + +/** One port on a container route, from a `port` feature of `GET /containers/{id}/map_geojson`. */ +export interface RoutePort { + locationId: string | null; + name: string | null; + countryCode: string | null; + /** `POL`, `POD`, or `TS1`, `TS2`, and so on for transshipment ports. */ + label: string | null; + /** Position in the route: 1 is the POL, the last is the POD. */ + sequence: number | null; + coordinates: RouteCoordinates | null; + inbound: { eta: string | null; ata: string | null }; + outbound: { etd: string | null; atd: string | null }; +} + +/** The vessel carrying the container right now. Present only while it is at sea. */ +export interface RouteVessel { + name: string | null; + imo: string | null; + voyage: string | null; + coordinates: RouteCoordinates | null; + /** Degrees, 0-360. */ + heading: number | null; + /** Knots. */ + speed: number | null; + departurePortId: string | null; + arrivalPortId: string | null; +} + +/** Mapped container route: ports in route order plus the current vessel. */ +export interface ContainerRoute { + ports: RoutePort[]; + currentVessel: RouteVessel | null; + totalPorts: number; } /** Simplified tracking request model returned by mapped SDK responses. */ From 61f52bfaf2007d3102f04f99f85d16edd735e956 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 10:55:27 -0700 Subject: [PATCH 07/14] feat(sdk,cli)!: send vessel future-position params and show the route table GET /vessels/{id}/future_positions requires port_id and previous_port_id, and future_positions_with_coordinates also requires latitude and longitude. The SDK methods could not send them, so every call was malformed. Both now take a params object and use the typed client. The CLI commands take the matching options. The CLI table view for t49 containers route lists the route's ports in order: sequence, POL/POD/TS label, name, country, and arrival and departure times. BREAKING CHANGE: vessels.futurePositions(id, options) is now futurePositions(id, { portId, previousPortId }, options), and futurePositionsWithCoords(id, options) is now futurePositionsWithCoords(id, { portId, previousPortId, latitude, longitude }, options). The getVesselFuturePositions* client methods change the same way. The CLI commands vessels future-positions and future-positions-coords now require --port-id and --previous-port-id, and the coords command also requires --latitude and --longitude. Co-Authored-By: Claude Opus 5.5 --- .../src/commands/containers.ts | 2 +- .../src/commands/vessels.ts | 75 ++++++++++---- sdks/typescript-sdk-cli/src/output/table.ts | 43 ++++---- sdks/typescript-sdk-cli/src/util/input.ts | 10 ++ .../test/regression.test.ts | 98 ++++++++++++++++++- sdks/typescript-sdk-cli/test/table.test.ts | 38 +++++++ sdks/typescript-sdk/src/client.ts | 72 +++++++++++--- .../src/client.write-endpoints.test.ts | 31 +++++- 8 files changed, 309 insertions(+), 60 deletions(-) diff --git a/sdks/typescript-sdk-cli/src/commands/containers.ts b/sdks/typescript-sdk-cli/src/commands/containers.ts index f16dc483..90966ca6 100644 --- a/sdks/typescript-sdk-cli/src/commands/containers.ts +++ b/sdks/typescript-sdk-cli/src/commands/containers.ts @@ -1,7 +1,7 @@ /** * t49 containers * - * Subcommands: get, list, events, route, raw-events, refresh, demurrage, rail + * Subcommands: get, list, events, route, map (alias of route), raw-events, refresh, demurrage, rail */ import type { Command } from 'commander'; diff --git a/sdks/typescript-sdk-cli/src/commands/vessels.ts b/sdks/typescript-sdk-cli/src/commands/vessels.ts index f4f02e6c..fcbf62c5 100644 --- a/sdks/typescript-sdk-cli/src/commands/vessels.ts +++ b/sdks/typescript-sdk-cli/src/commands/vessels.ts @@ -3,8 +3,19 @@ */ import type { Command } from 'commander'; +import { finiteNumber } from '../util/input.js'; import { action } from './action.js'; +interface FuturePositionsOptions { + portId: string; + previousPortId: string; +} + +interface FuturePositionsCoordsOptions extends FuturePositionsOptions { + latitude: number; + longitude: number; +} + export function registerVesselsCommand(program: Command): void { const cmd = program .command('vessels') @@ -28,27 +39,53 @@ export function registerVesselsCommand(program: Command): void { ), ); - cmd + const futurePositionsCommand = cmd .command('future-positions ') - .description('Get vessel future positions') - .action( - action( - 'vessels.future-positions', - async ({ client, globals }, id: string) => - client.vessels.futurePositions(id, { format: globals.format }), - ), - ); + .description('Get vessel future positions between two ports') + .requiredOption('--port-id ', 'Destination port id') + .requiredOption('--previous-port-id ', 'Port the vessel departed from'); + futurePositionsCommand.action( + action( + 'vessels.future-positions', + async ({ client, globals }, id: string) => { + const { portId, previousPortId } = + futurePositionsCommand.opts(); + return client.vessels.futurePositions( + id, + { portId, previousPortId }, + { format: globals.format }, + ); + }, + ), + ); - cmd + const futurePositionsCoordsCommand = cmd .command('future-positions-coords ') - .description('Get vessel future positions with coordinates') - .action( - action( - 'vessels.future-positions-coords', - async ({ client, globals }, id: string) => - client.vessels.futurePositionsWithCoords(id, { - format: globals.format, - }), - ), + .description('Get vessel future positions from a starting coordinate') + .requiredOption('--port-id ', 'Destination port id') + .requiredOption('--previous-port-id ', 'Port the vessel departed from') + .requiredOption( + '--latitude ', + 'Starting latitude', + finiteNumber('--latitude'), + ) + .requiredOption( + '--longitude ', + 'Starting longitude', + finiteNumber('--longitude'), ); + futurePositionsCoordsCommand.action( + action( + 'vessels.future-positions-coords', + async ({ client, globals }, id: string) => { + const { portId, previousPortId, latitude, longitude } = + futurePositionsCoordsCommand.opts(); + return client.vessels.futurePositionsWithCoords( + id, + { portId, previousPortId, latitude, longitude }, + { format: globals.format }, + ); + }, + ), + ); } diff --git a/sdks/typescript-sdk-cli/src/output/table.ts b/sdks/typescript-sdk-cli/src/output/table.ts index 04fd6483..bebda6cc 100644 --- a/sdks/typescript-sdk-cli/src/output/table.ts +++ b/sdks/typescript-sdk-cli/src/output/table.ts @@ -13,6 +13,17 @@ interface ColumnDef { title: string; } +const ROUTE_PORT_COLUMNS: ColumnDef[] = [ + { key: 'sequence', title: 'Seq' }, + { key: 'label', title: 'Label' }, + { key: 'name', title: 'Port' }, + { key: 'countryCode', title: 'Country' }, + { key: 'inbound.eta', title: 'Inbound ETA' }, + { key: 'inbound.ata', title: 'Inbound ATA' }, + { key: 'outbound.etd', title: 'Outbound ETD' }, + { key: 'outbound.atd', title: 'Outbound ATD' }, +]; + const commandColumns: Record = { 'shipments.list': [ { key: 'id', title: 'ID' }, @@ -51,21 +62,8 @@ const commandColumns: Record = { { key: ['dataSource', 'attributes.data_source'], title: 'Source' }, { key: ['value', 'attributes.value'], title: 'Value' }, ], - 'containers.route': [ - { key: ['port.name', 'port.code', 'location.name'], title: 'Port' }, - { key: ['inbound.mode', 'attributes.inbound_mode'], title: 'Inbound' }, - { key: ['inbound.eta', 'attributes.inbound_eta_at'], title: 'Inbound ETA' }, - { key: ['inbound.ata', 'attributes.inbound_ata_at'], title: 'Inbound ATA' }, - { key: ['outbound.mode', 'attributes.outbound_mode'], title: 'Outbound' }, - { - key: ['outbound.etd', 'attributes.outbound_etd_at'], - title: 'Outbound ETD', - }, - { - key: ['outbound.atd', 'attributes.outbound_atd_at'], - title: 'Outbound ATD', - }, - ], + 'containers.route': ROUTE_PORT_COLUMNS, + 'containers.map': ROUTE_PORT_COLUMNS, 'containers.demurrage': [ { key: 'container_id', title: 'Container ID' }, { key: 'pickup_lfd', title: 'Pickup LFD' }, @@ -590,15 +588,14 @@ function rowsForCommand( return record.mapped as Record[]; } - if (command === 'containers.route') { + if (command === 'containers.route' || command === 'containers.map') { const mapped = record?.mapped; - if (mapped && typeof mapped === 'object' && !Array.isArray(mapped)) { - const locations = (mapped as Record).locations; - if (Array.isArray(locations)) - return locations as Record[]; - } - if (Array.isArray(record?.locations)) { - return record.locations as Record[]; + const route = + mapped && typeof mapped === 'object' && !Array.isArray(mapped) + ? (mapped as Record) + : record; + if (Array.isArray(route?.ports)) { + return route.ports as Record[]; } } diff --git a/sdks/typescript-sdk-cli/src/util/input.ts b/sdks/typescript-sdk-cli/src/util/input.ts index 9c447e1d..b29f696d 100644 --- a/sdks/typescript-sdk-cli/src/util/input.ts +++ b/sdks/typescript-sdk-cli/src/util/input.ts @@ -44,3 +44,13 @@ export function positiveInt(name: string) { return parsed; }; } + +export function finiteNumber(name: string) { + return (value: string): number => { + const parsed = Number(value); + if (value.trim() === '' || !Number.isFinite(parsed)) { + throw new InvalidArgumentError(`${name} must be a number`); + } + return parsed; + }; +} diff --git a/sdks/typescript-sdk-cli/test/regression.test.ts b/sdks/typescript-sdk-cli/test/regression.test.ts index 81c15096..895462c1 100644 --- a/sdks/typescript-sdk-cli/test/regression.test.ts +++ b/sdks/typescript-sdk-cli/test/regression.test.ts @@ -3,7 +3,7 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { AuthenticationError, NetworkError } from '@terminal49/sdk'; import { Command, InvalidArgumentError } from 'commander'; -import { afterEach, describe, expect, it } from 'vite-plus/test'; +import { afterEach, describe, expect, it, vi } from 'vite-plus/test'; import { listFilters } from '../src/commands/tracking-requests.js'; import { getExitCode } from '../src/errors.js'; import { createProgram } from '../src/index.js'; @@ -21,6 +21,7 @@ class ProcessExit extends Error { } afterEach(() => { + vi.unstubAllGlobals(); restoreEnv('T49_API_TOKEN', originalEnv.T49_API_TOKEN); restoreEnv('T49_API_BASE_URL', originalEnv.T49_API_BASE_URL); restoreEnv('XDG_CONFIG_HOME', originalEnv.XDG_CONFIG_HOME); @@ -176,4 +177,99 @@ describe('CLI regressions', () => { }; expect('__cliEnvelope' in jsonApi).toBe(false); }); + + it('vessels future-positions requires both port ids', async () => { + process.env.T49_API_TOKEN = 'token-123'; + const result = await runProgram([ + '--json', + 'vessels', + 'future-positions', + 'v-1', + '--port-id', + 'port-2', + ]); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain( + "required option '--previous-port-id ' not specified", + ); + }); + + it('vessels future-positions-coords rejects a non-numeric latitude', async () => { + process.env.T49_API_TOKEN = 'token-123'; + const result = await runProgram([ + '--json', + 'vessels', + 'future-positions-coords', + 'v-1', + '--port-id', + 'port-2', + '--previous-port-id', + 'port-1', + '--latitude', + 'north', + '--longitude', + '-100.84', + ]); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain('--latitude must be a number'); + }); + + it('vessels future-positions-coords sends the spec query params', async () => { + const urls: string[] = []; + vi.stubGlobal('fetch', async (input: Request | URL | string) => { + urls.push(input instanceof Request ? input.url : String(input)); + return new Response(JSON.stringify({ data: null }), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + }); + process.env.T49_API_TOKEN = 'token-123'; + process.env.T49_API_BASE_URL = 'https://api.test/v2'; + process.env.XDG_CONFIG_HOME = mkdtempSync(join(tmpdir(), 't49-cli-')); + + const result = await runProgram([ + '--json', + 'vessels', + 'future-positions-coords', + 'v-1', + '--port-id', + 'port-2', + '--previous-port-id', + 'port-1', + '--latitude', + '13.07', + '--longitude', + '-100.84', + ]); + + expect(result.status).toBe(0); + expect(urls).toEqual([ + 'https://api.test/v2/vessels/v-1/future_positions_with_coordinates?port_id=port-2&previous_port_id=port-1&latitude=13.07&longitude=-100.84', + ]); + }); + + it('containers route and its map alias both read map_geojson', async () => { + const paths: string[] = []; + vi.stubGlobal('fetch', async (input: Request | URL | string) => { + paths.push( + new URL(input instanceof Request ? input.url : String(input)).pathname, + ); + return new Response( + JSON.stringify({ type: 'FeatureCollection', features: [] }), + { status: 200, headers: { 'Content-Type': 'application/json' } }, + ); + }); + process.env.T49_API_TOKEN = 'token-123'; + process.env.T49_API_BASE_URL = 'https://api.test/v2'; + process.env.XDG_CONFIG_HOME = mkdtempSync(join(tmpdir(), 't49-cli-')); + + const route = await runProgram(['--json', 'containers', 'route', 'c-1']); + const map = await runProgram(['--json', 'containers', 'map', 'c-1']); + + expect([route.status, map.status]).toEqual([0, 0]); + expect(paths).toEqual([ + '/v2/containers/c-1/map_geojson', + '/v2/containers/c-1/map_geojson', + ]); + }); }); diff --git a/sdks/typescript-sdk-cli/test/table.test.ts b/sdks/typescript-sdk-cli/test/table.test.ts index 94b18a56..bf2162ce 100644 --- a/sdks/typescript-sdk-cli/test/table.test.ts +++ b/sdks/typescript-sdk-cli/test/table.test.ts @@ -114,4 +114,42 @@ describe('renderTable', () => { expect(output).toContain('in_transit'); expect(output).toContain('unknown'); }); + + it('renders route ports in order for containers route and map', () => { + const route = { + ports: [ + { + sequence: 1, + label: 'POL', + name: 'Laem Chabang', + countryCode: 'TH', + inbound: { eta: null, ata: null }, + outbound: { etd: null, atd: '2025-11-08T00:44:52Z' }, + }, + { + sequence: 3, + label: 'POD', + name: 'Savannah', + countryCode: 'US', + inbound: { eta: '2025-12-31T05:00:00Z', ata: null }, + outbound: { etd: null, atd: null }, + }, + ], + currentVessel: null, + totalPorts: 2, + }; + + for (const command of ['containers.route', 'containers.map']) { + const lines = renderTable(command, route).split('\n'); + const header = lines.find((line) => line.includes('Seq')); + expect(header).toMatch( + /Seq.*Label.*Port.*Country.*Inbound ETA.*Inbound ATA.*Outbound ETD.*Outbound ATD/, + ); + const pol = lines.findIndex((line) => line.includes('Laem Chabang')); + const pod = lines.findIndex((line) => line.includes('Savannah')); + expect(lines[pol]).toMatch(/1.*POL.*Laem Chabang.*TH.*2025-11-08/); + expect(lines[pod]).toMatch(/3.*POD.*Savannah.*US.*2025-12-31/); + expect(pol).toBeLessThan(pod); + } + }); }); diff --git a/sdks/typescript-sdk/src/client.ts b/sdks/typescript-sdk/src/client.ts index 421e77df..781fedd8 100644 --- a/sdks/typescript-sdk/src/client.ts +++ b/sdks/typescript-sdk/src/client.ts @@ -78,6 +78,27 @@ type CustomFieldDefinitionAttributes = NonNullable< JsonBody['data'] >['attributes']; +type FuturePositionsQuery = + paths['/vessels/{id}/future_positions']['get']['parameters']['query']; +type FuturePositionsWithCoordsQuery = + paths['/vessels/{id}/future_positions_with_coordinates']['get']['parameters']['query']; + +/** Parameters for {@link Terminal49Client.getVesselFuturePositions}. */ +export interface VesselFuturePositionsParams { + /** Destination port ID. */ + portId: FuturePositionsQuery['port_id']; + /** ID of the port the vessel left before heading to `portId`. */ + previousPortId: FuturePositionsQuery['previous_port_id']; +} + +/** Parameters for {@link Terminal49Client.getVesselFuturePositionsWithCoords}. */ +export interface VesselFuturePositionsWithCoordsParams extends VesselFuturePositionsParams { + /** Starting latitude. */ + latitude: FuturePositionsWithCoordsQuery['latitude']; + /** Starting longitude. */ + longitude: FuturePositionsWithCoordsQuery['longitude']; +} + /** Parameters for {@link Terminal49Client.triggerWebhook}. */ export interface TriggerWebhookParams { /** HTTPS destination URL for the test delivery. */ @@ -191,10 +212,16 @@ export class Terminal49Client { get: (id: string, options?: CallOptions) => this.getVessel(id, options), getByImo: (imo: string, options?: CallOptions) => this.getVesselByImo(imo, options), - futurePositions: (id: string, options?: CallOptions) => - this.getVesselFuturePositions(id, options), - futurePositionsWithCoords: (id: string, options?: CallOptions) => - this.getVesselFuturePositionsWithCoords(id, options), + futurePositions: ( + id: string, + params: VesselFuturePositionsParams, + options?: CallOptions, + ) => this.getVesselFuturePositions(id, params, options), + futurePositionsWithCoords: ( + id: string, + params: VesselFuturePositionsWithCoordsParams, + options?: CallOptions, + ) => this.getVesselFuturePositionsWithCoords(id, params, options), }; public ports = { @@ -670,26 +697,47 @@ export class Terminal49Client { return this.formatResult(raw, options?.format); } - /** Fetch future vessel positions. */ + /** Fetch a vessel's estimated positions between two ports. Requires the Routing Data feature. */ async getVesselFuturePositions( id: string, + params: VesselFuturePositionsParams, options?: CallOptions, ): Promise { - // The spec marks port_id and previous_port_id required; this signature never accepted them. - const raw = await this.transport.executeManual( - `${this.transport.baseUrl}/vessels/${encodeURIComponent(id)}/future_positions`, + const raw = await this.transport.execute(() => + this.transport.client.GET('/vessels/{id}/future_positions', { + params: { + path: { id }, + query: { + port_id: params.portId, + previous_port_id: params.previousPortId, + }, + }, + }), ); return this.formatResult(raw, options?.format); } - /** Fetch future vessel positions with coordinates. */ + /** Fetch a vessel's estimated positions from a starting coordinate. Requires the Routing Data feature. */ async getVesselFuturePositionsWithCoords( id: string, + params: VesselFuturePositionsWithCoordsParams, options?: CallOptions, ): Promise { - // The spec marks port and coordinate params required; this signature never accepted them. - const raw = await this.transport.executeManual( - `${this.transport.baseUrl}/vessels/${encodeURIComponent(id)}/future_positions_with_coordinates`, + const raw = await this.transport.execute(() => + this.transport.client.GET( + '/vessels/{id}/future_positions_with_coordinates', + { + params: { + path: { id }, + query: { + port_id: params.portId, + previous_port_id: params.previousPortId, + latitude: params.latitude, + longitude: params.longitude, + }, + }, + }, + ), ); return this.formatResult(raw, options?.format); } diff --git a/sdks/typescript-sdk/src/client.write-endpoints.test.ts b/sdks/typescript-sdk/src/client.write-endpoints.test.ts index 4cb62ed2..42091d45 100644 --- a/sdks/typescript-sdk/src/client.write-endpoints.test.ts +++ b/sdks/typescript-sdk/src/client.write-endpoints.test.ts @@ -346,8 +346,16 @@ describe('resource methods on the client', () => { await client.webhookNotifications.examples(); await client.vessels.get('v-1'); await client.vessels.getByImo('9876543'); - await client.vessels.futurePositions('v-1'); - await client.vessels.futurePositionsWithCoords('v-1'); + await client.vessels.futurePositions('v-1', { + portId: 'port-2', + previousPortId: 'port-1', + }); + await client.vessels.futurePositionsWithCoords('v-1', { + portId: 'port-2', + previousPortId: 'port-1', + latitude: 13.07, + longitude: -100.84, + }); await client.ports.get('p-1'); await client.terminals.get('t-1'); await client.parties.list({ pageSize: 10 }); @@ -390,8 +398,23 @@ describe('resource methods on the client', () => { ['GET', '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/webhook_notifications/examples', {}, undefined], ['GET', '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/vessels/v-1', {}, undefined], ['GET', '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/vessels/9876543', {}, undefined], - ['GET', '/vessels/v-1/future_positions', {}, undefined], - ['GET', '/vessels/v-1/future_positions_with_coordinates', {}, undefined], + [ + 'GET', + '/vessels/v-1/future_positions', + { port_id: 'port-2', previous_port_id: 'port-1' }, + undefined, + ], + [ + 'GET', + '/vessels/v-1/future_positions_with_coordinates', + { + port_id: 'port-2', + previous_port_id: 'port-1', + latitude: '13.07', + longitude: '-100.84', + }, + undefined, + ], ['GET', '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/ports/p-1', {}, undefined], ['GET', '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/terminals/t-1', {}, undefined], ['GET', '/parties', { 'page[size]': '10' }, undefined], From f428415e2aec8924e63e91428633ce52a0bdc246 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 14:03:57 -0700 Subject: [PATCH 08/14] feat(mcp): build get_container_route from the map_geojson route get_container_route read the JSON:API document of the retired GET /containers/{id}/route endpoint, so it could only return NotFound. It now calls client.containers.route(id, { format: 'mapped' }) and builds its output from the SDK's ContainerRoute: ports in order with POL/POD/TS label, country code, ETA/ATA and ETD/ATD, plus the current vessel's name, IMO, voyage, position, heading, speed and its departure and arrival ports. Track geometry stays out of the output to keep the model's context small. Fields map_geojson cannot source (route_id, port code and city, mode, carrier SCAC, per-leg vessels) are dropped from the output schema. The schema now lives beside the formatter and the formatter's return type is inferred from it, so the two cannot drift. An empty FeatureCollection returns a NoRouteData soft result. The feature-gate message points to sales@terminal49.com, as the spec does. The unused getContainerRouteTool descriptor is removed. Tests and the live eval use the spec-example fixture; the eval now fails on NotFound for a known container instead of accepting any soft error. Co-Authored-By: Claude Opus 5.5 --- packages/mcp/eval/tools.eval.ts | 13 +- packages/mcp/src/server.ts | 60 +--- packages/mcp/src/test/route-fixture.ts | 53 ++++ packages/mcp/src/tool-transport.test.ts | 61 +--- packages/mcp/src/tools/contracts.test.ts | 85 +++--- packages/mcp/src/tools/get-container-route.ts | 269 ++++++++---------- 6 files changed, 240 insertions(+), 301 deletions(-) create mode 100644 packages/mcp/src/test/route-fixture.ts diff --git a/packages/mcp/eval/tools.eval.ts b/packages/mcp/eval/tools.eval.ts index 077890d6..a7fe2839 100644 --- a/packages/mcp/eval/tools.eval.ts +++ b/packages/mcp/eval/tools.eval.ts @@ -323,7 +323,7 @@ if (!cfg) { expect(score.contractPass).toBe(true); }); - it('get_container_route returns route data or a graceful not-found', async ({ + it('get_container_route returns ports or an explained gate', async ({ skip, }) => { if (!fixtures.containerId) return skip(); @@ -333,16 +333,17 @@ if (!cfg) { { predicates: [ { - name: 'route payload or explained not-found', + name: 'route payload, feature gate, or no route data yet', test: (p) => isRecord(p) && - (Array.isArray(p.route_locations) || - 'total_legs' in p || - (typeof p.error === 'string' && + ((Array.isArray(p.ports) && + typeof p.total_ports === 'number') || + ((p.error === 'FeatureNotEnabled' || + p.error === 'NoRouteData') && typeof p.alternative === 'string')), detail: (p) => isRecord(p) && typeof p.error === 'string' - ? 'graceful not-found' + ? `soft error ${p.error}` : 'route data', }, ], diff --git a/packages/mcp/src/server.ts b/packages/mcp/src/server.ts index 3e38bf6e..5d9147ef 100644 --- a/packages/mcp/src/server.ts +++ b/packages/mcp/src/server.ts @@ -17,6 +17,7 @@ import { executeGetShipmentDetails } from './tools/get-shipment-details.js'; import { executeGetContainerTransportEvents } from './tools/get-container-transport-events.js'; import { executeGetSupportedShippingLines } from './tools/get-supported-shipping-lines.js'; import { + routeSummaryOrSoftErrorSchema, executeGetContainerRoute, type FeatureNotEnabledResult, } from './tools/get-container-route.js'; @@ -99,7 +100,7 @@ Domain vocabulary: SCAC = 4-letter carrier code; BOL = bill of lading and bookin Only track_container changes Terminal49 account records: it creates a tracking request to begin monitoring a number and is marked non-read-only. The other tools only fetch data and are marked read-only. All tools except search_docs operate within the user's private Terminal49 account; search_docs searches the public Terminal49 documentation. None delete or overwrite data. -Canonical chaining: start with search_container to resolve a container number / BOL / reference into Terminal49 UUIDs, then get_container or get_shipment_details for a snapshot, then get_container_transport_events for the milestone timeline (and get_container_route for multi-leg routing if the account has it). Use get_supported_shipping_lines to resolve a carrier name to its SCAC before track_container. Use list_parties to resolve a company name (customer, shipper, dray carrier) to a party ID before filtering containers by advanced_filters.parties. Use list_containers / list_shipments / list_tracking_requests for fleet-level worklists. Use search_docs for how-to and API questions (webhooks, statuses, LFD rules, SDK, MCP) and cite the returned links.`; +Canonical chaining: start with search_container to resolve a container number / BOL / reference into Terminal49 UUIDs, then get_container or get_shipment_details for a snapshot, then get_container_transport_events for the milestone timeline (and get_container_route for ports, ETAs, and the current vessel if the account has Routing Data). Use get_supported_shipping_lines to resolve a carrier name to its SCAC before track_container. Use list_parties to resolve a company name (customer, shipper, dray carrier) to a party ID before filtering containers by advanced_filters.parties. Use list_containers / list_shipments / list_tracking_requests for fleet-level worklists. Use search_docs for how-to and API questions (webhooks, statuses, LFD rules, SDK, MCP) and cite the returned links.`; type ResponseDisplayColumn = { key: string; @@ -1328,9 +1329,9 @@ export function createTerminal49McpServer( { title: 'Get Container Route', description: - 'Get detailed routing and vessel itinerary for a container including all ports, vessels, and ETAs. ' + - 'Shows complete multi-leg journey (origin → transshipment ports → destination). ' + - 'This paid feature may not be available for every account.', + 'Get the ocean route for a container: ports in order (POL, transshipment ports, POD) with ETA/ATA and ETD/ATD, ' + + 'plus the vessel carrying it now (name, IMO, voyage, position, speed) while it is at sea. ' + + 'This paid feature (Routing Data) may not be available for every account.', annotations: { readOnlyHint: true, destructiveHint: false, @@ -1342,56 +1343,7 @@ export function createTerminal49McpServer( .uuid() .describe('The Terminal49 container ID (UUID format)'), }), - // Keep a single permissive schema because this tool can return either - // route fields or feature-gating fields depending on account capability. - outputSchema: z.object({ - route_id: z.string().optional(), - total_legs: z.number().optional(), - route_locations: z - .array( - z.object({ - port: z - .object({ - code: z.string().nullable().optional(), - name: z.string().nullable().optional(), - city: z.string().nullable().optional(), - country_code: z.string().nullable().optional(), - }) - .nullable(), - inbound: z.object({ - mode: z.string().nullable().optional(), - carrier_scac: z.string().nullable().optional(), - eta: z.string().nullable().optional(), - ata: z.string().nullable().optional(), - vessel: z - .object({ - name: z.string().nullable().optional(), - imo: z.string().nullable().optional(), - }) - .nullable(), - }), - outbound: z.object({ - mode: z.string().nullable().optional(), - carrier_scac: z.string().nullable().optional(), - etd: z.string().nullable().optional(), - atd: z.string().nullable().optional(), - vessel: z - .object({ - name: z.string().nullable().optional(), - imo: z.string().nullable().optional(), - }) - .nullable(), - }), - }), - ) - .optional(), - created_at: z.string().nullable().optional(), - updated_at: z.string().nullable().optional(), - // Feature gating / errors - error: z.string().optional(), - message: z.string().optional(), - alternative: z.string().optional(), - }), + outputSchema: routeSummaryOrSoftErrorSchema, }, wrapTool('get_container_route', async ({ id }) => executeGetContainerRoute({ id }, client), diff --git a/packages/mcp/src/test/route-fixture.ts b/packages/mcp/src/test/route-fixture.ts new file mode 100644 index 00000000..be594eb1 --- /dev/null +++ b/packages/mcp/src/test/route-fixture.ts @@ -0,0 +1,53 @@ +import { readFileSync } from 'node:fs'; +import type { RouteSummary } from '../tools/get-container-route.js'; + +export const routeFixture = JSON.parse( + readFileSync( + new URL( + '../../../../sdks/typescript-sdk/src/fixtures/containers.map_geojson.json', + import.meta.url, + ), + 'utf8', + ), +); + +export const EXPECTED_ROUTE_SUMMARY: RouteSummary = { + total_ports: 3, + ports: [ + { + sequence: 1, + label: 'POL', + name: 'Laem Chabang', + country_code: 'TH', + inbound: { eta: null, ata: null }, + outbound: { etd: null, atd: '2025-11-08T00:44:52Z' }, + }, + { + sequence: 2, + label: 'TS1', + name: 'Xiamen', + country_code: 'CN', + inbound: { eta: null, ata: '2025-11-15T16:00:00Z' }, + outbound: { etd: null, atd: '2025-11-19T16:00:00Z' }, + }, + { + sequence: 3, + label: 'POD', + name: 'Savannah', + country_code: 'US', + inbound: { eta: '2025-12-31T05:00:00Z', ata: null }, + outbound: { etd: null, atd: null }, + }, + ], + current_vessel: { + name: 'ZIM BANGKOK', + imo: '9936525', + voyage: '13E', + latitude: 31.023033333, + longitude: -131.128473333, + heading: 108, + speed_knots: 21, + departure_port: { name: 'Xiamen', label: 'TS1' }, + arrival_port: { name: 'Savannah', label: 'POD' }, + }, +}; diff --git a/packages/mcp/src/tool-transport.test.ts b/packages/mcp/src/tool-transport.test.ts index b288f952..de387fed 100644 --- a/packages/mcp/src/tool-transport.test.ts +++ b/packages/mcp/src/tool-transport.test.ts @@ -4,7 +4,9 @@ import { } from '@modelcontextprotocol/client'; import { createMcpHandler } from '@modelcontextprotocol/server'; import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'; +import { mapContainerRoute } from '@terminal49/sdk'; import { createTerminal49McpServer } from './server.js'; +import { EXPECTED_ROUTE_SUMMARY, routeFixture } from './test/route-fixture.js'; vi.mock('@sentry/node', () => ({ captureException: vi.fn(), @@ -27,7 +29,9 @@ const sdk = vi.hoisted(() => ({ trackingRequestsList: vi.fn(), })); -vi.mock('@terminal49/sdk', () => ({ +vi.mock('@terminal49/sdk', async (importOriginal) => ({ + mapContainerRoute: (await importOriginal()) + .mapContainerRoute, Terminal49Client: class Terminal49Client { search = sdk.search; createTrackingRequestFromInfer = sdk.createTrackingRequestFromInfer; @@ -184,49 +188,6 @@ function eventsRaw() { }; } -function routeRaw() { - return { - data: { - id: 'route-1', - type: 'route', - attributes: { - created_at: '2026-07-01T00:00:00Z', - updated_at: '2026-08-21T05:00:00Z', - }, - relationships: { - route_locations: { - data: [{ id: 'route-location-1', type: 'route_location' }], - }, - }, - }, - included: [ - { - id: 'route-location-1', - type: 'route_location', - attributes: { - inbound_mode: 'vessel', - inbound_scac: 'MAEU', - inbound_eta_at: '2026-08-18T10:00:00Z', - outbound_mode: 'truck', - }, - relationships: { - port: { data: { id: 'port-1', type: 'port' } }, - }, - }, - { - id: 'port-1', - type: 'port', - attributes: { - code: 'USLAX', - name: 'Los Angeles', - city: 'Los Angeles', - country_code: 'US', - }, - }, - ], - }; -} - async function connectClient() { const handler = createMcpHandler( () => createTerminal49McpServer('fixture-token', 'https://api.test'), @@ -295,7 +256,7 @@ function configureHappyPath(toolName: ToolName): void { ]); return; case 'get_container_route': - sdk.containersRoute.mockResolvedValue({ raw: routeRaw() }); + sdk.containersRoute.mockResolvedValue(mapContainerRoute(routeFixture)); return; case 'list_shipments': sdk.shipmentsList.mockResolvedValue({ @@ -435,15 +396,7 @@ function expectedOutputFor(toolName: ToolName): Record { ], }; case 'get_container_route': - return { - route_id: 'route-1', - total_legs: 1, - route_locations: [ - expect.objectContaining({ - port: expect.objectContaining({ code: 'USLAX' }), - }), - ], - }; + return EXPECTED_ROUTE_SUMMARY; case 'list_shipments': return { items: [ diff --git a/packages/mcp/src/tools/contracts.test.ts b/packages/mcp/src/tools/contracts.test.ts index 64d55a42..b4df8adf 100644 --- a/packages/mcp/src/tools/contracts.test.ts +++ b/packages/mcp/src/tools/contracts.test.ts @@ -1,5 +1,6 @@ import { FeatureNotEnabledError, + mapContainerRoute, NotFoundError, type Terminal49Client, } from '@terminal49/sdk'; @@ -14,6 +15,7 @@ import { executeListTrackingRequests } from './list-tracking-requests.js'; import { executeSearchContainer } from './search-container.js'; import { executeTrackContainer } from './track-container.js'; import { buildListContract } from '../server.js'; +import { EXPECTED_ROUTE_SUMMARY, routeFixture } from '../test/route-fixture.js'; function asClient(client: unknown): Terminal49Client { return client as Terminal49Client; @@ -992,49 +994,45 @@ describe('MCP tool contracts', () => { expect(resultB.shipping_lines[0]?.scac).toBe('MAEU'); }); - it('get_container_route returns route summary when route data exists', async () => { - const route = vi.fn().mockResolvedValue({ - raw: { - data: { - id: 'route-1', - type: 'route', - attributes: { - created_at: '2025-01-01T00:00:00Z', - updated_at: '2025-01-02T00:00:00Z', - }, - relationships: { - route_locations: { - data: [{ id: 'rl-1', type: 'route_location' }], - }, - }, - }, - included: [ - { - id: 'rl-1', - type: 'route_location', - attributes: { - inbound_mode: 'vessel', - outbound_mode: 'vessel', - }, - relationships: { - port: { data: { id: 'port-1', type: 'port' } }, - }, - }, - { - id: 'port-1', - type: 'port', - attributes: { - code: 'USLAX', - name: 'Los Angeles', - }, - }, - ], + it('get_container_route summarizes ports, ETAs, and the current vessel', async () => { + const route = vi.fn().mockResolvedValue(mapContainerRoute(routeFixture)); + const client = asClient({ containers: { route } }); + + const result = await executeGetContainerRoute( + { id: 'container-1' }, + client, + ); + + expect(route).toHaveBeenCalledWith('container-1', { format: 'mapped' }); + expect(result).toEqual(EXPECTED_ROUTE_SUMMARY); + }); + + it('get_container_route returns a NoRouteData soft result for an empty route', async () => { + const client = asClient({ + containers: { + route: vi + .fn() + .mockResolvedValue( + mapContainerRoute({ type: 'FeatureCollection', features: [] }), + ), }, - mapped: { id: 'route-1' }, }); + + const result = await executeGetContainerRoute( + { id: 'container-1' }, + client, + ); + + expect(result).toMatchObject({ + error: 'NoRouteData', + alternative: expect.stringContaining('get_container_transport_events'), + }); + }); + + it('get_container_route returns a NotFound soft result for an unknown container', async () => { const client = asClient({ containers: { - route, + route: vi.fn().mockRejectedValue(new NotFoundError('not found')), }, }); @@ -1043,10 +1041,10 @@ describe('MCP tool contracts', () => { client, ); - expect(result.route_id).toBe('route-1'); - expect(result.total_legs).toBe(1); - expect(result.route_locations[0].port).toMatchObject({ code: 'USLAX' }); - expect(route).toHaveBeenCalledWith('container-1', { format: 'raw' }); + expect(result).toMatchObject({ + error: 'NotFound', + alternative: expect.stringContaining('search_container'), + }); }); it('get_container_route returns feature-not-enabled contract instead of throwing', async () => { @@ -1065,6 +1063,7 @@ describe('MCP tool contracts', () => { expect(result).toMatchObject({ error: 'FeatureNotEnabled', + message: expect.stringContaining('sales@terminal49.com'), alternative: expect.stringContaining('get_container_transport_events'), }); }); diff --git a/packages/mcp/src/tools/get-container-route.ts b/packages/mcp/src/tools/get-container-route.ts index 902e4fd9..6bcc80ad 100644 --- a/packages/mcp/src/tools/get-container-route.ts +++ b/packages/mcp/src/tools/get-container-route.ts @@ -1,14 +1,10 @@ -/** - * get_container_route tool - * Retrieves detailed routing information for a container - * NOTE: This is a PAID FEATURE in Terminal49 API - */ - import { FeatureNotEnabledError, NotFoundError, Terminal49Client, + type ContainerRoute, } from '@terminal49/sdk'; +import { z } from 'zod'; import { logMcpEvent } from '../logging.js'; export interface FeatureNotEnabledResult { @@ -23,33 +19,69 @@ export interface NotFoundResult { alternative: string; } +export interface NoRouteDataResult { + error: 'NoRouteData'; + message: string; + alternative: string; +} + +type SoftError = FeatureNotEnabledResult | NotFoundResult | NoRouteDataResult; + export interface GetContainerRouteArgs { id: string; } -export const getContainerRouteTool = { - name: 'get_container_route', - description: - 'Get detailed routing and vessel itinerary for a container including all ports, vessels, and ETAs. ' + - 'Shows complete multi-leg journey (origin → transshipment ports → destination). ' + - 'NOTE: This is a paid feature and may not be available for all accounts. ' + - 'Use for questions about routing, transshipments, or detailed vessel itinerary.', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'string', - description: 'The Terminal49 container ID (UUID format)', - }, - }, - required: ['id'], - }, -}; +const portRefSchema = z + .object({ name: z.string().nullable(), label: z.string().nullable() }) + .nullable(); + +const routeSummarySchema = z.object({ + total_ports: z.number(), + ports: z.array( + z.object({ + sequence: z.number().nullable(), + label: z.string().nullable(), + name: z.string().nullable(), + country_code: z.string().nullable(), + inbound: z.object({ + eta: z.string().nullable(), + ata: z.string().nullable(), + }), + outbound: z.object({ + etd: z.string().nullable(), + atd: z.string().nullable(), + }), + }), + ), + current_vessel: z + .object({ + name: z.string().nullable(), + imo: z.string().nullable(), + voyage: z.string().nullable(), + latitude: z.number().nullable(), + longitude: z.number().nullable(), + heading: z.number().nullable(), + speed_knots: z.number().nullable(), + departure_port: portRefSchema, + arrival_port: portRefSchema, + }) + .nullable(), +}); + +export type RouteSummary = z.infer; + +export const routeSummaryOrSoftErrorSchema = routeSummarySchema + .partial() + .extend({ + error: z.string().optional(), + message: z.string().optional(), + alternative: z.string().optional(), + }); export async function executeGetContainerRoute( args: GetContainerRouteArgs, client: Terminal49Client, -): Promise { +): Promise { if (!args.id || args.id.trim() === '') { throw new Error('Container ID is required'); } @@ -63,12 +95,15 @@ export async function executeGetContainerRoute( }); try { - // The handler builds a curated route response entirely from JSON:API data; - // requesting the mapped representation as well only duplicates SDK work. - const result = await client.containers.route(args.id, { format: 'raw' }); - const raw = (result as any)?.raw ?? result; + const route: ContainerRoute = await client.containers.route(args.id, { + format: 'mapped', + }); const duration = Date.now() - startTime; + if (route.ports.length === 0 && route.currentVessel === null) { + return logSoftError(args.id, duration, NO_ROUTE_DATA); + } + logMcpEvent({ event: 'tool.execute.complete', tool: 'get_container_route', @@ -77,8 +112,7 @@ export async function executeGetContainerRoute( timestamp: new Date().toISOString(), }); - const summary = formatRouteResponse(raw); - return summary; + return formatRoute(route); } catch (error) { const duration = Date.now() - startTime; const err = error as any; @@ -87,11 +121,11 @@ export async function executeGetContainerRoute( err instanceof FeatureNotEnabledError || (err?.status === 403 && /not enabled|feature/i.test(err.message)) ) { - return handleFeatureNotEnabled(args.id, duration); + return logSoftError(args.id, duration, FEATURE_NOT_ENABLED); } if (err instanceof NotFoundError || err?.status === 404) { - return handleRouteNotFound(args.id, duration); + return logSoftError(args.id, duration, NOT_FOUND); } logMcpEvent({ @@ -108,132 +142,79 @@ export async function executeGetContainerRoute( } } -function handleFeatureNotEnabled( - containerId: string, - duration: number, -): FeatureNotEnabledResult { - const friendlyMessage = - 'Route tracking is a paid feature and is not enabled for this Terminal49 account. ' + - 'Contact support@terminal49.com to enable route data, or use get_container / get_container_transport_events for partial context.'; +const FEATURE_NOT_ENABLED: FeatureNotEnabledResult = { + error: 'FeatureNotEnabled', + message: + 'Route data is a paid feature (Routing Data) and is not enabled for this Terminal49 account. ' + + 'Contact sales@terminal49.com to enable it.', + alternative: + 'Use get_container_transport_events to see historical movement, or get_container for the POL, POD, and ETA.', +}; - logMcpEvent({ - event: 'tool.execute.error', - tool: 'get_container_route', - container_id: containerId, - error: 'FeatureNotEnabled', - message: friendlyMessage, - duration_ms: duration, - timestamp: new Date().toISOString(), - }); +const NOT_FOUND: NotFoundResult = { + error: 'NotFound', + message: + 'No container was found with this ID, so there is no route to return.', + alternative: + 'Use search_container to find the correct container ID, or get_container for basic details.', +}; - return { - error: 'FeatureNotEnabled', - message: friendlyMessage, - alternative: - 'Use get_container_transport_events to see historical movement, or get_container for basic routing info.', - }; -} +const NO_ROUTE_DATA: NoRouteDataResult = { + error: 'NoRouteData', + message: + 'Terminal49 has no route data for this container yet. This is common before the container is loaded on a vessel.', + alternative: + 'Use get_container_transport_events to see milestones so far, or get_container for the POL, POD, and ETA.', +}; -function handleRouteNotFound( +function logSoftError( containerId: string, duration: number, -): NotFoundResult { - const friendlyMessage = - 'Route data was not found for this container. The container ID may be incorrect or route data is unavailable.'; - + result: T, +): T { logMcpEvent({ event: 'tool.execute.error', tool: 'get_container_route', container_id: containerId, - error: 'NotFound', - message: friendlyMessage, + error: result.error, + message: result.message, duration_ms: duration, timestamp: new Date().toISOString(), }); - - return { - error: 'NotFound', - message: friendlyMessage, - alternative: - 'Use search_container to find the correct container ID, or get_container for basic details.', - }; + return { ...result }; } -function formatRouteResponse(apiResponse: any): any { - const route = apiResponse.data?.attributes || {}; - const relationships = apiResponse.data?.relationships || {}; - const included = apiResponse.included || []; - - // Extract route locations - const routeLocationRefs = relationships.route_locations?.data || []; - const routeLocations = routeLocationRefs - .map((ref: any) => { - const location = included.find( - (item: any) => item.id === ref.id && item.type === 'route_location', - ); - if (!location) return null; - - const attrs = location.attributes || {}; - const rels = location.relationships || {}; - - // Find port info - const portId = rels.port?.data?.id; - const port = included.find( - (item: any) => item.id === portId && item.type === 'port', - ); - - // Find vessel info - const inboundVesselId = rels.inbound_vessel?.data?.id; - const outboundVesselId = rels.outbound_vessel?.data?.id; - const inboundVessel = included.find( - (item: any) => item.id === inboundVesselId && item.type === 'vessel', - ); - const outboundVessel = included.find( - (item: any) => item.id === outboundVesselId && item.type === 'vessel', - ); - - return { - port: port - ? { - code: port.attributes?.code, - name: port.attributes?.name, - city: port.attributes?.city, - country_code: port.attributes?.country_code, - } - : null, - inbound: { - mode: attrs.inbound_mode, - carrier_scac: attrs.inbound_scac, - eta: attrs.inbound_eta_at, - ata: attrs.inbound_ata_at, - vessel: inboundVessel - ? { - name: inboundVessel.attributes?.name, - imo: inboundVessel.attributes?.imo, - } - : null, - }, - outbound: { - mode: attrs.outbound_mode, - carrier_scac: attrs.outbound_scac, - etd: attrs.outbound_etd_at, - atd: attrs.outbound_atd_at, - vessel: outboundVessel - ? { - name: outboundVessel.attributes?.name, - imo: outboundVessel.attributes?.imo, - } - : null, - }, - }; - }) - .filter((loc: any) => loc !== null); +function formatRoute({ + ports, + currentVessel, + totalPorts, +}: ContainerRoute): RouteSummary { + const portRef = (id: string | null) => { + const port = + id === null ? undefined : ports.find((p) => p.locationId === id); + return port ? { name: port.name, label: port.label } : null; + }; return { - route_id: apiResponse.data?.id, - total_legs: routeLocations.length, - route_locations: routeLocations, - created_at: route.created_at, - updated_at: route.updated_at, + total_ports: totalPorts, + ports: ports.map((port) => ({ + sequence: port.sequence, + label: port.label, + name: port.name, + country_code: port.countryCode, + inbound: port.inbound, + outbound: port.outbound, + })), + current_vessel: currentVessel && { + name: currentVessel.name, + imo: currentVessel.imo, + voyage: currentVessel.voyage, + latitude: currentVessel.coordinates?.latitude ?? null, + longitude: currentVessel.coordinates?.longitude ?? null, + heading: currentVessel.heading, + speed_knots: currentVessel.speed, + departure_port: portRef(currentVessel.departurePortId), + arrival_port: portRef(currentVessel.arrivalPortId), + }, }; } From 8746bb05c0aed61dd2a566e635fd93d6199ef868 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 11:02:02 -0700 Subject: [PATCH 09/14] docs: document the map_geojson route and vessel future-position params containers.route() / get_container_route now read GET /containers/{id}/map_geojson, and the vessel future-position methods take their required port and coordinate params. Update the SDK quickstart and methods page (new Vessels section), the MCP tool page (output fields, NoRouteData, REST equivalent map_geojson), the MCP guide table, the READMEs and TOOLS_OVERVIEW. Regenerate docs/sdk/reference and fix docs.json nav: drop the removed Route page, add ContainerRoute, RoutePort, RouteVessel, RouteCoordinates and the vessel params pages, plus the pages earlier commits on this branch added without a nav entry (document managers, custom field filters, TriggerWebhookParams). Co-Authored-By: Claude Opus 5.5 --- MCP_README.md | 2 +- docs/api-docs/in-depth-guides/mcp.mdx | 2 +- docs/docs.json | 19 +- docs/mcp/home.mdx | 15 +- docs/sdk/methods.mdx | 15 +- docs/sdk/quickstart.mdx | 5 +- .../client/classes/Terminal49Client.mdx | 109 +++++++- docs/sdk/reference/client/index.mdx | 5 + .../CustomFieldDefinitionListFilters.mdx | 15 ++ .../interfaces/CustomFieldListFilters.mdx | 15 ++ .../interfaces/TriggerWebhookParams.mdx | 16 ++ .../VesselFuturePositionsParams.mdx | 18 ++ .../VesselFuturePositionsWithCoordsParams.mdx | 20 ++ .../client/managers/classes/BaseManager.mdx | 3 + .../managers/classes/ContainerManager.mdx | 138 +++++++++- .../managers/classes/DocumentManager.mdx | 240 ++++++++++++++++++ .../classes/DocumentSchemaManager.mdx | 49 ++++ .../classes/EmailSubmissionManager.mdx | 67 +++++ .../managers/classes/ShipmentManager.mdx | 106 +++++++- .../managers/classes/ShippingLineManager.mdx | 19 ++ .../classes/TrackingRequestManager.mdx | 81 ++++++ docs/sdk/reference/client/managers/index.mdx | 7 + .../interfaces/CreateDocumentParams.mdx | 14 + .../interfaces/DocumentListFilters.mdx | 17 ++ .../interfaces/UpdateDocumentParams.mdx | 14 + .../type-aliases/DocumentRotation.mdx | 7 + docs/sdk/reference/types/models/index.mdx | 7 +- .../models/interfaces/ContainerRoute.mdx | 15 ++ .../types/models/interfaces/Route.mdx | 18 -- .../models/interfaces/RouteCoordinates.mdx | 14 + .../types/models/interfaces/RoutePort.mdx | 24 ++ .../types/models/interfaces/RouteVessel.mdx | 20 ++ packages/mcp/README.md | 2 +- packages/mcp/TOOLS_OVERVIEW.md | 23 +- sdks/typescript-sdk-cli/README.md | 4 +- sdks/typescript-sdk/README.md | 4 +- 36 files changed, 1089 insertions(+), 60 deletions(-) create mode 100644 docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx create mode 100644 docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx create mode 100644 docs/sdk/reference/client/interfaces/TriggerWebhookParams.mdx create mode 100644 docs/sdk/reference/client/interfaces/VesselFuturePositionsParams.mdx create mode 100644 docs/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams.mdx create mode 100644 docs/sdk/reference/client/managers/classes/DocumentManager.mdx create mode 100644 docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx create mode 100644 docs/sdk/reference/client/managers/classes/EmailSubmissionManager.mdx create mode 100644 docs/sdk/reference/client/managers/interfaces/CreateDocumentParams.mdx create mode 100644 docs/sdk/reference/client/managers/interfaces/DocumentListFilters.mdx create mode 100644 docs/sdk/reference/client/managers/interfaces/UpdateDocumentParams.mdx create mode 100644 docs/sdk/reference/client/managers/type-aliases/DocumentRotation.mdx create mode 100644 docs/sdk/reference/types/models/interfaces/ContainerRoute.mdx delete mode 100644 docs/sdk/reference/types/models/interfaces/Route.mdx create mode 100644 docs/sdk/reference/types/models/interfaces/RouteCoordinates.mdx create mode 100644 docs/sdk/reference/types/models/interfaces/RoutePort.mdx create mode 100644 docs/sdk/reference/types/models/interfaces/RouteVessel.mdx diff --git a/MCP_README.md b/MCP_README.md index d4c45ed4..0495d958 100644 --- a/MCP_README.md +++ b/MCP_README.md @@ -69,7 +69,7 @@ Search for bill of lading 123456789 | `get_container` | Get detailed container information | | `get_shipment_details` | Get complete shipment routing and containers | | `get_container_transport_events` | Get full event timeline | -| `get_container_route` | Get vessel routing with ETAs | +| `get_container_route` | Get ports in route order with ETAs and the current vessel | | `get_supported_shipping_lines` | List 40+ supported carriers | | `list_containers` | Browse all tracked containers | | `list_shipments` | Browse all shipments | diff --git a/docs/api-docs/in-depth-guides/mcp.mdx b/docs/api-docs/in-depth-guides/mcp.mdx index 69778599..bd97e4c5 100644 --- a/docs/api-docs/in-depth-guides/mcp.mdx +++ b/docs/api-docs/in-depth-guides/mcp.mdx @@ -223,7 +223,7 @@ T49_API_TOKEN=YOUR_API_KEY npm run mcp:stdio 2>&1 | head -20 | `get_shipment_details` | Get shipment and containers | `id: uuid`, `include_containers?: boolean`, `include_custom_fields?: boolean` | | `get_container_transport_events` | Get event timeline | `id: uuid` | | `get_supported_shipping_lines` | List carriers with SCAC codes | `search?: string` | -| `get_container_route` | Get multi-leg routing (paid feature) | `id: uuid` | +| `get_container_route` | Get ports in route order with ETAs and the current vessel (paid feature) | `id: uuid` | | `list_shipments` | List shipments with filters + pagination | `status?`, `port?`, `carrier?`, `updated_after?`, `include_containers?`, `page?`, `page_size?` | | `list_containers` | List containers with filters + pagination | `status?`, `port?`, `carrier?`, `updated_after?`, `include?`, `page?`, `page_size?` | | `list_tracking_requests` | List tracking requests with filters | `filters?`, `status?`, `request_type?`, `page?`, `page_size?` | diff --git a/docs/docs.json b/docs/docs.json index 4564e52a..9ac6ddf6 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -405,7 +405,12 @@ "pages": [ "sdk/reference/client/index", "sdk/reference/client/classes/Terminal49Client", - "sdk/reference/client/interfaces/Terminal49ClientConfig" + "sdk/reference/client/interfaces/Terminal49ClientConfig", + "sdk/reference/client/interfaces/CustomFieldDefinitionListFilters", + "sdk/reference/client/interfaces/CustomFieldListFilters", + "sdk/reference/client/interfaces/TriggerWebhookParams", + "sdk/reference/client/interfaces/VesselFuturePositionsParams", + "sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams" ] }, { @@ -414,11 +419,18 @@ "sdk/reference/client/managers/index", "sdk/reference/client/managers/classes/BaseManager", "sdk/reference/client/managers/classes/ContainerManager", + "sdk/reference/client/managers/classes/DocumentManager", + "sdk/reference/client/managers/classes/DocumentSchemaManager", + "sdk/reference/client/managers/classes/EmailSubmissionManager", "sdk/reference/client/managers/classes/ShipmentManager", "sdk/reference/client/managers/classes/ShippingLineManager", "sdk/reference/client/managers/classes/TrackingRequestManager", + "sdk/reference/client/managers/interfaces/CreateDocumentParams", "sdk/reference/client/managers/interfaces/CreateTrackingRequestFromInferOptions", + "sdk/reference/client/managers/interfaces/DocumentListFilters", "sdk/reference/client/managers/interfaces/TrackingRequestListFilters", + "sdk/reference/client/managers/interfaces/UpdateDocumentParams", + "sdk/reference/client/managers/type-aliases/DocumentRotation", "sdk/reference/client/managers/type-aliases/TrackingRequestType" ] }, @@ -459,9 +471,12 @@ "pages": [ "sdk/reference/types/models/index", "sdk/reference/types/models/interfaces/Container", + "sdk/reference/types/models/interfaces/ContainerRoute", "sdk/reference/types/models/interfaces/PaginatedResult", "sdk/reference/types/models/interfaces/PaginationLinks", - "sdk/reference/types/models/interfaces/Route", + "sdk/reference/types/models/interfaces/RouteCoordinates", + "sdk/reference/types/models/interfaces/RoutePort", + "sdk/reference/types/models/interfaces/RouteVessel", "sdk/reference/types/models/interfaces/Shipment", "sdk/reference/types/models/interfaces/ShippingLine", "sdk/reference/types/models/interfaces/TrackingRequest" diff --git a/docs/mcp/home.mdx b/docs/mcp/home.mdx index 6be6f234..b75d7407 100644 --- a/docs/mcp/home.mdx +++ b/docs/mcp/home.mdx @@ -373,10 +373,17 @@ List carriers supported by Terminal49 with their SCAC codes. ### `get_container_route` -Get detailed multi-leg routing with vessel itinerary. +Get a container's route: the ports in order with their arrival and departure times, and the vessel carrying the container while it is at sea. + +The tool returns: +- `ports`: each port's sequence, label (`POL`, `TS1`, `POD`), name, country code, `inbound` ETA and ATA, and `outbound` ETD and ATD. +- `current_vessel`: name, IMO, voyage, position, heading, speed in knots, and the departure and arrival ports. It is `null` when the container is not at sea. +- `total_ports`: the number of ports on the route. + +If Terminal49 has no route data for the container yet, the tool returns a `NoRouteData` result with a suggested alternative instead of an error. -This is a **paid feature**. If not enabled for your account, use `get_container_transport_events` for historical movement data instead. +This is a **paid feature**. If it is not enabled for your account, the tool returns a `FeatureNotEnabled` result. Use `get_container_transport_events` for historical movement data instead. See [Entitlements and Paid Features](/api-docs/useful-info/entitlements) for the related Routing Data entitlement. @@ -387,9 +394,9 @@ See [Entitlements and Paid Features](/api-docs/useful-info/entitlements) for the **Good for** - "What's the routing for this container?" - "Which transshipment ports?" -- "What vessel is it on?" +- "What vessel is it on, and where is it now?" -**REST equivalent**: [GET /containers/{id}](/api-docs/api-reference/containers/get-a-container) (route data is included with the container) +**REST equivalent**: [GET /containers/{id}/map_geojson](/api-docs/api-reference/containers/get-container-map-geojson) --- diff --git a/docs/sdk/methods.mdx b/docs/sdk/methods.mdx index 1ac0282f..9f9507b3 100644 --- a/docs/sdk/methods.mdx +++ b/docs/sdk/methods.mdx @@ -37,7 +37,7 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | `client.containers.get(id, include?, options?)` | Fetch a container by ID. `include` is an array of related resources. | | `client.containers.list(filters?, options?)` | List containers matching filter criteria. | | `client.containers.events(id, options?)` | Get transport events for a container. | -| `client.containers.route(id, options?)` | Get routing details: vessels, ports, and journey legs. | +| `client.containers.route(id, options?)` | Get the container's route from `GET /containers/{id}/map_geojson`. `raw` returns the GeoJSON FeatureCollection. `mapped` returns `{ ports, currentVessel, totalPorts }`, with ports in route order and their arrival and departure times. Requires the Routing Data feature. `client.containers.map` is a deprecated alias. | | `client.containers.rawEvents(id, options?)` | Get unprocessed events as received from carriers. | | `client.containers.refresh(id, options?)` | Request an immediate data refresh from the carrier. | @@ -52,6 +52,15 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | `client.trackingRequests.inferNumber(number)` | Detect whether a number is a container, booking, or bill of lading. | | `client.trackingRequests.createFromInfer(number, options?)` | Create a tracking request with automatic number type detection. | +### Vessels + +| Method | Description | +|--------|-------------| +| `client.vessels.get(id, options?)` | Fetch a vessel by ID. | +| `client.vessels.getByImo(imo, options?)` | Fetch a vessel by IMO number. | +| `client.vessels.futurePositions(id, { portId, previousPortId }, options?)` | Get the vessel's estimated positions between the previous port and the destination port. Requires the Routing Data feature. | +| `client.vessels.futurePositionsWithCoords(id, { portId, previousPortId, latitude, longitude }, options?)` | Get the vessel's estimated positions from a starting coordinate to the destination port. Requires the Routing Data feature. | + ### Shipping lines | Method | Description | @@ -92,6 +101,10 @@ All namespace methods are also available as direct methods on the client: | `client.trackingRequests.inferNumber` | `client.inferTrackingNumber` | | `client.trackingRequests.createFromInfer` | `client.createTrackingRequestFromInfer` | | `client.shippingLines.list` | `client.listShippingLines` | +| `client.vessels.get` | `client.getVessel` | +| `client.vessels.getByImo` | `client.getVesselByImo` | +| `client.vessels.futurePositions` | `client.getVesselFuturePositions` | +| `client.vessels.futurePositionsWithCoords` | `client.getVesselFuturePositionsWithCoords` | ## Common options diff --git a/docs/sdk/quickstart.mdx b/docs/sdk/quickstart.mdx index ae3842bb..2366ed1b 100644 --- a/docs/sdk/quickstart.mdx +++ b/docs/sdk/quickstart.mdx @@ -53,11 +53,12 @@ async function main() { }); console.log(`Container has ${events.length} events`); - // 5) Get routing details (vessels, ports, legs) + // 5) Get the route: ports in order and the current vessel. + // Requires the Routing Data feature; otherwise this throws FeatureNotEnabledError. const route = await client.containers.route(containerId, { format: 'mapped', }); - console.log(`Route has ${route.locations.length} locations`); + console.log(`Route has ${route.totalPorts} ports`); } main(); diff --git a/docs/sdk/reference/client/classes/Terminal49Client.mdx b/docs/sdk/reference/client/classes/Terminal49Client.mdx index b4744e57..7305d453 100644 --- a/docs/sdk/reference/client/classes/Terminal49Client.mdx +++ b/docs/sdk/reference/client/classes/Terminal49Client.mdx @@ -50,11 +50,16 @@ data from Node.js applications. | `customFields.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `customFields.list` | `public` | (`options?`) => `Promise`\<`any`\> | | `customFields.update` | `public` | (`id`, `payload`, `options?`) => `Promise`\<`any`\> | +| `documents` | `public` | [`DocumentManager`](/sdk/reference/client/managers/classes/DocumentManager) | +| `documentSchemas` | `public` | [`DocumentSchemaManager`](/sdk/reference/client/managers/classes/DocumentSchemaManager) | +| `emailSubmissions` | `public` | [`EmailSubmissionManager`](/sdk/reference/client/managers/classes/EmailSubmissionManager) | | `metroAreas` | `public` | `object` | | `metroAreas.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `parties` | `public` | `object` | +| `parties.create` | `public` | (`payload`, `options?`) => `Promise`\<`any`\> | | `parties.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `parties.list` | `public` | (`options?`) => `Promise`\<`any`\> | +| `parties.update` | `public` | (`id`, `payload`, `options?`) => `Promise`\<`any`\> | | `ports` | `public` | `object` | | `ports.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `shipments` | `public` | [`ShipmentManager`](/sdk/reference/client/managers/classes/ShipmentManager) | @@ -63,8 +68,8 @@ data from Node.js applications. | `terminals.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `trackingRequests` | `public` | [`TrackingRequestManager`](/sdk/reference/client/managers/classes/TrackingRequestManager) | | `vessels` | `public` | `object` | -| `vessels.futurePositions` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | -| `vessels.futurePositionsWithCoords` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | +| `vessels.futurePositions` | `public` | (`id`, `params`, `options?`) => `Promise`\<`any`\> | +| `vessels.futurePositionsWithCoords` | `public` | (`id`, `params`, `options?`) => `Promise`\<`any`\> | | `vessels.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `vessels.getByImo` | `public` | (`imo`, `options?`) => `Promise`\<`any`\> | | `webhookNotifications` | `public` | `object` | @@ -74,9 +79,11 @@ data from Node.js applications. | `webhooks` | `public` | `object` | | `webhooks.create` | `public` | (`payload`, `options?`) => `Promise`\<`any`\> | | `webhooks.delete` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | +| `webhooks.events` | `public` | (`options?`) => `Promise`\<`any`\> | | `webhooks.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `webhooks.ips` | `public` | (`options?`) => `Promise`\<`any`\> | | `webhooks.list` | `public` | (`options?`) => `Promise`\<`any`\> | +| `webhooks.trigger` | `public` | (`params`, `options?`) => `Promise`\<`any`\> | | `webhooks.update` | `public` | (`id`, `payload`, `options?`) => `Promise`\<`any`\> | ## Methods @@ -139,6 +146,28 @@ Create a custom field option. *** +### createParty() + +> **createParty**(`payload`, `options?`): `Promise`\<`any`\> + +Create a party. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | \{ `data?`: \{ `attributes`: \{ `company_name?`: `string`; \}; \}; \} | - | +| `payload.data?` | \{ `attributes`: \{ `company_name?`: `string`; \}; \} | - | +| `payload.data.attributes?` | \{ `company_name?`: `string`; \} | - | +| `payload.data.attributes.company_name?` | `string` | **Description** The name of the company **Example** `COMPANY NAME` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | - | + +#### Returns + +`Promise`\<`any`\> + +*** + ### createTrackingRequest() > **createTrackingRequest**(`params`): `Promise`\<`any`\> @@ -351,7 +380,7 @@ Fetch raw carrier/terminal events for a container. > **getContainerRoute**(`id`, `options?`): `Promise`\<`any`\> -Fetch routing details for a container. This may require a paid Terminal49 feature. +Fetch a container's route (ports, current vessel, tracks). Requires the Routing Data feature. #### Parameters @@ -634,15 +663,16 @@ Fetch a vessel by IMO number. ### getVesselFuturePositions() -> **getVesselFuturePositions**(`id`, `options?`): `Promise`\<`any`\> +> **getVesselFuturePositions**(`id`, `params`, `options?`): `Promise`\<`any`\> -Fetch future vessel positions. +Fetch a vessel's estimated positions between two ports. Requires the Routing Data feature. #### Parameters | Parameter | Type | | ------ | ------ | | `id` | `string` | +| `params` | [`VesselFuturePositionsParams`](/sdk/reference/client/interfaces/VesselFuturePositionsParams) | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns @@ -653,15 +683,16 @@ Fetch future vessel positions. ### getVesselFuturePositionsWithCoords() -> **getVesselFuturePositionsWithCoords**(`id`, `options?`): `Promise`\<`any`\> +> **getVesselFuturePositionsWithCoords**(`id`, `params`, `options?`): `Promise`\<`any`\> -Fetch future vessel positions with coordinates. +Fetch a vessel's estimated positions from a starting coordinate. Requires the Routing Data feature. #### Parameters | Parameter | Type | | ------ | ------ | | `id` | `string` | +| `params` | [`VesselFuturePositionsWithCoordsParams`](/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams) | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns @@ -792,7 +823,7 @@ List custom field definitions. | Parameter | Type | | ------ | ------ | -| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) | +| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) & `object` | #### Returns @@ -829,7 +860,7 @@ List custom field assignments. | Parameter | Type | | ------ | ------ | -| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) | +| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) & `object` | #### Returns @@ -931,6 +962,24 @@ Alias for [listTrackingRequests](#listtrackingrequests). *** +### listWebhookEvents() + +> **listWebhookEvents**(`options?`): `Promise`\<`any`\> + +List the event names a webhook can subscribe to. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### listWebhookNotifications() > **listWebhookNotifications**(`options?`): `Promise`\<`any`\> @@ -1065,6 +1114,25 @@ Convenience helper for creating a tracking request from a container or booking n *** +### triggerWebhook() + +> **triggerWebhook**(`params`, `options?`): `Promise`\<`any`\> + +Send a test webhook delivery with an example payload to a URL. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `params` | [`TriggerWebhookParams`](/sdk/reference/client/interfaces/TriggerWebhookParams) | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### updateCustomField() > **updateCustomField**(`id`, `payload`, `options?`): `Promise`\<`any`\> @@ -1126,6 +1194,29 @@ Update a custom field option. *** +### updateParty() + +> **updateParty**(`id`, `payload`, `options?`): `Promise`\<`any`\> + +Update a party. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `id` | `string` | - | +| `payload` | \{ `data?`: \{ `attributes`: \{ `company_name?`: `string`; \}; \}; \} | - | +| `payload.data?` | \{ `attributes`: \{ `company_name?`: `string`; \}; \} | - | +| `payload.data.attributes?` | \{ `company_name?`: `string`; \} | - | +| `payload.data.attributes.company_name?` | `string` | **Description** The name of the company **Example** `COMPANY NAME` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | - | + +#### Returns + +`Promise`\<`any`\> + +*** + ### updateShipment() > **updateShipment**(`id`, `attrs`, `options?`): `Promise`\<`any`\> diff --git a/docs/sdk/reference/client/index.mdx b/docs/sdk/reference/client/index.mdx index 9676f1e2..73f8eb84 100644 --- a/docs/sdk/reference/client/index.mdx +++ b/docs/sdk/reference/client/index.mdx @@ -25,4 +25,9 @@ description: "Reference index for the Terminal49 TypeScript SDK client module, l | Interface | Description | | ------ | ------ | +| [CustomFieldDefinitionListFilters](/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters) | Filters accepted by `customFieldDefinitions.list`. | +| [CustomFieldListFilters](/sdk/reference/client/interfaces/CustomFieldListFilters) | Filters accepted by `customFields.list`. | | [Terminal49ClientConfig](/sdk/reference/client/interfaces/Terminal49ClientConfig) | Configuration for [Terminal49Client](/sdk/reference/client/classes/Terminal49Client). | +| [TriggerWebhookParams](/sdk/reference/client/interfaces/TriggerWebhookParams) | Parameters for [Terminal49Client.triggerWebhook](/sdk/reference/client/classes/Terminal49Client#triggerwebhook). | +| [VesselFuturePositionsParams](/sdk/reference/client/interfaces/VesselFuturePositionsParams) | Parameters for [Terminal49Client.getVesselFuturePositions](/sdk/reference/client/classes/Terminal49Client#getvesselfuturepositions). | +| [VesselFuturePositionsWithCoordsParams](/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams) | Parameters for [Terminal49Client.getVesselFuturePositionsWithCoords](/sdk/reference/client/classes/Terminal49Client#getvesselfuturepositionswithcoords). | diff --git a/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx b/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx new file mode 100644 index 00000000..fcf3dbbb --- /dev/null +++ b/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx @@ -0,0 +1,15 @@ +--- +title: "Interface: CustomFieldDefinitionListFilters" +--- + +# Interface: CustomFieldDefinitionListFilters + +Filters accepted by `customFieldDefinitions.list`. + +## Properties + +| Property | Type | +| ------ | ------ | +| `dataType?` | `"number"` \| `"boolean"` \| `"datetime"` \| `"date"` \| `"short_text"` \| `"enum"` \| `"enum_multi"` \| `"reference"` | +| `displayName?` | `string` | +| `entityType?` | `"Shipment"` \| `"Container"` | diff --git a/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx b/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx new file mode 100644 index 00000000..ac1c23df --- /dev/null +++ b/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx @@ -0,0 +1,15 @@ +--- +title: "Interface: CustomFieldListFilters" +--- + +# Interface: CustomFieldListFilters + +Filters accepted by `customFields.list`. + +## Properties + +| Property | Type | +| ------ | ------ | +| `definitionId?` | `string` | +| `entityId?` | `string` | +| `entityType?` | `"Shipment"` \| `"Container"` | diff --git a/docs/sdk/reference/client/interfaces/TriggerWebhookParams.mdx b/docs/sdk/reference/client/interfaces/TriggerWebhookParams.mdx new file mode 100644 index 00000000..41363df0 --- /dev/null +++ b/docs/sdk/reference/client/interfaces/TriggerWebhookParams.mdx @@ -0,0 +1,16 @@ +--- +title: "Interface: TriggerWebhookParams" +--- + +# Interface: TriggerWebhookParams + +Parameters for [Terminal49Client.triggerWebhook](/sdk/reference/client/classes/Terminal49Client#triggerwebhook). + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `documentType?` | `string` | Document type for `document_representation.*` example payloads. | +| `event` | `string` | Webhook event name used to generate the example payload, e.g. `tracking_request.succeeded`. | +| `secret?` | `string` | Optional secret used to sign the request in `X-T49-Webhook-Signature`. | +| `url` | `string` | HTTPS destination URL for the test delivery. | diff --git a/docs/sdk/reference/client/interfaces/VesselFuturePositionsParams.mdx b/docs/sdk/reference/client/interfaces/VesselFuturePositionsParams.mdx new file mode 100644 index 00000000..9bfddf66 --- /dev/null +++ b/docs/sdk/reference/client/interfaces/VesselFuturePositionsParams.mdx @@ -0,0 +1,18 @@ +--- +title: "Interface: VesselFuturePositionsParams" +--- + +# Interface: VesselFuturePositionsParams + +Parameters for [Terminal49Client.getVesselFuturePositions](/sdk/reference/client/classes/Terminal49Client#getvesselfuturepositions). + +## Extended by + +- [`VesselFuturePositionsWithCoordsParams`](/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams) + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `portId` | `string` | Destination port ID. | +| `previousPortId` | `string` | ID of the port the vessel left before heading to `portId`. | diff --git a/docs/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams.mdx b/docs/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams.mdx new file mode 100644 index 00000000..4a3b5cb1 --- /dev/null +++ b/docs/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams.mdx @@ -0,0 +1,20 @@ +--- +title: "Interface: VesselFuturePositionsWithCoordsParams" +--- + +# Interface: VesselFuturePositionsWithCoordsParams + +Parameters for [Terminal49Client.getVesselFuturePositionsWithCoords](/sdk/reference/client/classes/Terminal49Client#getvesselfuturepositionswithcoords). + +## Extends + +- [`VesselFuturePositionsParams`](/sdk/reference/client/interfaces/VesselFuturePositionsParams) + +## Properties + +| Property | Type | Description | Inherited from | +| ------ | ------ | ------ | ------ | +| `latitude` | `number` | Starting latitude. | - | +| `longitude` | `number` | Starting longitude. | - | +| `portId` | `string` | Destination port ID. | [`VesselFuturePositionsParams`](/sdk/reference/client/interfaces/VesselFuturePositionsParams).[`portId`](/sdk/reference/client/interfaces/VesselFuturePositionsParams#property-portid) | +| `previousPortId` | `string` | ID of the port the vessel left before heading to `portId`. | [`VesselFuturePositionsParams`](/sdk/reference/client/interfaces/VesselFuturePositionsParams).[`previousPortId`](/sdk/reference/client/interfaces/VesselFuturePositionsParams#property-previousportid) | diff --git a/docs/sdk/reference/client/managers/classes/BaseManager.mdx b/docs/sdk/reference/client/managers/classes/BaseManager.mdx index 3f6161a2..3c2436d5 100644 --- a/docs/sdk/reference/client/managers/classes/BaseManager.mdx +++ b/docs/sdk/reference/client/managers/classes/BaseManager.mdx @@ -11,6 +11,9 @@ description: "BaseManager class in the Terminal49 TypeScript SDK, the shared bas - [`ShipmentManager`](/sdk/reference/client/managers/classes/ShipmentManager) - [`ShippingLineManager`](/sdk/reference/client/managers/classes/ShippingLineManager) - [`TrackingRequestManager`](/sdk/reference/client/managers/classes/TrackingRequestManager) +- [`DocumentManager`](/sdk/reference/client/managers/classes/DocumentManager) +- [`EmailSubmissionManager`](/sdk/reference/client/managers/classes/EmailSubmissionManager) +- [`DocumentSchemaManager`](/sdk/reference/client/managers/classes/DocumentSchemaManager) ## Constructors diff --git a/docs/sdk/reference/client/managers/classes/ContainerManager.mdx b/docs/sdk/reference/client/managers/classes/ContainerManager.mdx index 590ddf01..5e7f1e01 100644 --- a/docs/sdk/reference/client/managers/classes/ContainerManager.mdx +++ b/docs/sdk/reference/client/managers/classes/ContainerManager.mdx @@ -32,6 +32,26 @@ description: "ContainerManager reference for the Terminal49 TypeScript SDK, used ## Methods +### addPartyRole() + +> **addPartyRole**(`id`, `__namedParameters`, `options?`): `Promise`\<`any`\> + +Assign a party to a container in the given role. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `__namedParameters` | `AddPartyRoleParams` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### customFields() > **customFields**(`id`, `options?`): `Promise`\<`any`\> @@ -49,6 +69,26 @@ description: "ContainerManager reference for the Terminal49 TypeScript SDK, used *** +### deleteCustomField() + +> **deleteCustomField**(`id`, `apiSlug`, `options?`): `Promise`\<`any`\> + +Remove a custom field value from a container. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### demurrage() > **demurrage**(`id`): `Promise`\<`any`\> @@ -134,7 +174,7 @@ description: "ContainerManager reference for the Terminal49 TypeScript SDK, used *** -### map() +### ~~map()~~ > **map**(`id`, `options?`): `Promise`\<`any`\> @@ -149,6 +189,29 @@ description: "ContainerManager reference for the Terminal49 TypeScript SDK, used `Promise`\<`any`\> +#### Deprecated + +Use [ContainerManager.route](#route). + +*** + +### partyRoles() + +> **partyRoles**(`id`, `options?`): `Promise`\<`any`\> + +List the party roles assigned to a container. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + *** ### rawEvents() @@ -185,10 +248,35 @@ description: "ContainerManager reference for the Terminal49 TypeScript SDK, used *** +### removePartyRole() + +> **removePartyRole**(`id`, `partyRoleId`, `options?`): `Promise`\<`any`\> + +Remove a party role assignment from a container. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `partyRoleId` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### route() > **route**(`id`, `options?`): `Promise`\<`any`\> +Fetch the container's route: ports, the current vessel, and vessel tracks. +The raw format is the GeoJSON FeatureCollection; the mapped format is a +`ContainerRoute`. Requires the Routing Data feature, otherwise the API +returns 403. + #### Parameters | Parameter | Type | @@ -204,17 +292,61 @@ description: "ContainerManager reference for the Terminal49 TypeScript SDK, used ### setCustomField() -> **setCustomField**(`id`, `fieldId`, `value`, `options?`): `Promise`\<`any`\> +> **setCustomField**(`id`, `apiSlug`, `value`, `options?`): `Promise`\<`any`\> + +Create a custom field value on a container. #### Parameters | Parameter | Type | | ------ | ------ | | `id` | `string` | -| `fieldId` | `string` | +| `apiSlug` | `string` | | `value` | `unknown` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns `Promise`\<`any`\> + +*** + +### update() + +> **update**(`id`, `attrs`, `options?`): `Promise`\<`any`\> + +Update container attributes such as `ref_numbers`. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `attrs` | \{ `ref_numbers?`: `string`[]; \} | +| `attrs.ref_numbers?` | `string`[] | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### updateCustomField() + +> **updateCustomField**(`id`, `apiSlug`, `value`, `options?`): `Promise`\<`any`\> + +Update an existing custom field value on a container. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/classes/DocumentManager.mdx b/docs/sdk/reference/client/managers/classes/DocumentManager.mdx new file mode 100644 index 00000000..b69c33c1 --- /dev/null +++ b/docs/sdk/reference/client/managers/classes/DocumentManager.mdx @@ -0,0 +1,240 @@ +--- +title: "Class: DocumentManager" +--- + +# Class: DocumentManager + +## Extends + +- [`BaseManager`](/sdk/reference/client/managers/classes/BaseManager) + +## Constructors + +### Constructor + +> **new DocumentManager**(`transport`, `defaultFormat?`): `DocumentManager` + +#### Parameters + +| Parameter | Type | Default value | +| ------ | ------ | ------ | +| `transport` | [`Transport`](/sdk/reference/client/transport/classes/Transport) | `undefined` | +| `defaultFormat` | [`ResponseFormat`](/sdk/reference/types/options/type-aliases/ResponseFormat) | `'raw'` | + +#### Returns + +`DocumentManager` + +#### Inherited from + +[`BaseManager`](/sdk/reference/client/managers/classes/BaseManager).[`constructor`](/sdk/reference/client/managers/classes/BaseManager#constructor) + +## Methods + +### create() + +> **create**(`params`, `options?`): `Promise`\<`any`\> + +Create a document from a previously direct-uploaded blob. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `params` | [`CreateDocumentParams`](/sdk/reference/client/managers/interfaces/CreateDocumentParams) | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### delete() + +> **delete**(`id`, `options?`): `Promise`\<`any`\> + +Delete a document. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### downloadUrl() + +> **downloadUrl**(`id`, `options?`): `Promise`\<`any`\> + +Get a short-lived download URL for a document's file. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### get() + +> **get**(`id`, `options?`): `Promise`\<`any`\> + +Fetch a document by ID. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) & `object` | + +#### Returns + +`Promise`\<`any`\> + +*** + +### list() + +> **list**(`filters?`, `options?`): `Promise`\<`any`\> + +List documents with optional filters and pagination. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `filters` | [`DocumentListFilters`](/sdk/reference/client/managers/interfaces/DocumentListFilters) | +| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### reclassify() + +> **reclassify**(`id`, `options?`): `Promise`\<`any`\> + +Re-run classification on a document. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### reextract() + +> **reextract**(`id`, `options?`): `Promise`\<`any`\> + +Re-run data extraction on a document. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### relink() + +> **relink**(`id`, `options?`): `Promise`\<`any`\> + +Re-run shipment/container linking on a document. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### rotate() + +> **rotate**(`id`, `degrees`, `options?`): `Promise`\<`any`\> + +Rotate a document's pages by 90, 180, or 270 degrees. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `degrees` | [`DocumentRotation`](/sdk/reference/client/managers/type-aliases/DocumentRotation) | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### types() + +> **types**(`options?`): `Promise`\<`any`\> + +List the document types Terminal49 can classify. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### update() + +> **update**(`id`, `params`, `options?`): `Promise`\<`any`\> + +Override a document's type or extracted data. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `params` | [`UpdateDocumentParams`](/sdk/reference/client/managers/interfaces/UpdateDocumentParams) | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx b/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx new file mode 100644 index 00000000..2504f196 --- /dev/null +++ b/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx @@ -0,0 +1,49 @@ +--- +title: "Class: DocumentSchemaManager" +--- + +# Class: DocumentSchemaManager + +## Extends + +- [`BaseManager`](/sdk/reference/client/managers/classes/BaseManager) + +## Constructors + +### Constructor + +> **new DocumentSchemaManager**(`transport`, `defaultFormat?`): `DocumentSchemaManager` + +#### Parameters + +| Parameter | Type | Default value | +| ------ | ------ | ------ | +| `transport` | [`Transport`](/sdk/reference/client/transport/classes/Transport) | `undefined` | +| `defaultFormat` | [`ResponseFormat`](/sdk/reference/types/options/type-aliases/ResponseFormat) | `'raw'` | + +#### Returns + +`DocumentSchemaManager` + +#### Inherited from + +[`BaseManager`](/sdk/reference/client/managers/classes/BaseManager).[`constructor`](/sdk/reference/client/managers/classes/BaseManager#constructor) + +## Methods + +### get() + +> **get**(`id`, `options?`): `Promise`\<`any`\> + +Fetch the extraction schema for a document type. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/classes/EmailSubmissionManager.mdx b/docs/sdk/reference/client/managers/classes/EmailSubmissionManager.mdx new file mode 100644 index 00000000..f6c39bb2 --- /dev/null +++ b/docs/sdk/reference/client/managers/classes/EmailSubmissionManager.mdx @@ -0,0 +1,67 @@ +--- +title: "Class: EmailSubmissionManager" +--- + +# Class: EmailSubmissionManager + +## Extends + +- [`BaseManager`](/sdk/reference/client/managers/classes/BaseManager) + +## Constructors + +### Constructor + +> **new EmailSubmissionManager**(`transport`, `defaultFormat?`): `EmailSubmissionManager` + +#### Parameters + +| Parameter | Type | Default value | +| ------ | ------ | ------ | +| `transport` | [`Transport`](/sdk/reference/client/transport/classes/Transport) | `undefined` | +| `defaultFormat` | [`ResponseFormat`](/sdk/reference/types/options/type-aliases/ResponseFormat) | `'raw'` | + +#### Returns + +`EmailSubmissionManager` + +#### Inherited from + +[`BaseManager`](/sdk/reference/client/managers/classes/BaseManager).[`constructor`](/sdk/reference/client/managers/classes/BaseManager#constructor) + +## Methods + +### get() + +> **get**(`id`, `options?`): `Promise`\<`any`\> + +Fetch an email submission by ID. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) & `object` | + +#### Returns + +`Promise`\<`any`\> + +*** + +### list() + +> **list**(`options?`): `Promise`\<`any`\> + +List email submissions (documents sent to your Terminal49 inbox). + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) & `object` | + +#### Returns + +`Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx b/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx index 3a0272a6..04321a45 100644 --- a/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx +++ b/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx @@ -32,6 +32,26 @@ description: "ShipmentManager class in the Terminal49 TypeScript SDK, used to li ## Methods +### addPartyRole() + +> **addPartyRole**(`id`, `__namedParameters`, `options?`): `Promise`\<`any`\> + +Assign a party to a shipment in the given role. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `__namedParameters` | `AddPartyRoleParams` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### customFields() > **customFields**(`id`, `options?`): `Promise`\<`any`\> @@ -49,6 +69,26 @@ description: "ShipmentManager class in the Terminal49 TypeScript SDK, used to li *** +### deleteCustomField() + +> **deleteCustomField**(`id`, `apiSlug`, `options?`): `Promise`\<`any`\> + +Remove a custom field value from a shipment. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### get() > **get**(`id`, `includeContainers?`, `options?`): `Promise`\<`any`\> @@ -101,6 +141,45 @@ description: "ShipmentManager class in the Terminal49 TypeScript SDK, used to li *** +### partyRoles() + +> **partyRoles**(`id`, `options?`): `Promise`\<`any`\> + +List the party roles assigned to a shipment. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### removePartyRole() + +> **removePartyRole**(`id`, `partyRoleId`, `options?`): `Promise`\<`any`\> + +Remove a party role assignment from a shipment. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `partyRoleId` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### resumeTracking() > **resumeTracking**(`id`, `options?`): `Promise`\<`any`\> @@ -120,14 +199,16 @@ description: "ShipmentManager class in the Terminal49 TypeScript SDK, used to li ### setCustomField() -> **setCustomField**(`id`, `fieldId`, `value`, `options?`): `Promise`\<`any`\> +> **setCustomField**(`id`, `apiSlug`, `value`, `options?`): `Promise`\<`any`\> + +Create a custom field value on a shipment. #### Parameters | Parameter | Type | | ------ | ------ | | `id` | `string` | -| `fieldId` | `string` | +| `apiSlug` | `string` | | `value` | `unknown` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | @@ -169,3 +250,24 @@ description: "ShipmentManager class in the Terminal49 TypeScript SDK, used to li #### Returns `Promise`\<`any`\> + +*** + +### updateCustomField() + +> **updateCustomField**(`id`, `apiSlug`, `value`, `options?`): `Promise`\<`any`\> + +Update an existing custom field value on a shipment. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/classes/ShippingLineManager.mdx b/docs/sdk/reference/client/managers/classes/ShippingLineManager.mdx index 8376996d..c191bed5 100644 --- a/docs/sdk/reference/client/managers/classes/ShippingLineManager.mdx +++ b/docs/sdk/reference/client/managers/classes/ShippingLineManager.mdx @@ -32,6 +32,25 @@ description: "ShippingLineManager reference for the Terminal49 TypeScript SDK, p ## Methods +### get() + +> **get**(`id`, `options?`): `Promise`\<`any`\> + +Fetch a shipping line by ID. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### list() > **list**(`search?`, `options?`): `Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx b/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx index 2a600691..d9824ec4 100644 --- a/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx +++ b/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx @@ -71,6 +71,45 @@ description: "TrackingRequestManager in the Terminal49 TypeScript SDK, used to c *** +### customFields() + +> **customFields**(`id`, `options?`): `Promise`\<`any`\> + +List custom field values set on a tracking request, with their definitions. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + +### deleteCustomField() + +> **deleteCustomField**(`id`, `apiSlug`, `options?`): `Promise`\<`any`\> + +Remove a custom field value from a tracking request. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### get() > **get**(`id`, `options?`): `Promise`\<`any`\> @@ -138,6 +177,27 @@ description: "TrackingRequestManager in the Terminal49 TypeScript SDK, used to c *** +### setCustomField() + +> **setCustomField**(`id`, `apiSlug`, `value`, `options?`): `Promise`\<`any`\> + +Create a custom field value on a tracking request. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> + +*** + ### update() > **update**(`id`, `attrs`, `options?`): `Promise`\<`any`\> @@ -153,3 +213,24 @@ description: "TrackingRequestManager in the Terminal49 TypeScript SDK, used to c #### Returns `Promise`\<`any`\> + +*** + +### updateCustomField() + +> **updateCustomField**(`id`, `apiSlug`, `value`, `options?`): `Promise`\<`any`\> + +Update an existing custom field value on a tracking request. + +#### Parameters + +| Parameter | Type | +| ------ | ------ | +| `id` | `string` | +| `apiSlug` | `string` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | + +#### Returns + +`Promise`\<`any`\> diff --git a/docs/sdk/reference/client/managers/index.mdx b/docs/sdk/reference/client/managers/index.mdx index 2dda5a89..dda0eb58 100644 --- a/docs/sdk/reference/client/managers/index.mdx +++ b/docs/sdk/reference/client/managers/index.mdx @@ -11,6 +11,9 @@ description: "Reference for the Terminal49 TypeScript SDK managers module: conta | ------ | ------ | | [BaseManager](/sdk/reference/client/managers/classes/BaseManager) | - | | [ContainerManager](/sdk/reference/client/managers/classes/ContainerManager) | - | +| [DocumentManager](/sdk/reference/client/managers/classes/DocumentManager) | - | +| [DocumentSchemaManager](/sdk/reference/client/managers/classes/DocumentSchemaManager) | - | +| [EmailSubmissionManager](/sdk/reference/client/managers/classes/EmailSubmissionManager) | - | | [ShipmentManager](/sdk/reference/client/managers/classes/ShipmentManager) | - | | [ShippingLineManager](/sdk/reference/client/managers/classes/ShippingLineManager) | - | | [TrackingRequestManager](/sdk/reference/client/managers/classes/TrackingRequestManager) | - | @@ -19,14 +22,18 @@ description: "Reference for the Terminal49 TypeScript SDK managers module: conta | Interface | Description | | ------ | ------ | +| [CreateDocumentParams](/sdk/reference/client/managers/interfaces/CreateDocumentParams) | Attributes accepted by [DocumentManager.create](/sdk/reference/client/managers/classes/DocumentManager#create). | | [CreateTrackingRequestFromInferOptions](/sdk/reference/client/managers/interfaces/CreateTrackingRequestFromInferOptions) | - | +| [DocumentListFilters](/sdk/reference/client/managers/interfaces/DocumentListFilters) | Filters accepted by [DocumentManager.list](/sdk/reference/client/managers/classes/DocumentManager#list). | | [IterateOptions](/sdk/reference/client/managers/interfaces/IterateOptions) | Options accepted by BaseManager.createIterator. | | [TrackingRequestListFilters](/sdk/reference/client/managers/interfaces/TrackingRequestListFilters) | - | +| [UpdateDocumentParams](/sdk/reference/client/managers/interfaces/UpdateDocumentParams) | Attributes accepted by [DocumentManager.update](/sdk/reference/client/managers/classes/DocumentManager#update). | ## Type Aliases | Type Alias | Description | | ------ | ------ | +| [DocumentRotation](/sdk/reference/client/managers/type-aliases/DocumentRotation) | - | | [TrackingRequestType](/sdk/reference/client/managers/type-aliases/TrackingRequestType) | - | ## Variables diff --git a/docs/sdk/reference/client/managers/interfaces/CreateDocumentParams.mdx b/docs/sdk/reference/client/managers/interfaces/CreateDocumentParams.mdx new file mode 100644 index 00000000..1b526fb8 --- /dev/null +++ b/docs/sdk/reference/client/managers/interfaces/CreateDocumentParams.mdx @@ -0,0 +1,14 @@ +--- +title: "Interface: CreateDocumentParams" +--- + +# Interface: CreateDocumentParams + +Attributes accepted by [DocumentManager.create](/sdk/reference/client/managers/classes/DocumentManager#create). + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `attachedDocument` | `string` | ActiveStorage signed blob id returned by a direct upload. | +| `name` | `string` | Display name for the document. | diff --git a/docs/sdk/reference/client/managers/interfaces/DocumentListFilters.mdx b/docs/sdk/reference/client/managers/interfaces/DocumentListFilters.mdx new file mode 100644 index 00000000..ded9a246 --- /dev/null +++ b/docs/sdk/reference/client/managers/interfaces/DocumentListFilters.mdx @@ -0,0 +1,17 @@ +--- +title: "Interface: DocumentListFilters" +--- + +# Interface: DocumentListFilters + +Filters accepted by [DocumentManager.list](/sdk/reference/client/managers/classes/DocumentManager#list). + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `documentTypes?` | readonly `string`[] | One or more document types (sent comma-separated). | +| `filename?` | `string` | Full-text match on the document filename. | +| `include?` | `string` | Comma-separated JSON:API includes. | +| `reference?` | `string` | Filter by reference token. | +| `sort?` | `string` | Sort by `document_type`, `added_by`, or `created_at`; prefix with `-` for descending. | diff --git a/docs/sdk/reference/client/managers/interfaces/UpdateDocumentParams.mdx b/docs/sdk/reference/client/managers/interfaces/UpdateDocumentParams.mdx new file mode 100644 index 00000000..bda5494c --- /dev/null +++ b/docs/sdk/reference/client/managers/interfaces/UpdateDocumentParams.mdx @@ -0,0 +1,14 @@ +--- +title: "Interface: UpdateDocumentParams" +--- + +# Interface: UpdateDocumentParams + +Attributes accepted by [DocumentManager.update](/sdk/reference/client/managers/classes/DocumentManager#update). + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `documentTypeManual?` | `string` | Manually override the classified document type. | +| `extractedDataManual?` | \{\[`key`: `string`\]: `unknown`; \} \| `null` | Manually provide extracted key/value data. Pass `null` to clear manual values. | diff --git a/docs/sdk/reference/client/managers/type-aliases/DocumentRotation.mdx b/docs/sdk/reference/client/managers/type-aliases/DocumentRotation.mdx new file mode 100644 index 00000000..bb71b56e --- /dev/null +++ b/docs/sdk/reference/client/managers/type-aliases/DocumentRotation.mdx @@ -0,0 +1,7 @@ +--- +title: "Type Alias: DocumentRotation" +--- + +# Type Alias: DocumentRotation + +> **DocumentRotation** = `90` \| `180` \| `270` diff --git a/docs/sdk/reference/types/models/index.mdx b/docs/sdk/reference/types/models/index.mdx index 262c5f45..9c23dd76 100644 --- a/docs/sdk/reference/types/models/index.mdx +++ b/docs/sdk/reference/types/models/index.mdx @@ -1,6 +1,6 @@ --- title: "types/models: Terminal49 SDK mapped response models" -description: "Mapped response models in the Terminal49 TypeScript SDK: Container, Shipment, ShippingLine, TrackingRequest, Route, PaginatedResult, and PaginationLinks." +description: "Mapped response models in the Terminal49 TypeScript SDK: Container, Shipment, ShippingLine, TrackingRequest, ContainerRoute, PaginatedResult, and PaginationLinks." --- # types/models @@ -10,10 +10,13 @@ description: "Mapped response models in the Terminal49 TypeScript SDK: Container | Interface | Description | | ------ | ------ | | [Container](/sdk/reference/types/models/interfaces/Container) | Simplified container model returned by mapped SDK responses. | +| [ContainerRoute](/sdk/reference/types/models/interfaces/ContainerRoute) | Mapped container route: ports in route order plus the current vessel. | | [CustomField](/sdk/reference/types/models/interfaces/CustomField) | Account-defined custom field value on a container, shipment, or tracking request. | | [PaginatedResult](/sdk/reference/types/models/interfaces/PaginatedResult) | Mapped list response containing records plus pagination metadata. | | [PaginationLinks](/sdk/reference/types/models/interfaces/PaginationLinks) | Pagination links returned by Terminal49 list endpoints. | -| [Route](/sdk/reference/types/models/interfaces/Route) | Simplified container route model returned by mapped SDK responses. | +| [RouteCoordinates](/sdk/reference/types/models/interfaces/RouteCoordinates) | A `[longitude, latitude]` GeoJSON point, named so the axis order cannot be swapped. | +| [RoutePort](/sdk/reference/types/models/interfaces/RoutePort) | One port on a container route, from a `port` feature of `GET /containers/{id}/map_geojson`. | +| [RouteVessel](/sdk/reference/types/models/interfaces/RouteVessel) | The vessel carrying the container right now. Present only while it is at sea. | | [Shipment](/sdk/reference/types/models/interfaces/Shipment) | Simplified shipment model returned by mapped SDK responses. | | [ShippingLine](/sdk/reference/types/models/interfaces/ShippingLine) | Simplified shipping line returned by mapped SDK responses. | | [TrackingRequest](/sdk/reference/types/models/interfaces/TrackingRequest) | Simplified tracking request model returned by mapped SDK responses. | diff --git a/docs/sdk/reference/types/models/interfaces/ContainerRoute.mdx b/docs/sdk/reference/types/models/interfaces/ContainerRoute.mdx new file mode 100644 index 00000000..de7bb49f --- /dev/null +++ b/docs/sdk/reference/types/models/interfaces/ContainerRoute.mdx @@ -0,0 +1,15 @@ +--- +title: "Interface: ContainerRoute" +--- + +# Interface: ContainerRoute + +Mapped container route: ports in route order plus the current vessel. + +## Properties + +| Property | Type | +| ------ | ------ | +| `currentVessel` | [`RouteVessel`](/sdk/reference/types/models/interfaces/RouteVessel) \| `null` | +| `ports` | [`RoutePort`](/sdk/reference/types/models/interfaces/RoutePort)[] | +| `totalPorts` | `number` | diff --git a/docs/sdk/reference/types/models/interfaces/Route.mdx b/docs/sdk/reference/types/models/interfaces/Route.mdx deleted file mode 100644 index 72d6582d..00000000 --- a/docs/sdk/reference/types/models/interfaces/Route.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: "Interface: Route" -description: "Route interface in the Terminal49 TypeScript SDK, the mapped container route model with ordered transport legs, locations, timestamps, and total leg count." ---- - -# Interface: Route - -Simplified container route model returned by mapped SDK responses. - -## Properties - -| Property | Type | -| ------ | ------ | -| `createdAt?` | `string` \| `null` | -| `id?` | `string` | -| `locations` | `object`[] | -| `totalLegs` | `number` | -| `updatedAt?` | `string` \| `null` | diff --git a/docs/sdk/reference/types/models/interfaces/RouteCoordinates.mdx b/docs/sdk/reference/types/models/interfaces/RouteCoordinates.mdx new file mode 100644 index 00000000..5b5cda52 --- /dev/null +++ b/docs/sdk/reference/types/models/interfaces/RouteCoordinates.mdx @@ -0,0 +1,14 @@ +--- +title: "Interface: RouteCoordinates" +--- + +# Interface: RouteCoordinates + +A `[longitude, latitude]` GeoJSON point, named so the axis order cannot be swapped. + +## Properties + +| Property | Type | +| ------ | ------ | +| `latitude` | `number` | +| `longitude` | `number` | diff --git a/docs/sdk/reference/types/models/interfaces/RoutePort.mdx b/docs/sdk/reference/types/models/interfaces/RoutePort.mdx new file mode 100644 index 00000000..2edcba00 --- /dev/null +++ b/docs/sdk/reference/types/models/interfaces/RoutePort.mdx @@ -0,0 +1,24 @@ +--- +title: "Interface: RoutePort" +--- + +# Interface: RoutePort + +One port on a container route, from a `port` feature of `GET /containers/{id}/map_geojson`. + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `coordinates` | [`RouteCoordinates`](/sdk/reference/types/models/interfaces/RouteCoordinates) \| `null` | - | +| `countryCode` | `string` \| `null` | - | +| `inbound` | `object` | - | +| `inbound.ata` | `string` \| `null` | - | +| `inbound.eta` | `string` \| `null` | - | +| `label` | `string` \| `null` | `POL`, `POD`, or `TS1`, `TS2`, and so on for transshipment ports. | +| `locationId` | `string` \| `null` | - | +| `name` | `string` \| `null` | - | +| `outbound` | `object` | - | +| `outbound.atd` | `string` \| `null` | - | +| `outbound.etd` | `string` \| `null` | - | +| `sequence` | `number` \| `null` | Position in the route: 1 is the POL, the last is the POD. | diff --git a/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx b/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx new file mode 100644 index 00000000..37394486 --- /dev/null +++ b/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx @@ -0,0 +1,20 @@ +--- +title: "Interface: RouteVessel" +--- + +# Interface: RouteVessel + +The vessel carrying the container right now. Present only while it is at sea. + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `arrivalPortId` | `string` \| `null` | - | +| `coordinates` | [`RouteCoordinates`](/sdk/reference/types/models/interfaces/RouteCoordinates) \| `null` | - | +| `departurePortId` | `string` \| `null` | - | +| `heading` | `number` \| `null` | Degrees, 0-360. | +| `imo` | `string` \| `null` | - | +| `name` | `string` \| `null` | - | +| `speed` | `number` \| `null` | Knots. | +| `voyage` | `string` \| `null` | - | diff --git a/packages/mcp/README.md b/packages/mcp/README.md index fab8267f..be21a9f0 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -25,7 +25,7 @@ | **`get_shipment_details`** | Get shipment routing, BOL, containers, ports | Full shipment context | | **`get_container_transport_events`** | Get full event timeline for a container | Milestone history | | **`get_supported_shipping_lines`** | List 40+ major carriers with SCAC codes | Filterable by name/code | -| **`get_container_route`** | Get multi-leg routing with vessels and ETAs | Premium feature | +| **`get_container_route`** | Get ports in route order with ETAs and the current vessel | Premium feature | | **`list_shipments`** | List shipments with filters and pagination | Fleet-level visibility | | **`list_containers`** | List containers with filters and pagination | Returns ResourceLinks ✨ | | **`list_tracking_requests`** | List tracking requests and statuses | Audit and monitoring | diff --git a/packages/mcp/TOOLS_OVERVIEW.md b/packages/mcp/TOOLS_OVERVIEW.md index 3ae8d23a..1270451b 100644 --- a/packages/mcp/TOOLS_OVERVIEW.md +++ b/packages/mcp/TOOLS_OVERVIEW.md @@ -205,7 +205,7 @@ get_supported_shipping_lines({ search: "MSCU" }) --- ### 7. `get_container_route` ⭐ **NEW** -**Purpose**: Get detailed routing with vessel itinerary +**Purpose**: Get the container's ports in route order and its current vessel, from `GET /containers/{id}/map_geojson` **Usage**: ```typescript @@ -213,24 +213,25 @@ get_container_route({ id: "container-uuid" }) ``` **Returns**: -- Complete multi-leg journey -- Each port with inbound/outbound vessels -- ETD/ETA/ATD/ATA for each leg -- Transshipment details +- `ports`: sequence, label (POL, TS1, POD), name, country code, inbound ETA/ATA, outbound ETD/ATD +- `current_vessel`: name, IMO, voyage, position, heading, speed, departure and arrival ports (`null` when not at sea) +- `total_ports` -**Important**: This is a **PAID FEATURE** in Terminal49. If not enabled: +It does not return track geometry, port codes, transport mode, carrier SCAC, or the vessel for past legs. + +**Soft results**: an empty route returns `{ "error": "NoRouteData", ... }`. If the paid feature is not enabled: ```json { "error": "FeatureNotEnabled", - "message": "Route tracking is a paid feature...", - "alternative": "Use get_container_transport_events for historical movement" + "message": "Route data is a paid feature (Routing Data)... Contact sales@terminal49.com to enable it.", + "alternative": "Use get_container_transport_events to see historical movement..." } ``` **When to Use**: - User asks about routing or transshipments -- Need vessel itinerary -- Detailed multi-leg journey analysis +- User asks which vessel the container is on, or where it is now +- ETAs for each port on the route --- @@ -354,7 +355,7 @@ list_tracking_requests({ → Use `get_supported_shipping_lines` ### User asks: "How did it get from Shanghai to Chicago?" -→ Option A: Use `get_container_route` (paid feature, shows routing) +→ Option A: Use `get_container_route` (paid feature, shows ports and ETAs) → Option B: Use `get_container_transport_events` (shows actual movement) --- diff --git a/sdks/typescript-sdk-cli/README.md b/sdks/typescript-sdk-cli/README.md index 00039fda..3b1741f1 100644 --- a/sdks/typescript-sdk-cli/README.md +++ b/sdks/typescript-sdk-cli/README.md @@ -144,13 +144,13 @@ Stable error codes include `USAGE_ERROR`, `NETWORK_ERROR`, `AUTH_ERROR`, `RATE_L ## Commands - `t49 shipments get|list|update|stop-tracking|resume-tracking|custom-fields|set-custom-field` -- `t49 containers get|list|events|route|map|raw-events|refresh|demurrage|rail|custom-fields|set-custom-field` +- `t49 containers get|list|events|route|map|raw-events|refresh|demurrage|rail|custom-fields|set-custom-field` (`map` is an alias of `route`) - `t49 tracking-requests list|get|create|update|infer|create-from-infer` - `t49 track ` - `t49 shipping-lines list` - `t49 webhooks list|get|create|update|delete|ips` - `t49 webhook-notifications list|get|examples` -- `t49 vessels get|get-by-imo|future-positions|future-positions-coords` +- `t49 vessels get|get-by-imo|future-positions|future-positions-coords`. `future-positions` requires `--port-id` and `--previous-port-id`. `future-positions-coords` also requires `--latitude` and `--longitude`. - `t49 ports get` - `t49 terminals get` - `t49 parties list|get` diff --git a/sdks/typescript-sdk/README.md b/sdks/typescript-sdk/README.md index c49ee4aa..e4f8e17f 100644 --- a/sdks/typescript-sdk/README.md +++ b/sdks/typescript-sdk/README.md @@ -43,7 +43,9 @@ see the SDK quickstart in the docs site: `docs/api-docs/getting-started/sdk-quic - `listContainers(filters?, options?)` - `listTrackingRequests(filters?, options?)` / `listTrackRequests(filters?, options?)` - `getContainerTransportEvents(id)` -- `getContainerRoute(id)` +- `getContainerRoute(id)`: ports in route order and the current vessel, from `GET /containers/{id}/map_geojson` (Routing Data feature) +- `getVesselFuturePositions(id, { portId, previousPortId })` +- `getVesselFuturePositionsWithCoords(id, { portId, previousPortId, latitude, longitude })` - `listShippingLines(search?)` - `getDemurrage(containerId)` (helper) - `getRailMilestones(containerId)` (helper) From 0b49f4cfcae8e3c0b037654f695c5464f37b113f Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 11:07:53 -0700 Subject: [PATCH 10/14] fix(sdk): keep containers.map() returning GeoJSON map() shipped in 0.5.0 returning the map_geojson FeatureCollection in every format. It now fetches through route() and applies no mapper, so its output is unchanged and it is marked deprecated in favor of route(). The CLI map subcommand keeps printing GeoJSON, and its table view no longer renders the GeoJSON as an empty route table. Co-Authored-By: Claude Opus 5.5 --- docs/sdk/methods.mdx | 2 +- sdks/typescript-sdk-cli/README.md | 2 +- .../src/commands/containers.ts | 10 +++-- sdks/typescript-sdk-cli/src/output/table.ts | 3 +- sdks/typescript-sdk-cli/test/table.test.ts | 38 +++++++++++++------ .../typescript-sdk/src/client.mapping.test.ts | 4 +- .../src/client/managers/containers.ts | 8 +++- 7 files changed, 44 insertions(+), 23 deletions(-) diff --git a/docs/sdk/methods.mdx b/docs/sdk/methods.mdx index 9f9507b3..d32c2070 100644 --- a/docs/sdk/methods.mdx +++ b/docs/sdk/methods.mdx @@ -37,7 +37,7 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | `client.containers.get(id, include?, options?)` | Fetch a container by ID. `include` is an array of related resources. | | `client.containers.list(filters?, options?)` | List containers matching filter criteria. | | `client.containers.events(id, options?)` | Get transport events for a container. | -| `client.containers.route(id, options?)` | Get the container's route from `GET /containers/{id}/map_geojson`. `raw` returns the GeoJSON FeatureCollection. `mapped` returns `{ ports, currentVessel, totalPorts }`, with ports in route order and their arrival and departure times. Requires the Routing Data feature. `client.containers.map` is a deprecated alias. | +| `client.containers.route(id, options?)` | Get the container's route from `GET /containers/{id}/map_geojson`. `raw` returns the GeoJSON FeatureCollection. `mapped` returns `{ ports, currentVessel, totalPorts }`, with ports in route order and their arrival and departure times. Requires the Routing Data feature. `client.containers.map` is deprecated and always returns the GeoJSON FeatureCollection. | | `client.containers.rawEvents(id, options?)` | Get unprocessed events as received from carriers. | | `client.containers.refresh(id, options?)` | Request an immediate data refresh from the carrier. | diff --git a/sdks/typescript-sdk-cli/README.md b/sdks/typescript-sdk-cli/README.md index 3b1741f1..98309c81 100644 --- a/sdks/typescript-sdk-cli/README.md +++ b/sdks/typescript-sdk-cli/README.md @@ -144,7 +144,7 @@ Stable error codes include `USAGE_ERROR`, `NETWORK_ERROR`, `AUTH_ERROR`, `RATE_L ## Commands - `t49 shipments get|list|update|stop-tracking|resume-tracking|custom-fields|set-custom-field` -- `t49 containers get|list|events|route|map|raw-events|refresh|demurrage|rail|custom-fields|set-custom-field` (`map` is an alias of `route`) +- `t49 containers get|list|events|route|map|raw-events|refresh|demurrage|rail|custom-fields|set-custom-field` (`map` is deprecated: it prints the raw GeoJSON FeatureCollection, the same as `route --format raw`) - `t49 tracking-requests list|get|create|update|infer|create-from-infer` - `t49 track ` - `t49 shipping-lines list` diff --git a/sdks/typescript-sdk-cli/src/commands/containers.ts b/sdks/typescript-sdk-cli/src/commands/containers.ts index 90966ca6..a6fc5147 100644 --- a/sdks/typescript-sdk-cli/src/commands/containers.ts +++ b/sdks/typescript-sdk-cli/src/commands/containers.ts @@ -1,7 +1,7 @@ /** * t49 containers * - * Subcommands: get, list, events, route, map (alias of route), raw-events, refresh, demurrage, rail + * Subcommands: get, list, events, route, map (deprecated, GeoJSON), raw-events, refresh, demurrage, rail */ import type { Command } from 'commander'; @@ -202,7 +202,9 @@ export function registerContainersCommand(program: Command): void { cmd .command('route ') - .description('Fetch container route') + .description( + 'Fetch container route ports and current vessel (--format raw for GeoJSON)', + ) .action( action('containers.route', async ({ client, globals }, id: string) => client.containers.route(id, { format: globals.format }), @@ -211,7 +213,9 @@ export function registerContainersCommand(program: Command): void { cmd .command('map ') - .description('Fetch container route geometry as GeoJSON') + .description( + 'Fetch container route geometry as GeoJSON (deprecated: use route)', + ) .action( action('containers.map', async ({ client, globals }, id: string) => client.containers.map(id, { format: globals.format }), diff --git a/sdks/typescript-sdk-cli/src/output/table.ts b/sdks/typescript-sdk-cli/src/output/table.ts index bebda6cc..315bda4e 100644 --- a/sdks/typescript-sdk-cli/src/output/table.ts +++ b/sdks/typescript-sdk-cli/src/output/table.ts @@ -63,7 +63,6 @@ const commandColumns: Record = { { key: ['value', 'attributes.value'], title: 'Value' }, ], 'containers.route': ROUTE_PORT_COLUMNS, - 'containers.map': ROUTE_PORT_COLUMNS, 'containers.demurrage': [ { key: 'container_id', title: 'Container ID' }, { key: 'pickup_lfd', title: 'Pickup LFD' }, @@ -588,7 +587,7 @@ function rowsForCommand( return record.mapped as Record[]; } - if (command === 'containers.route' || command === 'containers.map') { + if (command === 'containers.route') { const mapped = record?.mapped; const route = mapped && typeof mapped === 'object' && !Array.isArray(mapped) diff --git a/sdks/typescript-sdk-cli/test/table.test.ts b/sdks/typescript-sdk-cli/test/table.test.ts index bf2162ce..b9729a7c 100644 --- a/sdks/typescript-sdk-cli/test/table.test.ts +++ b/sdks/typescript-sdk-cli/test/table.test.ts @@ -139,17 +139,31 @@ describe('renderTable', () => { totalPorts: 2, }; - for (const command of ['containers.route', 'containers.map']) { - const lines = renderTable(command, route).split('\n'); - const header = lines.find((line) => line.includes('Seq')); - expect(header).toMatch( - /Seq.*Label.*Port.*Country.*Inbound ETA.*Inbound ATA.*Outbound ETD.*Outbound ATD/, - ); - const pol = lines.findIndex((line) => line.includes('Laem Chabang')); - const pod = lines.findIndex((line) => line.includes('Savannah')); - expect(lines[pol]).toMatch(/1.*POL.*Laem Chabang.*TH.*2025-11-08/); - expect(lines[pod]).toMatch(/3.*POD.*Savannah.*US.*2025-12-31/); - expect(pol).toBeLessThan(pod); - } + const lines = renderTable('containers.route', route).split('\n'); + const header = lines.find((line) => line.includes('Seq')); + expect(header).toMatch( + /Seq.*Label.*Port.*Country.*Inbound ETA.*Inbound ATA.*Outbound ETD.*Outbound ATD/, + ); + const pol = lines.findIndex((line) => line.includes('Laem Chabang')); + const pod = lines.findIndex((line) => line.includes('Savannah')); + expect(lines[pol]).toMatch(/1.*POL.*Laem Chabang.*TH.*2025-11-08/); + expect(lines[pod]).toMatch(/3.*POD.*Savannah.*US.*2025-12-31/); + expect(pol).toBeLessThan(pod); + }); + + it('does not render containers map GeoJSON as route ports', () => { + const geojson = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [100.88, 13.08] }, + properties: { feature_type: 'port', name: 'Laem Chabang' }, + }, + ], + }; + const table = renderTable('containers.map', geojson); + expect(table).toMatch(/│ FeatureCollection │/); + expect(table).not.toMatch(/Seq.*Label/); }); }); diff --git a/sdks/typescript-sdk/src/client.mapping.test.ts b/sdks/typescript-sdk/src/client.mapping.test.ts index 89bf45f3..37efc8aa 100644 --- a/sdks/typescript-sdk/src/client.mapping.test.ts +++ b/sdks/typescript-sdk/src/client.mapping.test.ts @@ -572,7 +572,7 @@ describe('Terminal49Client mapping helpers', () => { }); }); - it('keeps the GeoJSON body as the raw half and serves map() as an alias', async () => { + it('keeps the GeoJSON body as the raw half, and map() still returns GeoJSON', async () => { const fixture = loadFixture('containers.map_geojson'); const { fetchImpl, calls } = createMockFetch({ '/containers/cont-1/map_geojson': () => jsonResponse(fixture), @@ -587,7 +587,7 @@ describe('Terminal49Client mapping helpers', () => { const viaMap = await client.containers.map('cont-1', { format: 'mapped' }); expect(both.raw).toEqual(fixture); - expect(viaMap).toEqual(both.mapped); + expect(viaMap).toEqual(fixture); expect(calls.map((c) => c.url.pathname)).toEqual([ '/v2/containers/cont-1/map_geojson', '/v2/containers/cont-1/map_geojson', diff --git a/sdks/typescript-sdk/src/client/managers/containers.ts b/sdks/typescript-sdk/src/client/managers/containers.ts index 48ab8490..d9159ef3 100644 --- a/sdks/typescript-sdk/src/client/managers/containers.ts +++ b/sdks/typescript-sdk/src/client/managers/containers.ts @@ -151,9 +151,13 @@ export class ContainerManager extends BaseManager { return this.formatResult(raw, options?.format, mapContainerRoute); } - /** @deprecated Use {@link ContainerManager.route}. */ + /** + * @deprecated Use {@link ContainerManager.route}. Returns the GeoJSON + * FeatureCollection in every format. + */ async map(id: string, options?: CallOptions): Promise { - return this.route(id, options); + const raw = await this.route(id, { format: 'raw' }); + return this.formatResult(raw, options?.format); } /** Create a custom field value on a container. */ From f72fcafa422e47acfd10e86d4744e1a1b255b111 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 11:07:53 -0700 Subject: [PATCH 11/14] chore(cli): drop the stale containers route 404 fixture containers.route.error.json recorded the 404 page from the removed /containers/{id}/route endpoint, and no test reads it. The capture script now saves containers route stdout as containers.route.json. Co-Authored-By: Claude Opus 5.5 --- .../scripts/capture-live-fixtures.sh | 2 +- .../test/fixtures/api/live/containers.route.error.json | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 sdks/typescript-sdk-cli/test/fixtures/api/live/containers.route.error.json diff --git a/sdks/typescript-sdk-cli/scripts/capture-live-fixtures.sh b/sdks/typescript-sdk-cli/scripts/capture-live-fixtures.sh index 516a17fe..4fac18fc 100755 --- a/sdks/typescript-sdk-cli/scripts/capture-live-fixtures.sh +++ b/sdks/typescript-sdk-cli/scripts/capture-live-fixtures.sh @@ -83,7 +83,7 @@ if [[ -n "$port_code" ]]; then fi set +e -run_dev containers route "$container_id" --json > /tmp/t49.route.out 2> "$API_FIXTURES/containers.route.error.json" +run_dev containers route "$container_id" --json > "$API_FIXTURES/containers.route.json" 2> /tmp/t49.route.err run_dev containers map "$container_id" --json > /tmp/t49.map.out 2> "$API_FIXTURES/containers.map.error.json" run_dev custom-fields list --page-size 2 --json > /tmp/t49.custom-fields.out 2> "$API_FIXTURES/custom-fields.list.error.json" run_dev webhook-notifications examples --json > /tmp/t49.webhook-examples.out 2> "$API_FIXTURES/webhook-notifications.examples.error.json" diff --git a/sdks/typescript-sdk-cli/test/fixtures/api/live/containers.route.error.json b/sdks/typescript-sdk-cli/test/fixtures/api/live/containers.route.error.json deleted file mode 100644 index aeae7688..00000000 --- a/sdks/typescript-sdk-cli/test/fixtures/api/live/containers.route.error.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ok": false, - "command": "containers.route", - "error": { - "code": "NOT_FOUND", - "message": "\n\n\n The page you were looking for doesn't exist (404)\n \n \n\n\n\n \n
\n
\n

The page you were looking for doesn't exist.

\n

You may have mistyped the address or the page may have moved.

\n
\n

If you are the application owner check the logs for more information.

\n
\n\n\n", - "status": 404, - "details": "\n\n\n The page you were looking for doesn't exist (404)\n \n \n\n\n\n \n
\n
\n

The page you were looking for doesn't exist.

\n

You may have mistyped the address or the page may have moved.

\n
\n

If you are the application owner check the logs for more information.

\n
\n\n\n" - } -} From 34cc7f231e7a78358a8e0eb9412c08da4073fff9 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 11:07:53 -0700 Subject: [PATCH 12/14] docs: describe ContainerRoute in the SDK quickstart The quickstart still described routes as locations with inbound and outbound legs. It now describes the ordered ports with arrival and departure times and the current vessel. Regenerated the SDK reference for the updated containers.map() JSDoc. Co-Authored-By: Claude Opus 5.5 --- docs/sdk/quickstart.mdx | 2 +- .../sdk/reference/client/managers/classes/ContainerManager.mdx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/sdk/quickstart.mdx b/docs/sdk/quickstart.mdx index 2366ed1b..88388208 100644 --- a/docs/sdk/quickstart.mdx +++ b/docs/sdk/quickstart.mdx @@ -72,7 +72,7 @@ main(); **Events** are individual milestones: gate out, vessel departure, discharge, and more. Each event has a timestamp, location, and description. -**Routes** show the planned and actual journey, broken into locations with inbound and outbound legs. +**Routes** list the ports a container visits, in order, with arrival and departure times for each port. When the container is at sea, the route also includes the current vessel. ## Next steps diff --git a/docs/sdk/reference/client/managers/classes/ContainerManager.mdx b/docs/sdk/reference/client/managers/classes/ContainerManager.mdx index 5e7f1e01..cb402220 100644 --- a/docs/sdk/reference/client/managers/classes/ContainerManager.mdx +++ b/docs/sdk/reference/client/managers/classes/ContainerManager.mdx @@ -191,7 +191,8 @@ Remove a custom field value from a container. #### Deprecated -Use [ContainerManager.route](#route). +Use [ContainerManager.route](#route). Returns the GeoJSON +FeatureCollection in every format. *** From 8bc8d7c85393bfe9a11605dbc4d25eeb89986f85 Mon Sep 17 00:00:00 2001 From: Akshay Dodeja Date: Wed, 14 Oct 2026 14:06:31 -0700 Subject: [PATCH 13/14] fix(sdk)!: address review findings and send booking_number from trackContainer An adversarial review of this branch upheld these defects, each by at least two of three independent reviewers: - Spec: parties create/update bodies lacked `data.type`; the container PATCH body lacked `id`/`type`; custom_field_value rejected non-empty objects. Types are regenerated. - SDK: trackContainer sent `bill_of_lading` for booking numbers. webhookNotifications.list/get accept `include`, and the custom field entityType filter accepts TrackingRequest. containers.map() keeps its 0.5.0 output for every format. - MCP: get_container_route returns the vessel position timestamp and the departure and arrival port names. - CLI: the route table shows the current vessel and handles raw output; map's README claims match each output mode. - Tests now assert return values for the new and migrated methods, and the route, NoRouteData, and trackContainer edge cases. - Docs: methods.mdx lists every new method, and the removed Route reference page redirects. BREAKING CHANGE: trackContainer({ bookingNumber }) now sends request_type "booking_number". Pass bill of lading numbers with the new billOfLading input. Co-Authored-By: Claude Opus 5.5 --- docs/docs.json | 12 +- docs/openapi.json | 27 +- docs/sdk/methods.mdx | 156 +++++++- .../client/classes/Terminal49Client.mdx | 29 +- docs/sdk/reference/client/index.mdx | 2 + .../CustomFieldDefinitionListFilters.mdx | 2 +- .../interfaces/CustomFieldListFilters.mdx | 2 +- .../WebhookNotificationGetOptions.mdx | 18 + .../WebhookNotificationListOptions.mdx | 22 ++ .../managers/classes/ContainerManager.mdx | 5 +- .../classes/DocumentSchemaManager.mdx | 2 +- .../managers/classes/ShipmentManager.mdx | 2 +- .../classes/TrackingRequestManager.mdx | 4 +- docs/sdk/reference/types/models/index.mdx | 1 + .../types/models/interfaces/RouteVessel.mdx | 5 +- .../models/interfaces/RouteVesselPort.mdx | 15 + docs/sdk/reference/types/options/index.mdx | 1 + .../types/options/interfaces/CallOptions.mdx | 1 + .../types/options/interfaces/ListOptions.mdx | 4 + .../WebhookNotificationInclude.mdx | 7 + packages/mcp/eval/client.test.ts | 45 +++ packages/mcp/eval/client.ts | 10 +- packages/mcp/eval/tools.eval.ts | 2 +- packages/mcp/src/server.ts | 2 +- packages/mcp/src/test/route-fixture.ts | 1 + packages/mcp/src/tools/contracts.test.ts | 133 +++++++ packages/mcp/src/tools/get-container-route.ts | 14 +- sdks/typescript-sdk-cli/README.md | 2 +- sdks/typescript-sdk-cli/src/output/table.ts | 86 +++-- .../test/regression.test.ts | 71 +++- sdks/typescript-sdk-cli/test/table.test.ts | 136 ++++--- sdks/typescript-sdk/README.md | 15 +- .../src/client.custom-fields.test.ts | 34 ++ .../typescript-sdk/src/client.mapping.test.ts | 23 +- sdks/typescript-sdk/src/client.test.ts | 39 ++ sdks/typescript-sdk/src/client.ts | 94 +++-- .../src/client.write-endpoints.test.ts | 341 +++++++++++++++++- .../src/client/managers/containers.ts | 8 +- .../src/client/managers/documents.ts | 2 +- sdks/typescript-sdk/src/client/mappers.ts | 13 +- .../src/generated/terminal49.ts | 12 +- sdks/typescript-sdk/src/spec-types.test.ts | 33 ++ sdks/typescript-sdk/src/types/models.ts | 15 +- sdks/typescript-sdk/src/types/options.ts | 2 + 44 files changed, 1273 insertions(+), 177 deletions(-) create mode 100644 docs/sdk/reference/client/interfaces/WebhookNotificationGetOptions.mdx create mode 100644 docs/sdk/reference/client/interfaces/WebhookNotificationListOptions.mdx create mode 100644 docs/sdk/reference/types/models/interfaces/RouteVesselPort.mdx create mode 100644 docs/sdk/reference/types/options/type-aliases/WebhookNotificationInclude.mdx create mode 100644 packages/mcp/eval/client.test.ts create mode 100644 sdks/typescript-sdk/src/spec-types.test.ts diff --git a/docs/docs.json b/docs/docs.json index 9ac6ddf6..e7646fa3 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -410,7 +410,9 @@ "sdk/reference/client/interfaces/CustomFieldListFilters", "sdk/reference/client/interfaces/TriggerWebhookParams", "sdk/reference/client/interfaces/VesselFuturePositionsParams", - "sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams" + "sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams", + "sdk/reference/client/interfaces/WebhookNotificationGetOptions", + "sdk/reference/client/interfaces/WebhookNotificationListOptions" ] }, { @@ -477,6 +479,7 @@ "sdk/reference/types/models/interfaces/RouteCoordinates", "sdk/reference/types/models/interfaces/RoutePort", "sdk/reference/types/models/interfaces/RouteVessel", + "sdk/reference/types/models/interfaces/RouteVesselPort", "sdk/reference/types/models/interfaces/Shipment", "sdk/reference/types/models/interfaces/ShippingLine", "sdk/reference/types/models/interfaces/TrackingRequest" @@ -493,7 +496,8 @@ "sdk/reference/types/options/type-aliases/IncludeParam", "sdk/reference/types/options/type-aliases/ResponseFormat", "sdk/reference/types/options/type-aliases/ShipmentInclude", - "sdk/reference/types/options/type-aliases/TrackingRequestInclude" + "sdk/reference/types/options/type-aliases/TrackingRequestInclude", + "sdk/reference/types/options/type-aliases/WebhookNotificationInclude" ] } ] @@ -656,6 +660,10 @@ { "source": "/api-docs/getting-started/migrate-from-searates", "destination": "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/migrate/searates" + }, + { + "source": "/sdk/reference/types/models/interfaces/Route", + "destination": "/sdk/reference/types/models/interfaces/ContainerRoute" } ], "contextual": { diff --git a/docs/openapi.json b/docs/openapi.json index 9cabd5c4..778838ab 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -7715,6 +7715,16 @@ "type" ], "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "type": { + "type": "string", + "enum": [ + "container" + ] + }, "attributes": { "type": "object", "properties": { @@ -9811,9 +9821,16 @@ "data": { "type": "object", "required": [ + "type", "attributes" ], "properties": { + "type": { + "type": "string", + "enum": [ + "party" + ] + }, "attributes": { "type": "object", "properties": { @@ -12110,9 +12127,16 @@ "data": { "type": "object", "required": [ + "type", "attributes" ], "properties": { + "type": { + "type": "string", + "enum": [ + "party" + ] + }, "attributes": { "type": "object", "properties": { @@ -17170,7 +17194,8 @@ } }, { - "type": "object" + "type": "object", + "additionalProperties": true } ] }, diff --git a/docs/sdk/methods.mdx b/docs/sdk/methods.mdx index d32c2070..c525cbe5 100644 --- a/docs/sdk/methods.mdx +++ b/docs/sdk/methods.mdx @@ -29,6 +29,13 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | `client.shipments.update(id, attrs, options?)` | Update shipment attributes like reference numbers or tags. | | `client.shipments.stopTracking(id, options?)` | Stop tracking a shipment and its containers. | | `client.shipments.resumeTracking(id, options?)` | Resume tracking a previously stopped shipment. | +| `client.shipments.customFields(id, options?)` | `GET /shipments/{id}/custom_fields`. List the custom field values set on the shipment, with their definitions. | +| `client.shipments.setCustomField(id, apiSlug, value, options?)` | `POST /shipments/{id}/custom_fields`. Set a custom field value on the shipment. | +| `client.shipments.updateCustomField(id, apiSlug, value, options?)` | `PATCH /shipments/{id}/custom_fields/{api_slug}`. Update an existing custom field value on the shipment. | +| `client.shipments.deleteCustomField(id, apiSlug, options?)` | `DELETE /shipments/{id}/custom_fields/{api_slug}`. Remove a custom field value from the shipment. | +| `client.shipments.partyRoles(id, options?)` | `GET /shipments/{id}/party_roles`. List the party roles assigned to the shipment. | +| `client.shipments.addPartyRole(id, { role, partyId }, options?)` | `POST /shipments/{id}/party_roles`. Assign a party to the shipment in the given role. | +| `client.shipments.removePartyRole(id, partyRoleId, options?)` | `DELETE /shipments/{id}/party_roles/{id}`. Remove a party role assignment from the shipment. | ### Containers @@ -37,9 +44,17 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | `client.containers.get(id, include?, options?)` | Fetch a container by ID. `include` is an array of related resources. | | `client.containers.list(filters?, options?)` | List containers matching filter criteria. | | `client.containers.events(id, options?)` | Get transport events for a container. | -| `client.containers.route(id, options?)` | Get the container's route from `GET /containers/{id}/map_geojson`. `raw` returns the GeoJSON FeatureCollection. `mapped` returns `{ ports, currentVessel, totalPorts }`, with ports in route order and their arrival and departure times. Requires the Routing Data feature. `client.containers.map` is deprecated and always returns the GeoJSON FeatureCollection. | +| `client.containers.route(id, options?)` | Get the container's route from `GET /containers/{id}/map_geojson`. `raw` returns the GeoJSON FeatureCollection. `mapped` returns `{ ports, currentVessel, totalPorts }`, with ports in route order and their arrival and departure times. Requires the Routing Data feature. `client.containers.map` is deprecated. It returns the GeoJSON FeatureCollection without mapping, so `both` returns `{ raw, mapped }` with the FeatureCollection in each half. | | `client.containers.rawEvents(id, options?)` | Get unprocessed events as received from carriers. | | `client.containers.refresh(id, options?)` | Request an immediate data refresh from the carrier. | +| `client.containers.update(id, attrs, options?)` | `PATCH /containers/{id}`. Update container attributes such as `ref_numbers`. | +| `client.containers.customFields(id, options?)` | `GET /containers/{id}/custom_fields`. List the custom field values set on the container, with their definitions. | +| `client.containers.setCustomField(id, apiSlug, value, options?)` | `POST /containers/{id}/custom_fields`. Set a custom field value on the container. | +| `client.containers.updateCustomField(id, apiSlug, value, options?)` | `PATCH /containers/{id}/custom_fields/{api_slug}`. Update an existing custom field value on the container. | +| `client.containers.deleteCustomField(id, apiSlug, options?)` | `DELETE /containers/{id}/custom_fields/{api_slug}`. Remove a custom field value from the container. | +| `client.containers.partyRoles(id, options?)` | `GET /containers/{id}/party_roles`. List the party roles assigned to the container. | +| `client.containers.addPartyRole(id, { role, partyId }, options?)` | `POST /containers/{id}/party_roles`. Assign a party to the container in the given role. | +| `client.containers.removePartyRole(id, partyRoleId, options?)` | `DELETE /containers/{id}/party_roles/{id}`. Remove a party role assignment from the container. | ### Tracking requests @@ -51,6 +66,10 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | `client.trackingRequests.create(params)` | Create a tracking request with an explicit request type and SCAC. | | `client.trackingRequests.inferNumber(number)` | Detect whether a number is a container, booking, or bill of lading. | | `client.trackingRequests.createFromInfer(number, options?)` | Create a tracking request with automatic number type detection. | +| `client.trackingRequests.customFields(id, options?)` | `GET /tracking_requests/{id}/custom_fields`. List the custom field values set on the tracking request, with their definitions. | +| `client.trackingRequests.setCustomField(id, apiSlug, value, options?)` | `POST /tracking_requests/{id}/custom_fields`. Set a custom field value on the tracking request. | +| `client.trackingRequests.updateCustomField(id, apiSlug, value, options?)` | `PATCH /tracking_requests/{id}/custom_fields/{api_slug}`. Update an existing custom field value on the tracking request. | +| `client.trackingRequests.deleteCustomField(id, apiSlug, options?)` | `DELETE /tracking_requests/{id}/custom_fields/{api_slug}`. Remove a custom field value from the tracking request. | ### Vessels @@ -66,12 +85,110 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each | Method | Description | |--------|-------------| | `client.shippingLines.list(search?, options?)` | List carriers. Use `search` to filter by name or SCAC. | +| `client.shippingLines.get(id, options?)` | Fetch a carrier by ID. | + +### Webhooks + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.webhooks.list(options?)` | `GET /webhooks` | List webhooks. Supports pagination. | +| `client.webhooks.get(id, options?)` | `GET /webhooks/{id}` | Fetch a webhook. | +| `client.webhooks.create(payload, options?)` | `POST /webhooks` | Create a webhook. `payload` is the JSON:API request body. | +| `client.webhooks.update(id, payload, options?)` | `PATCH /webhooks/{id}` | Update a webhook. `payload` is the JSON:API request body. | +| `client.webhooks.delete(id, options?)` | `DELETE /webhooks/{id}` | Delete a webhook. | +| `client.webhooks.ips(options?)` | `GET /webhooks/ips` | List the IP ranges that webhook deliveries come from. | +| `client.webhooks.events(options?)` | `GET /webhooks/events` | List the event names a webhook can subscribe to. | +| `client.webhooks.trigger({ url, event, secret?, documentType? }, options?)` | `POST /webhooks/trigger` | Send a test delivery with an example payload for `event` to `url`. Set `secret` to sign the request. Set `documentType` for `document_representation.*` events. | + +### Webhook notifications + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.webhookNotifications.list(options?)` | `GET /webhook_notifications` | List webhook notifications. Supports pagination and `options.include`. | +| `client.webhookNotifications.get(id, options?)` | `GET /webhook_notifications/{id}` | Fetch a webhook notification. Pass `options.include` to sideload relationships. | +| `client.webhookNotifications.examples(event?, options?)` | `GET /webhook_notifications/examples` | Get example notification payloads. Set `event` to get the examples for one event. | + +### Ports, terminals, and metro areas + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.ports.get(id, options?)` | `GET /ports/{id}` | Fetch a port. | +| `client.terminals.get(id, options?)` | `GET /terminals/{id}` | Fetch a terminal. | +| `client.metroAreas.get(id, options?)` | `GET /metro_areas/{id}` | Fetch a metro area. | + +### Parties + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.parties.list(options?)` | `GET /parties` | List parties. Supports pagination. | +| `client.parties.get(id, options?)` | `GET /parties/{id}` | Fetch a party. | +| `client.parties.create(attributes, options?)` | `POST /parties` | Create a party, such as `{ company_name: 'ACME' }`. | +| `client.parties.update(id, attributes, options?)` | `PATCH /parties/{id}` | Update a party's attributes. | + +### Custom field definitions + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.customFieldDefinitions.list(options?)` | `GET /custom_field_definitions` | List definitions. Filter with `options.filters` by `entityType`, `dataType`, or `displayName`. | +| `client.customFieldDefinitions.get(id, options?)` | `GET /custom_field_definitions/{id}` | Fetch a definition. | +| `client.customFieldDefinitions.create(payload, options?)` | `POST /custom_field_definitions` | Create a definition. `payload` is the JSON:API request body. | +| `client.customFieldDefinitions.update(id, payload, options?)` | `PATCH /custom_field_definitions/{id}` | Update a definition. `payload` is the JSON:API request body. | +| `client.customFieldDefinitions.delete(id, options?)` | `DELETE /custom_field_definitions/{id}` | Delete a definition. | + +### Custom field options + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.customFieldOptions.list(definitionId, options?)` | `GET /custom_field_definitions/{id}/options` | List the options of a definition. Supports pagination. | +| `client.customFieldOptions.get(definitionId, optionId, options?)` | `GET /custom_field_definitions/{id}/options/{option_id}` | Fetch an option. | +| `client.customFieldOptions.create(definitionId, payload, options?)` | `POST /custom_field_definitions/{id}/options` | Create an option. `payload` is the JSON:API request body. | +| `client.customFieldOptions.update(definitionId, optionId, payload, options?)` | `PATCH /custom_field_definitions/{id}/options/{option_id}` | Update an option. `payload` is the JSON:API request body. | +| `client.customFieldOptions.delete(definitionId, optionId, options?)` | `DELETE /custom_field_definitions/{id}/options/{option_id}` | Delete an option. | + +### Custom fields + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.customFields.list(options?)` | `GET /custom_fields` | List custom field values. Filter with `options.filters` by `entityType`, `entityId`, or `definitionId`. | +| `client.customFields.get(id, options?)` | `GET /custom_fields/{id}` | Fetch a custom field value. | +| `client.customFields.create(payload, options?)` | `POST /custom_fields` | Create a custom field value. `payload` is the JSON:API request body. | +| `client.customFields.update(id, payload, options?)` | `PATCH /custom_fields/{id}` | Update a custom field value. `payload` is the JSON:API request body. | +| `client.customFields.delete(id, options?)` | `DELETE /custom_fields/{id}` | Delete a custom field value. | + +### Documents + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.documents.list(filters?, options?)` | `GET /documents` | List documents. Filter by `filename`, `reference`, or `documentTypes`, and set `sort` and `include`. | +| `client.documents.get(id, options?)` | `GET /documents/{id}` | Fetch a document. Pass `options.include` to sideload relationships. | +| `client.documents.create({ name, attachedDocument }, options?)` | `POST /documents` | Create a document from a direct-uploaded blob. `attachedDocument` is the signed blob ID. | +| `client.documents.update(id, { documentTypeManual?, extractedDataManual? }, options?)` | `PATCH /documents/{id}` | Override the document type or the extracted data. Pass `extractedDataManual: null` to clear manually provided extracted data. | +| `client.documents.delete(id, options?)` | `DELETE /documents/{id}` | Delete a document. | +| `client.documents.types(options?)` | `GET /documents/types` | List the document types Terminal49 can classify. | +| `client.documents.downloadUrl(id, options?)` | `GET /documents/{id}/download_url` | Get a short-lived download URL for the document's file. | +| `client.documents.reextract(id, options?)` | `POST /documents/{id}/reextract` | Run data extraction again. | +| `client.documents.reclassify(id, options?)` | `POST /documents/{id}/reclassify` | Run classification again. | +| `client.documents.relink(id, options?)` | `POST /documents/{id}/relink` | Link the document to shipments and containers again. | +| `client.documents.rotate(id, degrees, options?)` | `POST /documents/{id}/rotate` | Rotate the pages by `90`, `180`, or `270` degrees. | + +### Email submissions + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.emailSubmissions.list(options?)` | `GET /email_submissions` | List documents sent to your Terminal49 inbox. Supports pagination and `options.include`. | +| `client.emailSubmissions.get(id, options?)` | `GET /email_submissions/{id}` | Fetch an email submission. Pass `options.include` to sideload relationships. | + +### Document schemas + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `client.documentSchemas.get(id, options?)` | `GET /document_schemas/{id}` | Fetch an extraction schema by its versioned id, `@`, such as `commercial_invoice@2026-03-23`. | ## Helpers and aliases | Method | Description | |--------|-------------| -| `client.trackContainer(params)` | Convenience helper that creates a tracking request using a container or booking number. | +| `client.trackContainer(params)` | Convenience helper that creates a tracking request from `containerNumber`, `bookingNumber`, or `billOfLading`. It sends `request_type` `container`, `booking_number`, or `bill_of_lading` to match. | | `client.listTrackRequests(filters?, options?)` | Alias for `client.trackingRequests.list`. | | `client.getDemurrage(containerId)` | Returns a subset of demurrage-related fields for a container. See [holds, fees, and release readiness](/api-docs/in-depth-guides/holds-and-fees) for context. | | `client.getRailMilestones(containerId)` | Returns rail milestones derived from transport events. | @@ -79,7 +196,7 @@ The SDK exposes a `Terminal49Client` with methods grouped by resource type. Each ## Direct method equivalents -All namespace methods are also available as direct methods on the client: +The namespace methods in this table are also available as direct methods on the client. Other namespace methods, such as `client.shippingLines.get` and the `client.documents`, `client.emailSubmissions`, and `client.documentSchemas` methods, have no direct method. | Namespace method | Direct method | |------------------|--------------| @@ -105,6 +222,39 @@ All namespace methods are also available as direct methods on the client: | `client.vessels.getByImo` | `client.getVesselByImo` | | `client.vessels.futurePositions` | `client.getVesselFuturePositions` | | `client.vessels.futurePositionsWithCoords` | `client.getVesselFuturePositionsWithCoords` | +| `client.webhooks.list` | `client.listWebhooks` | +| `client.webhooks.get` | `client.getWebhook` | +| `client.webhooks.create` | `client.createWebhook` | +| `client.webhooks.update` | `client.updateWebhook` | +| `client.webhooks.delete` | `client.deleteWebhook` | +| `client.webhooks.ips` | `client.getWebhookIps` | +| `client.webhooks.events` | `client.listWebhookEvents` | +| `client.webhooks.trigger` | `client.triggerWebhook` | +| `client.webhookNotifications.list` | `client.listWebhookNotifications` | +| `client.webhookNotifications.get` | `client.getWebhookNotification` | +| `client.webhookNotifications.examples` | `client.getWebhookNotificationExamples` | +| `client.ports.get` | `client.getPort` | +| `client.terminals.get` | `client.getTerminal` | +| `client.metroAreas.get` | `client.getMetroArea` | +| `client.parties.list` | `client.listParties` | +| `client.parties.get` | `client.getParty` | +| `client.parties.create` | `client.createParty` | +| `client.parties.update` | `client.updateParty` | +| `client.customFieldDefinitions.list` | `client.listCustomFieldDefinitions` | +| `client.customFieldDefinitions.get` | `client.getCustomFieldDefinition` | +| `client.customFieldDefinitions.create` | `client.createCustomFieldDefinition` | +| `client.customFieldDefinitions.update` | `client.updateCustomFieldDefinition` | +| `client.customFieldDefinitions.delete` | `client.deleteCustomFieldDefinition` | +| `client.customFieldOptions.list` | `client.listCustomFieldOptions` | +| `client.customFieldOptions.get` | `client.getCustomFieldOption` | +| `client.customFieldOptions.create` | `client.createCustomFieldOption` | +| `client.customFieldOptions.update` | `client.updateCustomFieldOption` | +| `client.customFieldOptions.delete` | `client.deleteCustomFieldOption` | +| `client.customFields.list` | `client.listCustomFields` | +| `client.customFields.get` | `client.getCustomField` | +| `client.customFields.create` | `client.createCustomField` | +| `client.customFields.update` | `client.updateCustomField` | +| `client.customFields.delete` | `client.deleteCustomField` | ## Common options diff --git a/docs/sdk/reference/client/classes/Terminal49Client.mdx b/docs/sdk/reference/client/classes/Terminal49Client.mdx index 7305d453..f661bd63 100644 --- a/docs/sdk/reference/client/classes/Terminal49Client.mdx +++ b/docs/sdk/reference/client/classes/Terminal49Client.mdx @@ -56,10 +56,10 @@ data from Node.js applications. | `metroAreas` | `public` | `object` | | `metroAreas.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `parties` | `public` | `object` | -| `parties.create` | `public` | (`payload`, `options?`) => `Promise`\<`any`\> | +| `parties.create` | `public` | (`attributes`, `options?`) => `Promise`\<`any`\> | | `parties.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `parties.list` | `public` | (`options?`) => `Promise`\<`any`\> | -| `parties.update` | `public` | (`id`, `payload`, `options?`) => `Promise`\<`any`\> | +| `parties.update` | `public` | (`id`, `attributes`, `options?`) => `Promise`\<`any`\> | | `ports` | `public` | `object` | | `ports.get` | `public` | (`id`, `options?`) => `Promise`\<`any`\> | | `shipments` | `public` | [`ShipmentManager`](/sdk/reference/client/managers/classes/ShipmentManager) | @@ -148,7 +148,7 @@ Create a custom field option. ### createParty() -> **createParty**(`payload`, `options?`): `Promise`\<`any`\> +> **createParty**(`attributes`, `options?`): `Promise`\<`any`\> Create a party. @@ -156,10 +156,8 @@ Create a party. | Parameter | Type | Description | | ------ | ------ | ------ | -| `payload` | \{ `data?`: \{ `attributes`: \{ `company_name?`: `string`; \}; \}; \} | - | -| `payload.data?` | \{ `attributes`: \{ `company_name?`: `string`; \}; \} | - | -| `payload.data.attributes?` | \{ `company_name?`: `string`; \} | - | -| `payload.data.attributes.company_name?` | `string` | **Description** The name of the company **Example** `COMPANY NAME` | +| `attributes` | \{ `company_name?`: `string`; \} | - | +| `attributes.company_name?` | `string` | **Description** The name of the company **Example** `COMPANY NAME` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | - | #### Returns @@ -749,7 +747,7 @@ Fetch a webhook notification by ID. | Parameter | Type | | ------ | ------ | | `id` | `string` | -| `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | +| `options?` | [`WebhookNotificationGetOptions`](/sdk/reference/client/interfaces/WebhookNotificationGetOptions) | #### Returns @@ -990,7 +988,7 @@ List webhook notifications. | Parameter | Type | | ------ | ------ | -| `options?` | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) | +| `options?` | [`WebhookNotificationListOptions`](/sdk/reference/client/interfaces/WebhookNotificationListOptions) | #### Returns @@ -1095,14 +1093,15 @@ Stop tracking a shipment and its containers. > **trackContainer**(`params`): `Promise`\<`any`\> -Convenience helper for creating a tracking request from a container or booking number. +Convenience helper for creating a tracking request from a container, booking, or bill of lading number. #### Parameters | Parameter | Type | | ------ | ------ | -| `params` | \{ `autoDetectVoccScac?`: `boolean`; `bookingNumber?`: `string`; `containerNumber?`: `string`; `refNumbers?`: `string`[]; `scac?`: `string`; \} | +| `params` | \{ `autoDetectVoccScac?`: `boolean`; `billOfLading?`: `string`; `bookingNumber?`: `string`; `containerNumber?`: `string`; `refNumbers?`: `string`[]; `scac?`: `string`; \} | | `params.autoDetectVoccScac?` | `boolean` | +| `params.billOfLading?` | `string` | | `params.bookingNumber?` | `string` | | `params.containerNumber?` | `string` | | `params.refNumbers?` | `string`[] | @@ -1196,7 +1195,7 @@ Update a custom field option. ### updateParty() -> **updateParty**(`id`, `payload`, `options?`): `Promise`\<`any`\> +> **updateParty**(`id`, `attributes`, `options?`): `Promise`\<`any`\> Update a party. @@ -1205,10 +1204,8 @@ Update a party. | Parameter | Type | Description | | ------ | ------ | ------ | | `id` | `string` | - | -| `payload` | \{ `data?`: \{ `attributes`: \{ `company_name?`: `string`; \}; \}; \} | - | -| `payload.data?` | \{ `attributes`: \{ `company_name?`: `string`; \}; \} | - | -| `payload.data.attributes?` | \{ `company_name?`: `string`; \} | - | -| `payload.data.attributes.company_name?` | `string` | **Description** The name of the company **Example** `COMPANY NAME` | +| `attributes` | \{ `company_name?`: `string`; \} | - | +| `attributes.company_name?` | `string` | **Description** The name of the company **Example** `COMPANY NAME` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | - | #### Returns diff --git a/docs/sdk/reference/client/index.mdx b/docs/sdk/reference/client/index.mdx index 73f8eb84..fc5273e7 100644 --- a/docs/sdk/reference/client/index.mdx +++ b/docs/sdk/reference/client/index.mdx @@ -31,3 +31,5 @@ description: "Reference index for the Terminal49 TypeScript SDK client module, l | [TriggerWebhookParams](/sdk/reference/client/interfaces/TriggerWebhookParams) | Parameters for [Terminal49Client.triggerWebhook](/sdk/reference/client/classes/Terminal49Client#triggerwebhook). | | [VesselFuturePositionsParams](/sdk/reference/client/interfaces/VesselFuturePositionsParams) | Parameters for [Terminal49Client.getVesselFuturePositions](/sdk/reference/client/classes/Terminal49Client#getvesselfuturepositions). | | [VesselFuturePositionsWithCoordsParams](/sdk/reference/client/interfaces/VesselFuturePositionsWithCoordsParams) | Parameters for [Terminal49Client.getVesselFuturePositionsWithCoords](/sdk/reference/client/classes/Terminal49Client#getvesselfuturepositionswithcoords). | +| [WebhookNotificationGetOptions](/sdk/reference/client/interfaces/WebhookNotificationGetOptions) | Options for [Terminal49Client.getWebhookNotification](/sdk/reference/client/classes/Terminal49Client#getwebhooknotification). | +| [WebhookNotificationListOptions](/sdk/reference/client/interfaces/WebhookNotificationListOptions) | Options for [Terminal49Client.listWebhookNotifications](/sdk/reference/client/classes/Terminal49Client#listwebhooknotifications). | diff --git a/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx b/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx index fcf3dbbb..9ae26250 100644 --- a/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx +++ b/docs/sdk/reference/client/interfaces/CustomFieldDefinitionListFilters.mdx @@ -12,4 +12,4 @@ Filters accepted by `customFieldDefinitions.list`. | ------ | ------ | | `dataType?` | `"number"` \| `"boolean"` \| `"datetime"` \| `"date"` \| `"short_text"` \| `"enum"` \| `"enum_multi"` \| `"reference"` | | `displayName?` | `string` | -| `entityType?` | `"Shipment"` \| `"Container"` | +| `entityType?` | `"Shipment"` \| `"Container"` \| `"TrackingRequest"` | diff --git a/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx b/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx index ac1c23df..859cdb26 100644 --- a/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx +++ b/docs/sdk/reference/client/interfaces/CustomFieldListFilters.mdx @@ -12,4 +12,4 @@ Filters accepted by `customFields.list`. | ------ | ------ | | `definitionId?` | `string` | | `entityId?` | `string` | -| `entityType?` | `"Shipment"` \| `"Container"` | +| `entityType?` | `"Shipment"` \| `"Container"` \| `"TrackingRequest"` | diff --git a/docs/sdk/reference/client/interfaces/WebhookNotificationGetOptions.mdx b/docs/sdk/reference/client/interfaces/WebhookNotificationGetOptions.mdx new file mode 100644 index 00000000..e1ec1d4d --- /dev/null +++ b/docs/sdk/reference/client/interfaces/WebhookNotificationGetOptions.mdx @@ -0,0 +1,18 @@ +--- +title: "Interface: WebhookNotificationGetOptions" +--- + +# Interface: WebhookNotificationGetOptions + +Options for [Terminal49Client.getWebhookNotification](/sdk/reference/client/classes/Terminal49Client#getwebhooknotification). + +## Extends + +- [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) + +## Properties + +| Property | Type | Description | Inherited from | +| ------ | ------ | ------ | ------ | +| `format?` | [`ResponseFormat`](/sdk/reference/types/options/type-aliases/ResponseFormat) | Override the client's default response format for this call. | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions).[`format`](/sdk/reference/types/options/interfaces/CallOptions#property-format) | +| `include?` | [`IncludeParam`](/sdk/reference/types/options/type-aliases/IncludeParam)\<[`WebhookNotificationInclude`](/sdk/reference/types/options/type-aliases/WebhookNotificationInclude)\> | Related resources to sideload. | - | diff --git a/docs/sdk/reference/client/interfaces/WebhookNotificationListOptions.mdx b/docs/sdk/reference/client/interfaces/WebhookNotificationListOptions.mdx new file mode 100644 index 00000000..b1db7180 --- /dev/null +++ b/docs/sdk/reference/client/interfaces/WebhookNotificationListOptions.mdx @@ -0,0 +1,22 @@ +--- +title: "Interface: WebhookNotificationListOptions" +--- + +# Interface: WebhookNotificationListOptions + +Options for [Terminal49Client.listWebhookNotifications](/sdk/reference/client/classes/Terminal49Client#listwebhooknotifications). + +## Extends + +- [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) + +## Properties + +| Property | Type | Description | Inherited from | +| ------ | ------ | ------ | ------ | +| `format?` | [`ResponseFormat`](/sdk/reference/types/options/type-aliases/ResponseFormat) | Override the client's default response format for this call. | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions).[`format`](/sdk/reference/types/options/interfaces/ListOptions#property-format) | +| `include?` | [`IncludeParam`](/sdk/reference/types/options/type-aliases/IncludeParam)\<[`WebhookNotificationInclude`](/sdk/reference/types/options/type-aliases/WebhookNotificationInclude)\> | Related resources to sideload. | - | +| `maxPages?` | `number` | Maximum number of pages `iterate()` will fetch before stopping. Defaults to the manager's safety cap; raise it to walk past the default bound. | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions).[`maxPages`](/sdk/reference/types/options/interfaces/ListOptions#property-maxpages) | +| `maxRows?` | `number` | Maximum number of rows `iterate()` will yield before stopping. Defaults to the manager's safety cap; raise it to walk past the default bound. | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions).[`maxRows`](/sdk/reference/types/options/interfaces/ListOptions#property-maxrows) | +| `page?` | `number` | 1-based page number. | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions).[`page`](/sdk/reference/types/options/interfaces/ListOptions#property-page) | +| `pageSize?` | `number` | Number of records per page. | [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions).[`pageSize`](/sdk/reference/types/options/interfaces/ListOptions#property-pagesize) | diff --git a/docs/sdk/reference/client/managers/classes/ContainerManager.mdx b/docs/sdk/reference/client/managers/classes/ContainerManager.mdx index cb402220..cf5f5aa0 100644 --- a/docs/sdk/reference/client/managers/classes/ContainerManager.mdx +++ b/docs/sdk/reference/client/managers/classes/ContainerManager.mdx @@ -192,7 +192,8 @@ Remove a custom field value from a container. #### Deprecated Use [ContainerManager.route](#route). Returns the GeoJSON -FeatureCollection in every format. +FeatureCollection unmapped: `raw` and `mapped` return it as is, and +`both` returns `{ raw, mapped }` with the FeatureCollection in each half. *** @@ -345,7 +346,7 @@ Update an existing custom field value on a container. | ------ | ------ | | `id` | `string` | | `apiSlug` | `string` | -| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| \{\[`key`: `string`\]: `unknown`; \} \| `null` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns diff --git a/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx b/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx index 2504f196..ded83a81 100644 --- a/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx +++ b/docs/sdk/reference/client/managers/classes/DocumentSchemaManager.mdx @@ -35,7 +35,7 @@ title: "Class: DocumentSchemaManager" > **get**(`id`, `options?`): `Promise`\<`any`\> -Fetch the extraction schema for a document type. +Fetch an extraction schema by its versioned id, `@`, such as `commercial_invoice@2026-03-23`. #### Parameters diff --git a/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx b/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx index 04321a45..28190248 100644 --- a/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx +++ b/docs/sdk/reference/client/managers/classes/ShipmentManager.mdx @@ -265,7 +265,7 @@ Update an existing custom field value on a shipment. | ------ | ------ | | `id` | `string` | | `apiSlug` | `string` | -| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| \{\[`key`: `string`\]: `unknown`; \} \| `null` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns diff --git a/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx b/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx index d9824ec4..bd43da64 100644 --- a/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx +++ b/docs/sdk/reference/client/managers/classes/TrackingRequestManager.mdx @@ -189,7 +189,7 @@ Create a custom field value on a tracking request. | ------ | ------ | | `id` | `string` | | `apiSlug` | `string` | -| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| \{\[`key`: `string`\]: `unknown`; \} \| `null` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns @@ -228,7 +228,7 @@ Update an existing custom field value on a tracking request. | ------ | ------ | | `id` | `string` | | `apiSlug` | `string` | -| `value` | `string` \| `number` \| `boolean` \| `string`[] \| `Record`\<`string`, `never`\> \| `null` | +| `value` | `string` \| `number` \| `boolean` \| `string`[] \| \{\[`key`: `string`\]: `unknown`; \} \| `null` | | `options?` | [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) | #### Returns diff --git a/docs/sdk/reference/types/models/index.mdx b/docs/sdk/reference/types/models/index.mdx index 9c23dd76..c8a94718 100644 --- a/docs/sdk/reference/types/models/index.mdx +++ b/docs/sdk/reference/types/models/index.mdx @@ -17,6 +17,7 @@ description: "Mapped response models in the Terminal49 TypeScript SDK: Container | [RouteCoordinates](/sdk/reference/types/models/interfaces/RouteCoordinates) | A `[longitude, latitude]` GeoJSON point, named so the axis order cannot be swapped. | | [RoutePort](/sdk/reference/types/models/interfaces/RoutePort) | One port on a container route, from a `port` feature of `GET /containers/{id}/map_geojson`. | | [RouteVessel](/sdk/reference/types/models/interfaces/RouteVessel) | The vessel carrying the container right now. Present only while it is at sea. | +| [RouteVesselPort](/sdk/reference/types/models/interfaces/RouteVesselPort) | A port the current vessel left or is heading to, as the `current_vessel` feature names it. | | [Shipment](/sdk/reference/types/models/interfaces/Shipment) | Simplified shipment model returned by mapped SDK responses. | | [ShippingLine](/sdk/reference/types/models/interfaces/ShippingLine) | Simplified shipping line returned by mapped SDK responses. | | [TrackingRequest](/sdk/reference/types/models/interfaces/TrackingRequest) | Simplified tracking request model returned by mapped SDK responses. | diff --git a/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx b/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx index 37394486..c96af269 100644 --- a/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx +++ b/docs/sdk/reference/types/models/interfaces/RouteVessel.mdx @@ -10,11 +10,12 @@ The vessel carrying the container right now. Present only while it is at sea. | Property | Type | Description | | ------ | ------ | ------ | -| `arrivalPortId` | `string` \| `null` | - | +| `arrivalPort` | [`RouteVesselPort`](/sdk/reference/types/models/interfaces/RouteVesselPort) | - | | `coordinates` | [`RouteCoordinates`](/sdk/reference/types/models/interfaces/RouteCoordinates) \| `null` | - | -| `departurePortId` | `string` \| `null` | - | +| `departurePort` | [`RouteVesselPort`](/sdk/reference/types/models/interfaces/RouteVesselPort) | - | | `heading` | `number` \| `null` | Degrees, 0-360. | | `imo` | `string` \| `null` | - | | `name` | `string` \| `null` | - | +| `positionAt` | `string` \| `null` | When the vessel reported `coordinates`, `heading`, and `speed` (ISO 8601). | | `speed` | `number` \| `null` | Knots. | | `voyage` | `string` \| `null` | - | diff --git a/docs/sdk/reference/types/models/interfaces/RouteVesselPort.mdx b/docs/sdk/reference/types/models/interfaces/RouteVesselPort.mdx new file mode 100644 index 00000000..256f9b94 --- /dev/null +++ b/docs/sdk/reference/types/models/interfaces/RouteVesselPort.mdx @@ -0,0 +1,15 @@ +--- +title: "Interface: RouteVesselPort" +--- + +# Interface: RouteVesselPort + +A port the current vessel left or is heading to, as the `current_vessel` feature names it. + +## Properties + +| Property | Type | Description | +| ------ | ------ | ------ | +| `label` | `string` \| `null` | `POL`, `POD`, or `TS1`, `TS2`, and so on for transshipment ports. | +| `locationId` | `string` \| `null` | Matches [RoutePort.locationId](/sdk/reference/types/models/interfaces/RoutePort#property-locationid) of the same port. | +| `name` | `string` \| `null` | - | diff --git a/docs/sdk/reference/types/options/index.mdx b/docs/sdk/reference/types/options/index.mdx index e5094c45..a650d62e 100644 --- a/docs/sdk/reference/types/options/index.mdx +++ b/docs/sdk/reference/types/options/index.mdx @@ -21,3 +21,4 @@ description: "Terminal49 TypeScript SDK option types: CallOptions, ListOptions, | [ResponseFormat](/sdk/reference/types/options/type-aliases/ResponseFormat) | Controls how SDK methods return API responses. | | [ShipmentInclude](/sdk/reference/types/options/type-aliases/ShipmentInclude) | - | | [TrackingRequestInclude](/sdk/reference/types/options/type-aliases/TrackingRequestInclude) | - | +| [WebhookNotificationInclude](/sdk/reference/types/options/type-aliases/WebhookNotificationInclude) | - | diff --git a/docs/sdk/reference/types/options/interfaces/CallOptions.mdx b/docs/sdk/reference/types/options/interfaces/CallOptions.mdx index 53382ef6..9f09a32f 100644 --- a/docs/sdk/reference/types/options/interfaces/CallOptions.mdx +++ b/docs/sdk/reference/types/options/interfaces/CallOptions.mdx @@ -9,6 +9,7 @@ Per-call options accepted by single-resource methods. ## Extended by +- [`WebhookNotificationGetOptions`](/sdk/reference/client/interfaces/WebhookNotificationGetOptions) - [`ListOptions`](/sdk/reference/types/options/interfaces/ListOptions) ## Properties diff --git a/docs/sdk/reference/types/options/interfaces/ListOptions.mdx b/docs/sdk/reference/types/options/interfaces/ListOptions.mdx index cd59f196..534f32b7 100644 --- a/docs/sdk/reference/types/options/interfaces/ListOptions.mdx +++ b/docs/sdk/reference/types/options/interfaces/ListOptions.mdx @@ -11,6 +11,10 @@ Per-call options accepted by list methods. - [`CallOptions`](/sdk/reference/types/options/interfaces/CallOptions) +## Extended by + +- [`WebhookNotificationListOptions`](/sdk/reference/client/interfaces/WebhookNotificationListOptions) + ## Properties | Property | Type | Description | Inherited from | diff --git a/docs/sdk/reference/types/options/type-aliases/WebhookNotificationInclude.mdx b/docs/sdk/reference/types/options/type-aliases/WebhookNotificationInclude.mdx new file mode 100644 index 00000000..035ad74b --- /dev/null +++ b/docs/sdk/reference/types/options/type-aliases/WebhookNotificationInclude.mdx @@ -0,0 +1,7 @@ +--- +title: "Type Alias: WebhookNotificationInclude" +--- + +# Type Alias: WebhookNotificationInclude + +> **WebhookNotificationInclude** = `"webhook"` \| `"reference_object"` diff --git a/packages/mcp/eval/client.test.ts b/packages/mcp/eval/client.test.ts new file mode 100644 index 00000000..5d84c082 --- /dev/null +++ b/packages/mcp/eval/client.test.ts @@ -0,0 +1,45 @@ +import { afterEach, describe, expect, it, vi } from 'vite-plus/test'; +import { EvalClient } from './client.js'; + +afterEach(() => { + vi.unstubAllGlobals(); +}); + +describe('EvalClient.callTool', () => { + it('reads a plain-text soft error from structuredContent', async () => { + const structuredContent = { + error: 'FeatureNotEnabled', + message: 'Routing Data is not enabled for this account.', + alternative: 'Use get_container_transport_events instead.', + }; + vi.stubGlobal( + 'fetch', + async () => + new Response( + JSON.stringify({ + jsonrpc: '2.0', + id: '1', + result: { + content: [ + { + type: 'text', + text: `${structuredContent.message}\n\nAlternative: ${structuredContent.alternative}`, + }, + ], + structuredContent, + }, + }), + { status: 200, headers: { 'Content-Type': 'application/json' } }, + ), + ); + const client = new EvalClient({ + endpoint: 'https://mcp.test/mcp', + scheme: 'Token', + token: 'token-123', + }); + + const result = await client.callTool('get_container_route', { id: 'c-1' }); + + expect(result.payload).toEqual(structuredContent); + }); +}); diff --git a/packages/mcp/eval/client.ts b/packages/mcp/eval/client.ts index 7021067b..35066a87 100644 --- a/packages/mcp/eval/client.ts +++ b/packages/mcp/eval/client.ts @@ -40,7 +40,11 @@ export interface ToolResult { bytes: number; /** Every text content block, JSON parsed where possible. */ blocks: ParsedBlock[]; - /** First JSON block: the tool's primary payload. */ + /** + * First JSON block, else `structuredContent`: the tool's primary payload. + * Soft errors such as FeatureNotEnabled render as plain text, so only + * `structuredContent` carries their fields. + */ payload: unknown; /** JSON-RPC error message, when the transport returned one. */ errorMessage: string | undefined; @@ -236,7 +240,9 @@ export class EvalClient { latencyMs, bytes: texts.reduce((sum, text) => sum + text.length, 0), blocks, - payload: payloadBlock?.json, + payload: + payloadBlock?.json ?? + (isRecord(body.result) ? body.result.structuredContent : undefined), errorMessage: body.error?.message, rawText: texts.join('\n'), }; diff --git a/packages/mcp/eval/tools.eval.ts b/packages/mcp/eval/tools.eval.ts index a7fe2839..c5ec4587 100644 --- a/packages/mcp/eval/tools.eval.ts +++ b/packages/mcp/eval/tools.eval.ts @@ -349,7 +349,7 @@ if (!cfg) { ], }, ); - // Soft-error responses are still HTTP 200 with a JSON payload. + // Soft errors are HTTP 200; FeatureNotEnabled carries its fields only in structuredContent. expect(result.http).toBe(200); expect(result.payload).toBeDefined(); expect(score.contractPass).toBe(true); diff --git a/packages/mcp/src/server.ts b/packages/mcp/src/server.ts index 5d9147ef..22978431 100644 --- a/packages/mcp/src/server.ts +++ b/packages/mcp/src/server.ts @@ -1330,7 +1330,7 @@ export function createTerminal49McpServer( title: 'Get Container Route', description: 'Get the ocean route for a container: ports in order (POL, transshipment ports, POD) with ETA/ATA and ETD/ATD, ' + - 'plus the vessel carrying it now (name, IMO, voyage, position, speed) while it is at sea. ' + + 'plus the vessel carrying it now (name, IMO, voyage, position with the time it was reported, speed) while it is at sea. ' + 'This paid feature (Routing Data) may not be available for every account.', annotations: { readOnlyHint: true, diff --git a/packages/mcp/src/test/route-fixture.ts b/packages/mcp/src/test/route-fixture.ts index be594eb1..421f74f7 100644 --- a/packages/mcp/src/test/route-fixture.ts +++ b/packages/mcp/src/test/route-fixture.ts @@ -47,6 +47,7 @@ export const EXPECTED_ROUTE_SUMMARY: RouteSummary = { longitude: -131.128473333, heading: 108, speed_knots: 21, + position_at: '2025-12-11T11:46:03Z', departure_port: { name: 'Xiamen', label: 'TS1' }, arrival_port: { name: 'Savannah', label: 'POD' }, }, diff --git a/packages/mcp/src/tools/contracts.test.ts b/packages/mcp/src/tools/contracts.test.ts index b4df8adf..960da510 100644 --- a/packages/mcp/src/tools/contracts.test.ts +++ b/packages/mcp/src/tools/contracts.test.ts @@ -1029,6 +1029,139 @@ describe('MCP tool contracts', () => { }); }); + it('get_container_route returns the ports when no vessel position is known', async () => { + const withoutVessel = { + ...routeFixture, + features: routeFixture.features.filter( + (feature: { properties: { feature_type: string } }) => + feature.properties.feature_type !== 'current_vessel', + ), + }; + const client = asClient({ + containers: { + route: vi.fn().mockResolvedValue(mapContainerRoute(withoutVessel)), + }, + }); + + const result = await executeGetContainerRoute( + { id: 'container-1' }, + client, + ); + + expect(result).toEqual({ + ...EXPECTED_ROUTE_SUMMARY, + current_vessel: null, + }); + }); + + it('get_container_route returns the vessel when the route has no ports', async () => { + const vesselOnly = { + ...routeFixture, + features: routeFixture.features.filter( + (feature: { properties: { feature_type: string } }) => + feature.properties.feature_type === 'current_vessel', + ), + }; + const client = asClient({ + containers: { + route: vi.fn().mockResolvedValue(mapContainerRoute(vesselOnly)), + }, + }); + + const result = await executeGetContainerRoute( + { id: 'container-1' }, + client, + ); + + expect(result).toEqual({ + total_ports: 0, + ports: [], + current_vessel: EXPECTED_ROUTE_SUMMARY.current_vessel, + }); + }); + + it('get_container_route names vessel ports from the port features when the vessel omits them', async () => { + const unnamedVesselPorts = { + ...routeFixture, + features: routeFixture.features.map( + (feature: { properties: Record }) => { + if (feature.properties.feature_type !== 'current_vessel') { + return feature; + } + const { + departure_port_name: _departureName, + departure_port_label: _departureLabel, + arrival_port_name: _arrivalName, + arrival_port_label: _arrivalLabel, + ...properties + } = feature.properties; + return { ...feature, properties }; + }, + ), + }; + const client = asClient({ + containers: { + route: vi.fn().mockResolvedValue(mapContainerRoute(unnamedVesselPorts)), + }, + }); + + const result = await executeGetContainerRoute( + { id: 'container-1' }, + client, + ); + + expect(result).toEqual(EXPECTED_ROUTE_SUMMARY); + }); + + it('get_container_route returns null vessel ports when no port feature matches', async () => { + const unresolvableVesselPorts = { + ...routeFixture, + features: routeFixture.features.map( + (feature: { properties: Record }) => { + if (feature.properties.feature_type !== 'current_vessel') { + return feature; + } + const { + departure_port_name: _departureName, + departure_port_label: _departureLabel, + arrival_port_name: _arrivalName, + arrival_port_label: _arrivalLabel, + ...properties + } = feature.properties; + return { + ...feature, + properties: { + ...properties, + departure_port_id: 'unknown-departure', + arrival_port_id: null, + }, + }; + }, + ), + }; + const client = asClient({ + containers: { + route: vi + .fn() + .mockResolvedValue(mapContainerRoute(unresolvableVesselPorts)), + }, + }); + + const result = await executeGetContainerRoute( + { id: 'container-1' }, + client, + ); + + expect(result).toEqual({ + ...EXPECTED_ROUTE_SUMMARY, + current_vessel: { + ...EXPECTED_ROUTE_SUMMARY.current_vessel, + departure_port: null, + arrival_port: null, + }, + }); + }); + it('get_container_route returns a NotFound soft result for an unknown container', async () => { const client = asClient({ containers: { diff --git a/packages/mcp/src/tools/get-container-route.ts b/packages/mcp/src/tools/get-container-route.ts index 6bcc80ad..4a10c22c 100644 --- a/packages/mcp/src/tools/get-container-route.ts +++ b/packages/mcp/src/tools/get-container-route.ts @@ -3,6 +3,7 @@ import { NotFoundError, Terminal49Client, type ContainerRoute, + type RouteVesselPort, } from '@terminal49/sdk'; import { z } from 'zod'; import { logMcpEvent } from '../logging.js'; @@ -62,6 +63,7 @@ const routeSummarySchema = z.object({ longitude: z.number().nullable(), heading: z.number().nullable(), speed_knots: z.number().nullable(), + position_at: z.string().nullable(), departure_port: portRefSchema, arrival_port: portRefSchema, }) @@ -189,9 +191,12 @@ function formatRoute({ currentVessel, totalPorts, }: ContainerRoute): RouteSummary { - const portRef = (id: string | null) => { + const portRef = ({ locationId, name, label }: RouteVesselPort) => { + if (name !== null || label !== null) return { name, label }; const port = - id === null ? undefined : ports.find((p) => p.locationId === id); + locationId === null + ? undefined + : ports.find((p) => p.locationId === locationId); return port ? { name: port.name, label: port.label } : null; }; @@ -213,8 +218,9 @@ function formatRoute({ longitude: currentVessel.coordinates?.longitude ?? null, heading: currentVessel.heading, speed_knots: currentVessel.speed, - departure_port: portRef(currentVessel.departurePortId), - arrival_port: portRef(currentVessel.arrivalPortId), + position_at: currentVessel.positionAt, + departure_port: portRef(currentVessel.departurePort), + arrival_port: portRef(currentVessel.arrivalPort), }, }; } diff --git a/sdks/typescript-sdk-cli/README.md b/sdks/typescript-sdk-cli/README.md index 98309c81..29ecd2a9 100644 --- a/sdks/typescript-sdk-cli/README.md +++ b/sdks/typescript-sdk-cli/README.md @@ -144,7 +144,7 @@ Stable error codes include `USAGE_ERROR`, `NETWORK_ERROR`, `AUTH_ERROR`, `RATE_L ## Commands - `t49 shipments get|list|update|stop-tracking|resume-tracking|custom-fields|set-custom-field` -- `t49 containers get|list|events|route|map|raw-events|refresh|demurrage|rail|custom-fields|set-custom-field` (`map` is deprecated: it prints the raw GeoJSON FeatureCollection, the same as `route --format raw`) +- `t49 containers get|list|events|route|map|raw-events|refresh|demurrage|rail|custom-fields|set-custom-field` (`map` is deprecated: with `--json` it prints the raw GeoJSON FeatureCollection, the same as `route --format raw --json`. In table mode both print only the collection type. In table mode, `route` prints the ports and a Current vessel table.) - `t49 tracking-requests list|get|create|update|infer|create-from-infer` - `t49 track ` - `t49 shipping-lines list` diff --git a/sdks/typescript-sdk-cli/src/output/table.ts b/sdks/typescript-sdk-cli/src/output/table.ts index 315bda4e..e21472d0 100644 --- a/sdks/typescript-sdk-cli/src/output/table.ts +++ b/sdks/typescript-sdk-cli/src/output/table.ts @@ -24,6 +24,17 @@ const ROUTE_PORT_COLUMNS: ColumnDef[] = [ { key: 'outbound.atd', title: 'Outbound ATD' }, ]; +const ROUTE_VESSEL_COLUMNS: ColumnDef[] = [ + { key: 'name', title: 'Vessel' }, + { key: 'imo', title: 'IMO' }, + { key: 'voyage', title: 'Voyage' }, + { key: 'coordinates.latitude', title: 'Latitude' }, + { key: 'coordinates.longitude', title: 'Longitude' }, + { key: 'heading', title: 'Heading' }, + { key: 'speed', title: 'Speed (kn)' }, + { key: 'positionAt', title: 'Position At' }, +]; + const commandColumns: Record = { 'shipments.list': [ { key: 'id', title: 'ID' }, @@ -62,7 +73,6 @@ const commandColumns: Record = { { key: ['dataSource', 'attributes.data_source'], title: 'Source' }, { key: ['value', 'attributes.value'], title: 'Value' }, ], - 'containers.route': ROUTE_PORT_COLUMNS, 'containers.demurrage': [ { key: 'container_id', title: 'Container ID' }, { key: 'pickup_lfd', title: 'Pickup LFD' }, @@ -574,31 +584,32 @@ function enrichSearchRow( return enriched; } -function rowsForCommand( - command: string, - data: unknown, -): Record[] { - const record = - data && typeof data === 'object' && !Array.isArray(data) - ? (data as Record) - : undefined; - - if (Array.isArray(record?.mapped)) { - return record.mapped as Record[]; - } +function asRecord(value: unknown): Record | undefined { + return value && typeof value === 'object' && !Array.isArray(value) + ? (value as Record) + : undefined; +} - if (command === 'containers.route') { - const mapped = record?.mapped; - const route = - mapped && typeof mapped === 'object' && !Array.isArray(mapped) - ? (mapped as Record) - : record; - if (Array.isArray(route?.ports)) { - return route.ports as Record[]; - } - } +function tableRows(data: unknown): Record[] { + const mapped = asRecord(data)?.mapped; + return Array.isArray(mapped) + ? (mapped as Record[]) + : normalizeRows(data); +} - return normalizeRows(data); +/** Ports table plus a current-vessel table, from a `{ ports }` route or a `{ raw, mapped }` pair; undefined for raw GeoJSON. */ +function renderRoute(data: unknown): string | undefined { + const record = asRecord(data); + const route = asRecord(record?.mapped) ?? record; + if (!Array.isArray(route?.ports)) return undefined; + + const ports = renderRows( + route.ports as Record[], + ROUTE_PORT_COLUMNS, + ); + const vessel = asRecord(route.currentVessel); + if (!vessel) return ports; + return `${ports}Current vessel\n${renderRows([vessel], ROUTE_VESSEL_COLUMNS)}`; } function isSearchCommand(command: string): boolean { @@ -682,23 +693,36 @@ export function renderTable(command: string, data: unknown): string { if (detail) return detail; } - const rows = rowsForCommand(command, data); - const baseCols = commandColumns[command]; - const commandIsSearch = isSearchCommand(command); + if (command === 'containers.route') { + const route = renderRoute(data); + if (route) return route; + } + + const rows = tableRows(data); + const renderedRows = isSearchCommand(command) + ? rows.map(enrichSearchRow) + : rows; + return renderRows( + renderedRows, + commandColumns[command] ?? inferUnknownColumns(renderedRows), + ); +} + +function renderRows( + rows: Record[], + cols: ColumnDef[], +): string { if (rows.length === 0) { return 'No rows.\n'; } - const renderedRows = commandIsSearch ? rows.map(enrichSearchRow) : rows; - const cols = baseCols ?? inferUnknownColumns(renderedRows); - const table = new Table({ head: cols.map((c) => c.title), style: { head: [], border: [] }, wordWrap: true, }); - renderedRows.forEach((row) => { + rows.forEach((row) => { table.push(cols.map((column) => formatCell(valueForColumn(row, column)))); }); diff --git a/sdks/typescript-sdk-cli/test/regression.test.ts b/sdks/typescript-sdk-cli/test/regression.test.ts index 895462c1..33a440fa 100644 --- a/sdks/typescript-sdk-cli/test/regression.test.ts +++ b/sdks/typescript-sdk-cli/test/regression.test.ts @@ -248,16 +248,31 @@ describe('CLI regressions', () => { ]); }); - it('containers route and its map alias both read map_geojson', async () => { + it('containers route prints mapped ports and map prints the unmapped GeoJSON', async () => { + const collection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [121.5, 31.2] }, + properties: { + feature_type: 'port', + location_id: 'loc-1', + name: 'Shanghai', + ports_sequence: 1, + }, + }, + ], + }; const paths: string[] = []; vi.stubGlobal('fetch', async (input: Request | URL | string) => { paths.push( new URL(input instanceof Request ? input.url : String(input)).pathname, ); - return new Response( - JSON.stringify({ type: 'FeatureCollection', features: [] }), - { status: 200, headers: { 'Content-Type': 'application/json' } }, - ); + return new Response(JSON.stringify(collection), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); }); process.env.T49_API_TOKEN = 'token-123'; process.env.T49_API_BASE_URL = 'https://api.test/v2'; @@ -265,11 +280,55 @@ describe('CLI regressions', () => { const route = await runProgram(['--json', 'containers', 'route', 'c-1']); const map = await runProgram(['--json', 'containers', 'map', 'c-1']); + const mapBoth = await runProgram([ + '--json', + '--format', + 'both', + 'containers', + 'map', + 'c-1', + ]); + const mapTable = await runProgram(['--table', 'containers', 'map', 'c-1']); - expect([route.status, map.status]).toEqual([0, 0]); + expect([route.status, map.status, mapBoth.status, mapTable.status]).toEqual( + [0, 0, 0, 0], + ); + expect(JSON.parse(mapBoth.stdout).data).toEqual({ + raw: collection, + mapped: collection, + }); + expect(mapTable.stdout).toBe( + [ + '┌───────────────────┐', + '│ Type │', + '├───────────────────┤', + '│ FeatureCollection │', + '└───────────────────┘', + '', + ].join('\n'), + ); + expect(JSON.parse(route.stdout).data).toEqual({ + ports: [ + { + locationId: 'loc-1', + name: 'Shanghai', + countryCode: null, + label: null, + sequence: 1, + coordinates: { latitude: 31.2, longitude: 121.5 }, + inbound: { eta: null, ata: null }, + outbound: { etd: null, atd: null }, + }, + ], + currentVessel: null, + totalPorts: 1, + }); + expect(JSON.parse(map.stdout).data).toEqual(collection); expect(paths).toEqual([ '/v2/containers/c-1/map_geojson', '/v2/containers/c-1/map_geojson', + '/v2/containers/c-1/map_geojson', + '/v2/containers/c-1/map_geojson', ]); }); }); diff --git a/sdks/typescript-sdk-cli/test/table.test.ts b/sdks/typescript-sdk-cli/test/table.test.ts index b9729a7c..1c64290a 100644 --- a/sdks/typescript-sdk-cli/test/table.test.ts +++ b/sdks/typescript-sdk-cli/test/table.test.ts @@ -115,53 +115,103 @@ describe('renderTable', () => { expect(output).toContain('unknown'); }); - it('renders route ports in order for containers route and map', () => { - const route = { - ports: [ - { - sequence: 1, - label: 'POL', - name: 'Laem Chabang', - countryCode: 'TH', - inbound: { eta: null, ata: null }, - outbound: { etd: null, atd: '2025-11-08T00:44:52Z' }, - }, - { - sequence: 3, - label: 'POD', - name: 'Savannah', - countryCode: 'US', - inbound: { eta: '2025-12-31T05:00:00Z', ata: null }, - outbound: { etd: null, atd: null }, - }, - ], - currentVessel: null, - totalPorts: 2, - }; - - const lines = renderTable('containers.route', route).split('\n'); - const header = lines.find((line) => line.includes('Seq')); - expect(header).toMatch( - /Seq.*Label.*Port.*Country.*Inbound ETA.*Inbound ATA.*Outbound ETD.*Outbound ATD/, + const route = { + ports: [ + { + sequence: 1, + label: 'POL', + name: 'Laem Chabang', + countryCode: 'TH', + inbound: { eta: null, ata: null }, + outbound: { etd: null, atd: '2025-11-08T00:44:52Z' }, + }, + { + sequence: 2, + label: 'TS1', + name: 'Xiamen', + countryCode: 'CN', + inbound: { eta: '2025-11-20T00:00:00Z', ata: '2025-11-21T00:00:00Z' }, + outbound: { etd: '2025-11-22T00:00:00Z', atd: '2025-11-23T00:00:00Z' }, + }, + { + sequence: 3, + label: 'POD', + name: 'Savannah', + countryCode: 'US', + inbound: { eta: '2025-12-31T05:00:00Z', ata: null }, + outbound: { etd: null, atd: null }, + }, + ], + currentVessel: null, + totalPorts: 3, + }; + + const geojson = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [100.88, 13.08] }, + properties: { feature_type: 'port', name: 'Laem Chabang' }, + }, + ], + }; + + it.each([ + ['mapped', route], + ['both', { raw: geojson, mapped: route }], + ])('renders containers route ports from %s output', (_format, data) => { + expect(renderTable('containers.route', data)).toBe( + [ + '┌─────┬───────┬──────────────┬─────────┬──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────┐', + '│ Seq │ Label │ Port │ Country │ Inbound ETA │ Inbound ATA │ Outbound ETD │ Outbound ATD │', + '├─────┼───────┼──────────────┼─────────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┤', + '│ 1 │ POL │ Laem Chabang │ TH │ │ │ │ 2025-11-08T00:44:52Z │', + '├─────┼───────┼──────────────┼─────────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┤', + '│ 2 │ TS1 │ Xiamen │ CN │ 2025-11-20T00:00:00Z │ 2025-11-21T00:00:00Z │ 2025-11-22T00:00:00Z │ 2025-11-23T00:00:00Z │', + '├─────┼───────┼──────────────┼─────────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┤', + '│ 3 │ POD │ Savannah │ US │ 2025-12-31T05:00:00Z │ │ │ │', + '└─────┴───────┴──────────────┴─────────┴──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────┘', + '', + ].join('\n'), + ); + }); + + it('renders the current vessel under the route ports', () => { + const table = renderTable('containers.route', { + ...route, + currentVessel: { + name: 'ZIM BANGKOK', + imo: '9936525', + voyage: '13E', + coordinates: { longitude: -131.128473333, latitude: 31.023033333 }, + heading: 108, + speed: 21, + positionAt: '2025-12-11T11:46:03Z', + departurePort: { locationId: null, name: null, label: null }, + arrivalPort: { locationId: null, name: null, label: null }, + }, + }); + const lines = table.split('\n'); + const title = lines.indexOf('Current vessel'); + expect(title).toBeGreaterThan( + lines.findIndex((line) => line.includes('Savannah')), + ); + expect(lines[title + 2]).toMatch( + /Vessel.*IMO.*Voyage.*Latitude.*Longitude.*Heading.*Speed \(kn\).*Position At/, ); - const pol = lines.findIndex((line) => line.includes('Laem Chabang')); - const pod = lines.findIndex((line) => line.includes('Savannah')); - expect(lines[pol]).toMatch(/1.*POL.*Laem Chabang.*TH.*2025-11-08/); - expect(lines[pod]).toMatch(/3.*POD.*Savannah.*US.*2025-12-31/); - expect(pol).toBeLessThan(pod); + expect(lines[title + 4]).toMatch( + /ZIM BANGKOK.*9936525.*13E.*31\.023033333.*-131\.128473333.*108.*21.*2025-12-11T11:46:03Z/, + ); + }); + + it('renders raw containers route GeoJSON like containers map', () => { + const table = renderTable('containers.route', geojson); + expect(table).toBe(renderTable('containers.map', geojson)); + expect(table).toMatch(/│ FeatureCollection │/); }); it('does not render containers map GeoJSON as route ports', () => { - const geojson = { - type: 'FeatureCollection', - features: [ - { - type: 'Feature', - geometry: { type: 'Point', coordinates: [100.88, 13.08] }, - properties: { feature_type: 'port', name: 'Laem Chabang' }, - }, - ], - }; const table = renderTable('containers.map', geojson); expect(table).toMatch(/│ FeatureCollection │/); expect(table).not.toMatch(/Seq.*Label/); diff --git a/sdks/typescript-sdk/README.md b/sdks/typescript-sdk/README.md index e4f8e17f..3e3f5c69 100644 --- a/sdks/typescript-sdk/README.md +++ b/sdks/typescript-sdk/README.md @@ -34,7 +34,7 @@ see the SDK quickstart in the docs site: `docs/api-docs/getting-started/sdk-quic ### Methods - `search(query)` - `getContainer(id, include?)` -- `trackContainer({ containerNumber?, bookingNumber?, scac?, refNumbers? })` +- `trackContainer({ containerNumber?, bookingNumber?, billOfLading?, scac?, refNumbers? })`: sends `request_type` `container`, `booking_number`, or `bill_of_lading` to match the number you pass - `createTrackingRequest({ requestType, requestNumber, scac?, refNumbers?, shipmentTags? })` - `inferTrackingNumber(number)` - `createTrackingRequestFromInfer(number, { scac?, numberType?, refNumbers?, shipmentTags? })` @@ -43,14 +43,25 @@ see the SDK quickstart in the docs site: `docs/api-docs/getting-started/sdk-quic - `listContainers(filters?, options?)` - `listTrackingRequests(filters?, options?)` / `listTrackRequests(filters?, options?)` - `getContainerTransportEvents(id)` -- `getContainerRoute(id)`: ports in route order and the current vessel, from `GET /containers/{id}/map_geojson` (Routing Data feature) +- `getContainerRoute(id, options?)`: the route from `GET /containers/{id}/map_geojson` (Routing Data feature). By default (`format: 'raw'`) it returns the GeoJSON FeatureCollection. With `{ format: 'mapped' }` it returns `{ ports, currentVessel, totalPorts }`, with ports in route order. - `getVesselFuturePositions(id, { portId, previousPortId })` - `getVesselFuturePositionsWithCoords(id, { portId, previousPortId, latitude, longitude })` - `listShippingLines(search?)` +- `listWebhooks(options?)`, `getWebhook(id)`, `createWebhook(payload)`, `updateWebhook(id, payload)`, `deleteWebhook(id)`, `getWebhookIps()` +- `listWebhookEvents()`: the event names a webhook can subscribe to +- `triggerWebhook({ url, event, secret?, documentType? })`: sends a test delivery with an example payload +- `listWebhookNotifications(options?)`, `getWebhookNotification(id, options?)`, `getWebhookNotificationExamples(event?)` +- `getVessel(id)`, `getVesselByImo(imo)`, `getPort(id)`, `getTerminal(id)`, `getMetroArea(id)` +- `listParties(options?)`, `getParty(id)`, `createParty(attributes)`, `updateParty(id, attributes)` +- `listCustomFieldDefinitions(options?)`, `getCustomFieldDefinition(id)`, `createCustomFieldDefinition(payload)`, `updateCustomFieldDefinition(id, payload)`, `deleteCustomFieldDefinition(id)` +- `listCustomFieldOptions(definitionId, options?)`, `getCustomFieldOption(definitionId, optionId)`, `createCustomFieldOption(definitionId, payload)`, `updateCustomFieldOption(definitionId, optionId, payload)`, `deleteCustomFieldOption(definitionId, optionId)` +- `listCustomFields(options?)`, `getCustomField(id)`, `createCustomField(payload)`, `updateCustomField(id, payload)`, `deleteCustomField(id)` - `getDemurrage(containerId)` (helper) - `getRailMilestones(containerId)` (helper) - `deserialize(document)` → JSONA-based plain objects +Some methods exist only on a resource namespace, for example `containers.update(id, attrs)`, `shippingLines.get(id)`, the per-entity custom field methods (`containers`, `shipments`, `trackingRequests`), the party role methods (`containers`, `shipments`), and the `documents`, `emailSubmissions`, and `documentSchemas` methods. See `docs/sdk/methods.mdx` for the full list. + ### Examples After building, run: diff --git a/sdks/typescript-sdk/src/client.custom-fields.test.ts b/sdks/typescript-sdk/src/client.custom-fields.test.ts index 7dd5095b..126cee97 100644 --- a/sdks/typescript-sdk/src/client.custom-fields.test.ts +++ b/sdks/typescript-sdk/src/client.custom-fields.test.ts @@ -111,4 +111,38 @@ describe('custom fields', () => { expect(calls[0].url.pathname).toBe('/v2/shipments/ship%201/custom_fields'); expect(result[0].name).toBe('Project Manager'); }); + + it('maps tracking request custom fields from the tracking request sub-resource', async () => { + const { client, calls } = buildClient( + '/tracking_requests/tr-1/custom_fields?include=definition', + ); + + const result = await client.trackingRequests.customFields('tr-1', { + format: 'mapped', + }); + + expect(calls[0].url.pathname).toBe( + '/v2/tracking_requests/tr-1/custom_fields', + ); + expect(result).toEqual([ + { + id: 'cf-1', + slug: 'project_manager', + name: 'Project Manager', + value: 'Roberto', + displayValue: 'Roberto', + dataType: 'short_text', + updatedAt: '2026-09-29T08:00:00Z', + }, + { + id: 'cf-2', + slug: 'is_priority', + name: undefined, + value: true, + displayValue: 'Yes', + dataType: undefined, + updatedAt: null, + }, + ]); + }); }); diff --git a/sdks/typescript-sdk/src/client.mapping.test.ts b/sdks/typescript-sdk/src/client.mapping.test.ts index 37efc8aa..c673a444 100644 --- a/sdks/typescript-sdk/src/client.mapping.test.ts +++ b/sdks/typescript-sdk/src/client.mapping.test.ts @@ -565,8 +565,17 @@ describe('Terminal49Client mapping helpers', () => { coordinates: { longitude: -131.128473333, latitude: 31.023033333 }, heading: 108, speed: 21, - departurePortId: 'ed64d446-9098-420c-ab08-c127e62509fe', - arrivalPortId: '6129528d-846e-4571-ae16-b5328a4285ab', + positionAt: '2025-12-11T11:46:03Z', + departurePort: { + locationId: 'ed64d446-9098-420c-ab08-c127e62509fe', + name: 'Xiamen', + label: 'TS1', + }, + arrivalPort: { + locationId: '6129528d-846e-4571-ae16-b5328a4285ab', + name: 'Savannah', + label: 'POD', + }, }, totalPorts: 3, }); @@ -585,12 +594,17 @@ describe('Terminal49Client mapping helpers', () => { const both = await client.containers.route('cont-1', { format: 'both' }); const viaMap = await client.containers.map('cont-1', { format: 'mapped' }); + const viaMapBoth = await client.containers.map('cont-1', { + format: 'both', + }); expect(both.raw).toEqual(fixture); expect(viaMap).toEqual(fixture); + expect(viaMapBoth).toEqual({ raw: fixture, mapped: fixture }); expect(calls.map((c) => c.url.pathname)).toEqual([ '/v2/containers/cont-1/map_geojson', '/v2/containers/cont-1/map_geojson', + '/v2/containers/cont-1/map_geojson', ]); }); @@ -646,8 +660,9 @@ describe('Terminal49Client mapping helpers', () => { coordinates: { longitude: 10, latitude: 20 }, heading: null, speed: null, - departurePortId: null, - arrivalPortId: null, + positionAt: null, + departurePort: { locationId: null, name: null, label: null }, + arrivalPort: { locationId: null, name: null, label: null }, }); expect(result.totalPorts).toBe(3); }); diff --git a/sdks/typescript-sdk/src/client.test.ts b/sdks/typescript-sdk/src/client.test.ts index 47d159e0..9164e196 100644 --- a/sdks/typescript-sdk/src/client.test.ts +++ b/sdks/typescript-sdk/src/client.test.ts @@ -215,6 +215,45 @@ describe('Terminal49Client', () => { }); }); + it.each([ + [{ bookingNumber: 'BK123' }, 'booking_number', 'BK123'], + [{ billOfLading: 'MAEU123456789' }, 'bill_of_lading', 'MAEU123456789'], + [ + { + containerNumber: 'MSCU1234567', + bookingNumber: 'BK123', + billOfLading: 'B1', + }, + 'container', + 'MSCU1234567', + ], + [{ bookingNumber: 'BK123', billOfLading: 'B1' }, 'booking_number', 'BK123'], + ])( + 'sends the matching request_type for %o', + async (number, requestType, requestNumber) => { + let capturedBody: any = null; + const { fetchImpl } = createMockFetch({ + '/tracking_requests': (init) => { + capturedBody = JSON.parse(String(init?.body)); + return jsonResponse({ data: { id: 'tr-1', attributes: {} } }, 201); + }, + }); + const client = new Terminal49Client({ + apiToken: 'token-123', + apiBaseUrl: baseUrl, + fetchImpl, + }); + + await client.trackContainer({ ...number, scac: 'MAEU' }); + + expect(capturedBody.data.attributes).toEqual({ + request_type: requestType, + request_number: requestNumber, + scac: 'MAEU', + }); + }, + ); + it('uses deserialize helper to flatten JSON:API with included', async () => { const doc = { data: { diff --git a/sdks/typescript-sdk/src/client.ts b/sdks/typescript-sdk/src/client.ts index 781fedd8..18ca3eee 100644 --- a/sdks/typescript-sdk/src/client.ts +++ b/sdks/typescript-sdk/src/client.ts @@ -29,10 +29,10 @@ import type { TrackingRequestListFilters, TrackingRequestType, } from './client/managers/tracking-requests.js'; -import { applyTypedPagination } from './client/query.js'; +import { applyTypedPagination, normalizeInclude } from './client/query.js'; import { callerPayload, type JsonBody } from './client/spec.js'; import { Transport } from './client/transport.js'; -import type { paths } from './generated/terminal49.js'; +import type { components, paths } from './generated/terminal49.js'; import type { CallOptions, ContainerInclude, @@ -41,6 +41,7 @@ import type { ResponseFormat, ShipmentInclude, TrackingRequestInclude, + WebhookNotificationInclude, } from './types/options.js'; /** @@ -68,15 +69,19 @@ type WebhookEvent = NonNullable< type CustomFieldDefinitionListQuery = NonNullable< paths['/custom_field_definitions']['get']['parameters']['query'] >; +type WebhookNotificationListQuery = NonNullable< + paths['/webhook_notifications']['get']['parameters']['query'] +>; type CustomFieldListQuery = NonNullable< paths['/custom_fields']['get']['parameters']['query'] >; type TriggerWebhookBody = JsonBody; -type CreatePartyBody = JsonBody; -type UpdatePartyBody = JsonBody; -type CustomFieldDefinitionAttributes = NonNullable< - JsonBody['data'] +type PartyAttributes = NonNullable< + JsonBody['data'] >['attributes']; +type CustomFieldDefinitionAttributes = NonNullable< + components['schemas']['custom_field_definition']['attributes'] +>; type FuturePositionsQuery = paths['/vessels/{id}/future_positions']['get']['parameters']['query']; @@ -99,6 +104,12 @@ export interface VesselFuturePositionsWithCoordsParams extends VesselFuturePosit longitude: FuturePositionsWithCoordsQuery['longitude']; } +const TRACK_CONTAINER_NUMBER_TYPES = [ + ['containerNumber', 'container'], + ['bookingNumber', 'booking_number'], + ['billOfLading', 'bill_of_lading'], +] as const satisfies readonly (readonly [string, TrackingRequestType])[]; + /** Parameters for {@link Terminal49Client.triggerWebhook}. */ export interface TriggerWebhookParams { /** HTTPS destination URL for the test delivery. */ @@ -125,6 +136,18 @@ export interface CustomFieldDefinitionListFilters { displayName?: string; } +/** Options for {@link Terminal49Client.getWebhookNotification}. */ +export interface WebhookNotificationGetOptions extends CallOptions { + /** Related resources to sideload. */ + include?: IncludeParam; +} + +/** Options for {@link Terminal49Client.listWebhookNotifications}. */ +export interface WebhookNotificationListOptions extends ListOptions { + /** Related resources to sideload. */ + include?: IncludeParam; +} + /** Configuration for {@link Terminal49Client}. */ export interface Terminal49ClientConfig { /** Terminal49 API token. Pass either the raw token or a value prefixed with `Token ` or `Bearer `. */ @@ -201,8 +224,9 @@ export class Terminal49Client { }; public webhookNotifications = { - list: (options?: ListOptions) => this.listWebhookNotifications(options), - get: (id: string, options?: CallOptions) => + list: (options?: WebhookNotificationListOptions) => + this.listWebhookNotifications(options), + get: (id: string, options?: WebhookNotificationGetOptions) => this.getWebhookNotification(id, options), examples: (event?: string, options?: CallOptions) => this.getWebhookNotificationExamples(event, options), @@ -235,10 +259,10 @@ export class Terminal49Client { public parties = { list: (options?: ListOptions) => this.listParties(options), get: (id: string, options?: CallOptions) => this.getParty(id, options), - create: (payload: CreatePartyBody, options?: CallOptions) => - this.createParty(payload, options), - update: (id: string, payload: UpdatePartyBody, options?: CallOptions) => - this.updateParty(id, payload, options), + create: (attributes: PartyAttributes, options?: CallOptions) => + this.createParty(attributes, options), + update: (id: string, attributes: PartyAttributes, options?: CallOptions) => + this.updateParty(id, attributes, options), }; public metroAreas = { @@ -373,28 +397,30 @@ export class Terminal49Client { return this.containers.get(id, include, options); } - /** Convenience helper for creating a tracking request from a container or booking number. */ + /** Convenience helper for creating a tracking request from a container, booking, or bill of lading number. */ async trackContainer(params: { containerNumber?: string; bookingNumber?: string; + billOfLading?: string; scac?: string; autoDetectVoccScac?: boolean; refNumbers?: string[]; }): Promise { - const requestType: TrackingRequestType = params.containerNumber - ? 'container' - : 'bill_of_lading'; - const requestNumber = params.containerNumber || params.bookingNumber; + const [request] = TRACK_CONTAINER_NUMBER_TYPES.flatMap( + ([key, requestType]) => { + const requestNumber = params[key]; + return requestNumber ? [{ requestType, requestNumber }] : []; + }, + ); - if (!requestNumber) { + if (!request) { throw new ValidationError( 'request_number is required (/data/attributes/request_number)', ); } return this.trackingRequests.create({ - requestType, - requestNumber, + ...request, scac: params.scac, autoDetectVoccScac: params.autoDetectVoccScac, refNumbers: params.refNumbers, @@ -642,10 +668,17 @@ export class Terminal49Client { } /** List webhook notifications. */ - async listWebhookNotifications(options?: ListOptions): Promise { + async listWebhookNotifications( + options?: WebhookNotificationListOptions, + ): Promise { const raw = await this.transport.execute(() => this.transport.client.GET('/webhook_notifications', { - params: { query: applyTypedPagination({}, options) }, + params: { + query: applyTypedPagination( + { include: normalizeInclude(options?.include) }, + options, + ), + }, }), ); return this.formatResult(raw, options?.format); @@ -654,11 +687,14 @@ export class Terminal49Client { /** Fetch a webhook notification by ID. */ async getWebhookNotification( id: string, - options?: CallOptions, + options?: WebhookNotificationGetOptions, ): Promise { const raw = await this.transport.execute(() => this.transport.client.GET('/webhook_notifications/{id}', { - params: { path: { id } }, + params: { + path: { id }, + query: { include: normalizeInclude(options?.include) }, + }, }), ); return this.formatResult(raw, options?.format); @@ -780,11 +816,13 @@ export class Terminal49Client { /** Create a party. */ async createParty( - payload: CreatePartyBody, + attributes: PartyAttributes, options?: CallOptions, ): Promise { const raw = await this.transport.execute(() => - this.transport.client.POST('/parties', { body: payload }), + this.transport.client.POST('/parties', { + body: { data: { type: 'party', attributes } }, + }), ); return this.formatResult(raw, options?.format); } @@ -792,13 +830,13 @@ export class Terminal49Client { /** Update a party. */ async updateParty( id: string, - payload: UpdatePartyBody, + attributes: PartyAttributes, options?: CallOptions, ): Promise { const raw = await this.transport.execute(() => this.transport.client.PATCH('/parties/{id}', { params: { path: { id } }, - body: payload, + body: { data: { type: 'party', attributes } }, }), ); return this.formatResult(raw, options?.format); diff --git a/sdks/typescript-sdk/src/client.write-endpoints.test.ts b/sdks/typescript-sdk/src/client.write-endpoints.test.ts index 42091d45..fa259a07 100644 --- a/sdks/typescript-sdk/src/client.write-endpoints.test.ts +++ b/sdks/typescript-sdk/src/client.write-endpoints.test.ts @@ -9,6 +9,12 @@ interface RecordedCall { body: any; } +function servedBody(method: string, pathname: string) { + return { + data: { id: `${method} ${pathname.replace('/v2', '')}`, type: 'stub' }, + }; +} + function buildClient() { const calls: RecordedCall[] = []; const fetchImpl: typeof fetch = async (input, init) => { @@ -22,7 +28,7 @@ function buildClient() { body: text ? JSON.parse(text) : undefined, }); if (request.method === 'DELETE') return new Response(null, { status: 204 }); - return jsonResponse({ data: { id: 'x', type: 'stub' } }); + return jsonResponse(servedBody(request.method, url.pathname)); }; const client = new Terminal49Client({ apiToken: 'token-123', @@ -275,15 +281,22 @@ describe('webhooks', () => { }); describe('parties', () => { - it('creates and updates parties', async () => { + it('creates and updates parties with the documented JSON:API body', async () => { const { client, calls } = buildClient(); - const payload = { data: { attributes: { company_name: 'ACME' } } }; - await client.parties.create(payload); - await client.parties.update('p-1', payload); + await client.parties.create({ company_name: 'ACME' }); + await client.parties.update('p-1', { company_name: 'ACME 2' }); expect(calls.map((c) => [c.method, c.path, c.body])).toEqual([ - ['POST', '/parties', payload], - ['PATCH', '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/parties/p-1', payload], + [ + 'POST', + '/parties', + { data: { type: 'party', attributes: { company_name: 'ACME' } } }, + ], + [ + 'PATCH', + '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/parties/p-1', + { data: { type: 'party', attributes: { company_name: 'ACME 2' } } }, + ], ]); }); }); @@ -315,6 +328,21 @@ describe('custom field list filters', () => { 'filter[display_name]': 'PO', }); }); + + it('filters by the TrackingRequest entity type', async () => { + const { client, calls } = buildClient(); + await client.customFields.list({ + filters: { entityType: 'TrackingRequest' }, + }); + await client.customFieldDefinitions.list({ + filters: { entityType: 'TrackingRequest' }, + }); + + expect(calls.map((c) => c.query)).toEqual([ + { 'filter[entity_type]': 'TrackingRequest' }, + { 'filter[entity_type]': 'TrackingRequest' }, + ]); + }); }); describe('search', () => { @@ -441,16 +469,307 @@ describe('resource methods on the client', () => { ]); }); + it('sends include on webhook notification list and get', async () => { + const { client, calls } = buildClient(); + await client.webhookNotifications.list({ + page: 2, + include: ['webhook', 'reference_object'], + }); + await client.webhookNotifications.get('n-1', { include: 'webhook' }); + + expect(calls.map((c) => [c.path, c.query])).toEqual([ + [ + '/webhook_notifications', + { include: 'webhook,reference_object', 'page[number]': '2' }, + ], + ['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/webhook_notifications/n-1', { include: 'webhook' }], + ]); + }); + it('clamps page[size] to the API maximum', async () => { const { client, calls } = buildClient(); await client.parties.list({ pageSize: 500 }); expect(calls[0].query).toEqual({ 'page[size]': '100' }); }); +}); - it('returns the response body the API served', async () => { +describe('return values', () => { + it.each([ + ['GET', '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/webhooks/w-1', (c: Terminal49Client) => c.webhooks.get('w-1')], + ['GET', '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/webhooks/events', (c: Terminal49Client) => c.webhooks.events()], + [ + 'POST', + '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/webhooks/trigger', + (c: Terminal49Client) => + c.webhooks.trigger({ + url: 'https://example.com/hook', + event: 'container.updated', + }), + ], + [ + 'GET', + '/webhook_notifications', + (c: Terminal49Client) => c.webhookNotifications.list(), + ], + [ + 'GET', + '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/webhook_notifications/n-1', + (c: Terminal49Client) => c.webhookNotifications.get('n-1'), + ], + [ + 'POST', + '/parties', + (c: Terminal49Client) => c.parties.create({ company_name: 'ACME' }), + ], + [ + 'PATCH', + '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/parties/p-1', + (c: Terminal49Client) => + c.parties.update('p-1', { company_name: 'ACME' }), + ], + [ + 'GET', + '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/shipping_lines/sl-1', + (c: Terminal49Client) => c.shippingLines.get('sl-1'), + ], + [ + 'PATCH', + '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/containers/c-1', + (c: Terminal49Client) => c.containers.update('c-1', { ref_numbers: [] }), + ], + [ + 'GET', + '/containers/c-1/custom_fields', + (c: Terminal49Client) => c.containers.customFields('c-1'), + ], + [ + 'POST', + '/shipments/s-1/custom_fields', + (c: Terminal49Client) => c.shipments.setCustomField('s-1', 'po', 'PO-1'), + ], + [ + 'PATCH', + '/tracking_requests/t-1/custom_fields/po', + (c: Terminal49Client) => + c.trackingRequests.updateCustomField('t-1', 'po', 'PO-2'), + ], + [ + 'GET', + '/tracking_requests/t-1/custom_fields', + (c: Terminal49Client) => c.trackingRequests.customFields('t-1'), + ], + [ + 'POST', + '/tracking_requests/t-1/custom_fields', + (c: Terminal49Client) => + c.trackingRequests.setCustomField('t-1', 'po', 'PO-1'), + ], + [ + 'PATCH', + '/containers/c-1/custom_fields/po', + (c: Terminal49Client) => + c.containers.updateCustomField('c-1', 'po', 'PO-2'), + ], + [ + 'PATCH', + '/shipments/s-1/custom_fields/po', + (c: Terminal49Client) => + c.shipments.updateCustomField('s-1', 'po', 'PO-2'), + ], + [ + 'GET', + '/containers/c-1/party_roles', + (c: Terminal49Client) => c.containers.partyRoles('c-1'), + ], + [ + 'POST', + '/containers/c-1/party_roles', + (c: Terminal49Client) => + c.containers.addPartyRole('c-1', { + role: 'pickup_dray_carrier', + partyId: 'pa-1', + }), + ], + [ + 'GET', + '/shipments/s-1/party_roles', + (c: Terminal49Client) => c.shipments.partyRoles('s-1'), + ], + [ + 'POST', + '/shipments/s-1/party_roles', + (c: Terminal49Client) => + c.shipments.addPartyRole('s-1', { role: 'consignee', partyId: 'pa-1' }), + ], + ['GET', '/documents', (c: Terminal49Client) => c.documents.list()], + [ + 'POST', + '/documents', + (c: Terminal49Client) => + c.documents.create({ name: 'BOL.pdf', attachedDocument: 'blob-1' }), + ], + ['GET', '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/documents/d-1', (c: Terminal49Client) => c.documents.get('d-1')], + [ + 'PATCH', + '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/documents/d-1', + (c: Terminal49Client) => + c.documents.update('d-1', { documentTypeManual: 'bill_of_lading' }), + ], + ['GET', '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/documents/types', (c: Terminal49Client) => c.documents.types()], + [ + 'GET', + '/documents/d-1/download_url', + (c: Terminal49Client) => c.documents.downloadUrl('d-1'), + ], + [ + 'POST', + '/documents/d-1/reextract', + (c: Terminal49Client) => c.documents.reextract('d-1'), + ], + [ + 'POST', + '/documents/d-1/reclassify', + (c: Terminal49Client) => c.documents.reclassify('d-1'), + ], + [ + 'POST', + '/documents/d-1/relink', + (c: Terminal49Client) => c.documents.relink('d-1'), + ], + [ + 'POST', + '/documents/d-1/rotate', + (c: Terminal49Client) => c.documents.rotate('d-1', 90), + ], + [ + 'GET', + '/email_submissions', + (c: Terminal49Client) => c.emailSubmissions.list(), + ], + [ + 'GET', + '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/email_submissions/e-1', + (c: Terminal49Client) => c.emailSubmissions.get('e-1'), + ], + [ + 'GET', + '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/document_schemas/bill_of_lading', + (c: Terminal49Client) => c.documentSchemas.get('bill_of_lading'), + ], + ['GET', '/custom_fields', (c: Terminal49Client) => c.customFields.list()], + [ + 'GET', + '/custom_field_definitions', + (c: Terminal49Client) => c.customFieldDefinitions.list(), + ], + ['GET', '/webhooks', (c: Terminal49Client) => c.webhooks.list()], + [ + 'POST', + '/webhooks', + (c: Terminal49Client) => c.webhooks.create({ data: {} }), + ], + [ + 'PATCH', + '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/webhooks/w-1', + (c: Terminal49Client) => c.webhooks.update('w-1', { data: {} }), + ], + ['GET', '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/webhooks/ips', (c: Terminal49Client) => c.webhooks.ips()], + [ + 'GET', + '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/webhook_notifications/examples', + (c: Terminal49Client) => c.webhookNotifications.examples(), + ], + ['GET', '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/vessels/v-1', (c: Terminal49Client) => c.vessels.get('v-1')], + [ + 'GET', + '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/vessels/9876543', + (c: Terminal49Client) => c.vessels.getByImo('9876543'), + ], + [ + 'GET', + '/vessels/v-1/future_positions', + (c: Terminal49Client) => + c.vessels.futurePositions('v-1', { + portId: 'port-2', + previousPortId: 'port-1', + }), + ], + [ + 'GET', + '/vessels/v-1/future_positions_with_coordinates', + (c: Terminal49Client) => + c.vessels.futurePositionsWithCoords('v-1', { + portId: 'port-2', + previousPortId: 'port-1', + latitude: 13.07, + longitude: -100.84, + }), + ], + ['GET', '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/ports/p-1', (c: Terminal49Client) => c.ports.get('p-1')], + ['GET', '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/terminals/t-1', (c: Terminal49Client) => c.terminals.get('t-1')], + ['GET', '/parties', (c: Terminal49Client) => c.parties.list()], + ['GET', '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/parties/pa-1', (c: Terminal49Client) => c.parties.get('pa-1')], + [ + 'GET', + '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/metro_areas/m-1', + (c: Terminal49Client) => c.metroAreas.get('m-1'), + ], + [ + 'GET', + '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/custom_field_definitions/d-1', + (c: Terminal49Client) => c.customFieldDefinitions.get('d-1'), + ], + [ + 'POST', + '/custom_field_definitions', + (c: Terminal49Client) => c.customFieldDefinitions.create({ data: {} }), + ], + [ + 'PATCH', + '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/custom_field_definitions/d-1', + (c: Terminal49Client) => + c.customFieldDefinitions.update('d-1', { data: {} }), + ], + [ + 'GET', + '/custom_field_definitions/d-1/options', + (c: Terminal49Client) => c.customFieldOptions.list('d-1'), + ], + [ + 'GET', + '/custom_field_definitions/d-1/options/o-1', + (c: Terminal49Client) => c.customFieldOptions.get('d-1', 'o-1'), + ], + [ + 'POST', + '/custom_field_definitions/d-1/options', + (c: Terminal49Client) => c.customFieldOptions.create('d-1', { data: {} }), + ], + [ + 'PATCH', + '/custom_field_definitions/d-1/options/o-1', + (c: Terminal49Client) => + c.customFieldOptions.update('d-1', 'o-1', { data: {} }), + ], + [ + 'GET', + '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/custom_fields/cf-1', + (c: Terminal49Client) => c.customFields.get('cf-1'), + ], + [ + 'POST', + '/custom_fields', + (c: Terminal49Client) => c.customFields.create({ data: {} }), + ], + [ + 'PATCH', + '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/custom_fields/cf-1', + (c: Terminal49Client) => c.customFields.update('cf-1', { data: {} }), + ], + ] as const)('%s %s returns the served body', async (method, path, call) => { const { client } = buildClient(); - await expect(client.webhooks.get('w-1')).resolves.toEqual({ - data: { id: 'x', type: 'stub' }, - }); + await expect(call(client)).resolves.toEqual( + servedBody(method, `/v2${path}`), + ); }); }); diff --git a/sdks/typescript-sdk/src/client/managers/containers.ts b/sdks/typescript-sdk/src/client/managers/containers.ts index d9159ef3..c02aff33 100644 --- a/sdks/typescript-sdk/src/client/managers/containers.ts +++ b/sdks/typescript-sdk/src/client/managers/containers.ts @@ -71,13 +71,10 @@ export class ContainerManager extends BaseManager { attrs: ContainerUpdateAttributes, options?: CallOptions, ): Promise { - const payload = { - data: { type: 'container' as const, id, attributes: attrs }, - }; const raw = await this.transport.execute(() => this.transport.client.PATCH('/containers/{id}', { params: { path: { id } }, - body: payload, + body: { data: { type: 'container', id, attributes: attrs } }, }), ); return this.formatResult(raw, options?.format); @@ -153,7 +150,8 @@ export class ContainerManager extends BaseManager { /** * @deprecated Use {@link ContainerManager.route}. Returns the GeoJSON - * FeatureCollection in every format. + * FeatureCollection unmapped: `raw` and `mapped` return it as is, and + * `both` returns `{ raw, mapped }` with the FeatureCollection in each half. */ async map(id: string, options?: CallOptions): Promise { const raw = await this.route(id, { format: 'raw' }); diff --git a/sdks/typescript-sdk/src/client/managers/documents.ts b/sdks/typescript-sdk/src/client/managers/documents.ts index cd7dd59c..6bf114a4 100644 --- a/sdks/typescript-sdk/src/client/managers/documents.ts +++ b/sdks/typescript-sdk/src/client/managers/documents.ts @@ -240,7 +240,7 @@ export class EmailSubmissionManager extends BaseManager { } export class DocumentSchemaManager extends BaseManager { - /** Fetch the extraction schema for a document type. */ + /** Fetch an extraction schema by its versioned id, `@`, such as `commercial_invoice@2026-03-23`. */ async get(id: string, options?: CallOptions): Promise { const raw = await this.transport.execute(() => this.transport.client.GET('/document_schemas/{id}', { diff --git a/sdks/typescript-sdk/src/client/mappers.ts b/sdks/typescript-sdk/src/client/mappers.ts index f475aa5d..d7aecc44 100644 --- a/sdks/typescript-sdk/src/client/mappers.ts +++ b/sdks/typescript-sdk/src/client/mappers.ts @@ -128,8 +128,17 @@ function mapRouteVessel( coordinates: pointCoordinates(geometry), heading: props.vessel_location_heading ?? null, speed: props.vessel_location_speed ?? null, - departurePortId: props.departure_port_id ?? null, - arrivalPortId: props.arrival_port_id ?? null, + positionAt: props.vessel_location_timestamp ?? null, + departurePort: { + locationId: props.departure_port_id ?? null, + name: props.departure_port_name ?? null, + label: props.departure_port_label ?? null, + }, + arrivalPort: { + locationId: props.arrival_port_id ?? null, + name: props.arrival_port_name ?? null, + label: props.arrival_port_label ?? null, + }, }; } diff --git a/sdks/typescript-sdk/src/generated/terminal49.ts b/sdks/typescript-sdk/src/generated/terminal49.ts index ed25485a..79c79bf2 100644 --- a/sdks/typescript-sdk/src/generated/terminal49.ts +++ b/sdks/typescript-sdk/src/generated/terminal49.ts @@ -2616,7 +2616,9 @@ export interface components { coordinates: number[]; }; /** @description Raw custom field value (type depends on definition) */ - custom_field_value: (string | number | boolean | string[] | Record) | null; + custom_field_value: (string | number | boolean | string[] | { + [key: string]: unknown; + }) | null; /** Custom field */ custom_field: { /** Format: uuid */ @@ -5201,6 +5203,10 @@ export interface operations { content: { "application/json": { data?: { + /** Format: uuid */ + id?: string; + /** @enum {string} */ + type: "container"; attributes: { ref_numbers?: string[]; }; @@ -5773,6 +5779,8 @@ export interface operations { content: { "application/json": { data?: { + /** @enum {string} */ + type: "party"; attributes: { /** * @description The name of the company @@ -7021,6 +7029,8 @@ export interface operations { content: { "application/json": { data?: { + /** @enum {string} */ + type: "party"; attributes: { /** * @description The name of the company diff --git a/sdks/typescript-sdk/src/spec-types.test.ts b/sdks/typescript-sdk/src/spec-types.test.ts new file mode 100644 index 00000000..1a66db20 --- /dev/null +++ b/sdks/typescript-sdk/src/spec-types.test.ts @@ -0,0 +1,33 @@ +import { describe, expectTypeOf, it } from 'vite-plus/test'; +import type { ContainerManager } from './client/managers/containers.js'; +import type { ShipmentManager } from './client/managers/shipments.js'; +import type { TrackingRequestManager } from './client/managers/tracking-requests.js'; +import type { components } from './generated/terminal49.js'; + +describe('generated spec types', () => { + it('types a container resource as type "container"', () => { + expectTypeOf< + components['schemas']['container']['type'] + >().toEqualTypeOf<'container'>(); + }); + + it('accepts a non-empty object as a custom field value in every setter', () => { + type ObjectValue = { id: string; type: string }; + + expectTypeOf().toExtend< + components['schemas']['custom_field_value'] + >(); + expectTypeOf().toExtend< + Parameters[2] + >(); + expectTypeOf().toExtend< + Parameters[2] + >(); + expectTypeOf().toExtend< + Parameters[2] + >(); + expectTypeOf().toExtend< + Parameters[2] + >(); + }); +}); diff --git a/sdks/typescript-sdk/src/types/models.ts b/sdks/typescript-sdk/src/types/models.ts index a2b25c2f..feb6a356 100644 --- a/sdks/typescript-sdk/src/types/models.ts +++ b/sdks/typescript-sdk/src/types/models.ts @@ -156,6 +156,15 @@ export interface RoutePort { outbound: { etd: string | null; atd: string | null }; } +/** A port the current vessel left or is heading to, as the `current_vessel` feature names it. */ +export interface RouteVesselPort { + /** Matches {@link RoutePort.locationId} of the same port. */ + locationId: string | null; + name: string | null; + /** `POL`, `POD`, or `TS1`, `TS2`, and so on for transshipment ports. */ + label: string | null; +} + /** The vessel carrying the container right now. Present only while it is at sea. */ export interface RouteVessel { name: string | null; @@ -166,8 +175,10 @@ export interface RouteVessel { heading: number | null; /** Knots. */ speed: number | null; - departurePortId: string | null; - arrivalPortId: string | null; + /** When the vessel reported `coordinates`, `heading`, and `speed` (ISO 8601). */ + positionAt: string | null; + departurePort: RouteVesselPort; + arrivalPort: RouteVesselPort; } /** Mapped container route: ports in route order plus the current vessel. */ diff --git a/sdks/typescript-sdk/src/types/options.ts b/sdks/typescript-sdk/src/types/options.ts index 73d5b3a9..3dfe31b1 100644 --- a/sdks/typescript-sdk/src/types/options.ts +++ b/sdks/typescript-sdk/src/types/options.ts @@ -47,3 +47,5 @@ export type ContainerInclude = | 'transport_events'; export type TrackingRequestInclude = 'shipment' | 'container'; + +export type WebhookNotificationInclude = 'webhook' | 'reference_object'; From 677506085fe78ab94975ea476d0ecaae677e5568 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 14 Oct 2026 21:12:32 +0000 Subject: [PATCH 14/14] chore: Auto-generate Postman collection from openapi.json [skip ci] --- Terminal49-API.postman_collection.json | 904 +++++++++++++------------ 1 file changed, 464 insertions(+), 440 deletions(-) diff --git a/Terminal49-API.postman_collection.json b/Terminal49-API.postman_collection.json index bad93f51..f40fd75f 100644 --- a/Terminal49-API.postman_collection.json +++ b/Terminal49-API.postman_collection.json @@ -5,7 +5,7 @@ "description": "", "item": [ { - "id": "f9370939-97e8-41aa-88f6-61be872e33b1", + "id": "528f7965-6dc9-486e-9c83-dcb4e0c8ba13", "name": "List containers", "request": { "name": "List containers", @@ -289,7 +289,7 @@ "type": "text/plain" }, "key": "filter[current_status][]", - "value": "new" + "value": "awaiting_inland_transfer" }, { "disabled": true, @@ -1062,7 +1062,7 @@ }, "response": [ { - "id": "7b86191d-f9f7-431e-ba44-185bdb8c2086", + "id": "071bec8f-6fe5-4e2d-b8b4-c86688cd6cf0", "name": "OK", "originalRequest": { "url": { @@ -1341,7 +1341,7 @@ "type": "text/plain" }, "key": "filter[current_status][]", - "value": "new" + "value": "awaiting_inland_transfer" }, { "disabled": true, @@ -2109,12 +2109,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"tank\",\n \"equipment_length\": 20,\n \"equipment_height\": \"standard\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"dropped\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"bulk\",\n \"equipment_length\": 20,\n \"equipment_height\": null,\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"extended_dwell_time\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"on_rail\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"cancelled_by_user\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"cancelled_by_user\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"reefer\",\n \"equipment_length\": 20,\n \"equipment_height\": \"high_cube\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"total\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"grounded\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"reefer\",\n \"equipment_length\": 45,\n \"equipment_height\": null,\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"total\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"off_dock\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"booking_cancelled\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "4fe2d322-0aed-434e-b0ee-a9911b34e9ea", + "id": "544fdb18-3952-4790-b7b3-5983e79508d0", "name": "Malformed supported filter value, operator, range, or strict boolean. The error identifies the invalid parameter where available.", "originalRequest": { "url": { @@ -2393,7 +2393,7 @@ "type": "text/plain" }, "key": "filter[current_status][]", - "value": "new" + "value": "awaiting_inland_transfer" }, { "disabled": true, @@ -3161,7 +3161,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -3172,67 +3172,94 @@ } }, { - "id": "24f66ce3-83d6-48b1-8f52-74bd4404f03f", - "name": "Edit a container", + "id": "db36539c-f035-4d0c-9016-3abc7c9231e3", + "name": "Get a container", "request": { - "name": "Edit a container", + "name": "Get a container", "description": { - "content": "Update a container", + "content": "Retrieves the details of a container.", "type": "text/plain" }, "url": { "path": [ - "containers" + "containers", + ":id" ], "host": [ "{{baseUrl}}" ], - "query": [], - "variable": [] + "query": [ + { + "disabled": true, + "description": { + "content": "Comma delimited list of relations to include", + "type": "text/plain" + }, + "key": "include", + "value": "" + } + ], + "variable": [ + { + "type": "any", + "value": "", + "key": "id", + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + } + } + ] }, "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, { "key": "Accept", "value": "application/json" } ], - "method": "PATCH", - "body": { - "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_numbers\": [\n \"\",\n \"\"\n ]\n },\n \"type\": false\n }\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, + "method": "GET", + "body": {}, "auth": null }, "response": [ { - "id": "f4da5b14-1bad-493f-8192-b85b4ccc4c41", + "id": "e7305b45-6bd8-4311-afb6-a247b33ed9cb", "name": "OK", "originalRequest": { "url": { "path": [ - "containers" + "containers", + ":id" ], "host": [ "{{baseUrl}}" ], - "query": [], - "variable": [] + "query": [ + { + "disabled": true, + "description": { + "content": "Comma delimited list of relations to include", + "type": "text/plain" + }, + "key": "include", + "value": "" + } + ], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "", + "key": "id" + } + ] }, "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, { "key": "Accept", "value": "application/json" @@ -3246,17 +3273,8 @@ "value": "" } ], - "method": "PATCH", - "body": { - "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_numbers\": [\n \"\",\n \"\"\n ]\n },\n \"type\": false\n }\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - } + "method": "GET", + "body": {} }, "status": "OK", "code": 200, @@ -3266,7 +3284,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"reefer\",\n \"equipment_length\": 10,\n \"equipment_height\": \"standard\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"delivered\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"bulk\",\n \"equipment_length\": null,\n \"equipment_height\": null,\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"on_ship\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"booking_cancelled\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"no_updates_at_line\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -3277,12 +3295,12 @@ } }, { - "id": "f627a10f-1c5f-4522-badf-ea08ba305053", - "name": "Get a container", + "id": "ee23bcf1-b08c-4bd8-9eee-d352beaa4cb1", + "name": "Edit a container", "request": { - "name": "Get a container", + "name": "Edit a container", "description": { - "content": "Retrieves the details of a container.", + "content": "Update a container", "type": "text/plain" }, "url": { @@ -3293,17 +3311,7 @@ "host": [ "{{baseUrl}}" ], - "query": [ - { - "disabled": true, - "description": { - "content": "Comma delimited list of relations to include", - "type": "text/plain" - }, - "key": "include", - "value": "" - } - ], + "query": [], "variable": [ { "type": "any", @@ -3318,18 +3326,31 @@ ] }, "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, { "key": "Accept", "value": "application/json" } ], - "method": "GET", - "body": {}, + "method": "PATCH", + "body": { + "mode": "raw", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_numbers\": [\n \"\",\n \"\"\n ]\n },\n \"type\": \"container\",\n \"id\": \"\"\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, "auth": null }, "response": [ { - "id": "1eb35f83-8e88-410a-ad0b-c6ddeeeaf165", + "id": "3cf943c3-57c0-4d43-99bd-ad38332742c4", "name": "OK", "originalRequest": { "url": { @@ -3340,17 +3361,7 @@ "host": [ "{{baseUrl}}" ], - "query": [ - { - "disabled": true, - "description": { - "content": "Comma delimited list of relations to include", - "type": "text/plain" - }, - "key": "include", - "value": "" - } - ], + "query": [], "variable": [ { "disabled": false, @@ -3365,6 +3376,10 @@ ] }, "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, { "key": "Accept", "value": "application/json" @@ -3378,8 +3393,17 @@ "value": "" } ], - "method": "GET", - "body": {} + "method": "PATCH", + "body": { + "mode": "raw", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_numbers\": [\n \"\",\n \"\"\n ]\n },\n \"type\": \"container\",\n \"id\": \"\"\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } }, "status": "OK", "code": 200, @@ -3389,7 +3413,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"flat rack\",\n \"equipment_length\": 45,\n \"equipment_height\": \"high_cube\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"total\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"delivered\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": null\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ]\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"dry\",\n \"equipment_length\": 45,\n \"equipment_height\": \"standard\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"total\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"not_available\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -3400,7 +3424,7 @@ } }, { - "id": "2add22ee-658f-47f1-9362-c892bcc60deb", + "id": "3d542df6-6eec-4a52-9af1-3d8b6cabc64c", "name": "Get a container's raw events", "request": { "name": "Get a container's raw events", @@ -3443,7 +3467,7 @@ }, "response": [ { - "id": "d2e7f2cc-7124-4179-b371-8b3748c32404", + "id": "9909830c-f9b5-4b69-9fc8-c8a00eac5575", "name": "OK", "originalRequest": { "url": { @@ -3494,7 +3518,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\",\n \"attributes\": {\n \"event\": \"feeder_departed\",\n \"original_event\": \"\",\n \"timestamp\": \"\",\n \"estimated\": \"\",\n \"actual_on\": \"\",\n \"estimated_on\": \"\",\n \"actual_at\": \"\",\n \"estimated_at\": \"\",\n \"timezone\": \"\",\n \"created_at\": \"\",\n \"location_name\": \"\",\n \"location_locode\": \"\",\n \"vessel_name\": \"\",\n \"vessel_imo\": \"\",\n \"index\": \"\",\n \"voyage_number\": \"\"\n },\n \"relationships\": {\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"port\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"vessel\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\",\n \"attributes\": {\n \"event\": \"positioned_in\",\n \"original_event\": \"\",\n \"timestamp\": \"\",\n \"estimated\": \"\",\n \"actual_on\": \"\",\n \"estimated_on\": \"\",\n \"actual_at\": \"\",\n \"estimated_at\": \"\",\n \"timezone\": \"\",\n \"created_at\": \"\",\n \"location_name\": \"\",\n \"location_locode\": \"\",\n \"vessel_name\": \"\",\n \"vessel_imo\": \"\",\n \"index\": \"\",\n \"voyage_number\": \"\"\n },\n \"relationships\": {\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"port\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"vessel\"\n }\n }\n }\n }\n ]\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\",\n \"attributes\": {\n \"event\": \"delivered\",\n \"original_event\": \"\",\n \"timestamp\": \"\",\n \"estimated\": \"\",\n \"actual_on\": \"\",\n \"estimated_on\": \"\",\n \"actual_at\": \"\",\n \"estimated_at\": \"\",\n \"timezone\": \"\",\n \"created_at\": \"\",\n \"location_name\": \"\",\n \"location_locode\": \"\",\n \"vessel_name\": \"\",\n \"vessel_imo\": \"\",\n \"index\": \"\",\n \"voyage_number\": \"\"\n },\n \"relationships\": {\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"port\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"vessel\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\",\n \"attributes\": {\n \"event\": \"feeder_arrived\",\n \"original_event\": \"\",\n \"timestamp\": \"\",\n \"estimated\": \"\",\n \"actual_on\": \"\",\n \"estimated_on\": \"\",\n \"actual_at\": \"\",\n \"estimated_at\": \"\",\n \"timezone\": \"\",\n \"created_at\": \"\",\n \"location_name\": \"\",\n \"location_locode\": \"\",\n \"vessel_name\": \"\",\n \"vessel_imo\": \"\",\n \"index\": \"\",\n \"voyage_number\": \"\"\n },\n \"relationships\": {\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"metro_area\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"vessel\"\n }\n }\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -3505,7 +3529,7 @@ } }, { - "id": "1e439b31-ba66-472a-add1-b22238d164dc", + "id": "ed23ab1f-6deb-45ee-94f2-545a1a802ce1", "name": "Get a container's transport events", "request": { "name": "Get a container's transport events", @@ -3558,7 +3582,7 @@ }, "response": [ { - "id": "f83f76ad-b882-408f-8e43-427b11e1827c", + "id": "36a06992-642c-4a91-b948-9e5e3237f689", "name": "OK", "originalRequest": { "url": { @@ -3619,7 +3643,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\",\n \"attributes\": {\n \"event\": \"container.transport.feeder_loaded\",\n \"voyage_number\": \"\",\n \"timestamp\": \"\",\n \"timezone\": \"\",\n \"location_locode\": \"\",\n \"created_at\": \"\",\n \"data_source\": \"terminal\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"metro_area\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"name\": \"vessel\"\n }\n },\n \"terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"rail_terminal\"\n }\n },\n \"container\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\",\n \"attributes\": {\n \"event\": \"container.transport.rail_loaded\",\n \"voyage_number\": \"\",\n \"timestamp\": \"\",\n \"timezone\": \"\",\n \"location_locode\": \"\",\n \"created_at\": \"\",\n \"data_source\": \"shipping_line\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"metro_area\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"name\": \"vessel\"\n }\n },\n \"terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"rail_terminal\"\n }\n },\n \"container\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\"\n }\n }\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"booking_cancelled\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"past_full_out_window\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\",\n \"attributes\": {\n \"event\": \"container.transport.full_in\",\n \"voyage_number\": \"\",\n \"timestamp\": \"\",\n \"timezone\": \"\",\n \"location_locode\": \"\",\n \"created_at\": \"\",\n \"data_source\": \"terminal\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"port\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"name\": \"vessel\"\n }\n },\n \"terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"container\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\",\n \"attributes\": {\n \"event\": \"container.transport.transshipment_departed\",\n \"voyage_number\": \"\",\n \"timestamp\": \"\",\n \"timezone\": \"\",\n \"location_locode\": \"\",\n \"created_at\": \"\",\n \"data_source\": \"ais\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"location\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"port\"\n }\n },\n \"vessel\": {\n \"data\": {\n \"id\": \"\",\n \"name\": \"vessel\"\n }\n },\n \"terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"container\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container\"\n }\n }\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": null\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": null\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -3630,7 +3654,7 @@ } }, { - "id": "51dc7507-1f53-4c2e-ad0b-5a8a252a1afd", + "id": "17be61bf-cbbd-4297-8625-b1db12eb168c", "name": "Get container map GeoJSON", "request": { "name": "Get container map GeoJSON", @@ -3673,7 +3697,7 @@ }, "response": [ { - "id": "ae417c4c-47b4-4df5-a6e6-7b0185ab2262", + "id": "132d5a90-713f-4cb2-99a8-06218b5dac82", "name": "OK", "originalRequest": { "url": { @@ -3729,7 +3753,7 @@ "_postman_previewlanguage": "json" }, { - "id": "a0249493-fb1a-477b-91c8-702b518cff62", + "id": "b29301ce-d8bb-4326-9f2b-7a4553c5b14f", "name": "Forbidden - Routing data feature is not enabled for this account", "originalRequest": { "url": { @@ -3791,7 +3815,7 @@ } }, { - "id": "9110f6a3-8764-4118-afb7-3e9019de74cd", + "id": "47672f16-7ca3-4f8e-8c20-824eacc11c07", "name": "Refresh container", "request": { "name": "Refresh container", @@ -3834,7 +3858,7 @@ }, "response": [ { - "id": "e2f194b4-e018-46c8-b1da-53b60f6c5bbd", + "id": "1d613145-cc07-4d22-b5f6-b2c02eb350eb", "name": "OK", "originalRequest": { "url": { @@ -3890,7 +3914,7 @@ "_postman_previewlanguage": "json" }, { - "id": "49e1a851-791b-4e39-addb-65ee1c492645", + "id": "325398f6-7a0d-4be2-9a4a-55735c9955d2", "name": "Forbidden - This API endpoint is not enabled for your account. Please contact support@terminal49.com", "originalRequest": { "url": { @@ -3946,7 +3970,7 @@ "_postman_previewlanguage": "json" }, { - "id": "038e281e-9d1b-44a6-a7cc-0373777bcc06", + "id": "cb6b390e-84c4-4ad3-84ce-87848e2a136b", "name": "Too Many Requests - You've hit the refresh limit. Please try again in a minute.", "originalRequest": { "url": { @@ -4017,7 +4041,7 @@ } }, { - "id": "91508c7c-9c98-4ee2-a783-40a4cda68435", + "id": "31b1eada-1ca6-4684-84f4-e374e0e6d481", "name": "List container custom fields", "request": { "name": "List container custom fields", @@ -4057,7 +4081,7 @@ }, "response": [ { - "id": "89548b2e-b3e5-471a-8e57-eaa1bc7e91cb", + "id": "55a08ac2-2782-40e2-bba9-0e815d51f7c3", "name": "OK", "originalRequest": { "url": { @@ -4108,7 +4132,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"shipment\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -4119,7 +4143,7 @@ } }, { - "id": "751c6b9b-96e5-41e3-bd78-889178d3569d", + "id": "54422496-ffad-4956-82e7-e526097bd5d3", "name": "Create a container custom field", "request": { "name": "Create a container custom field", @@ -4172,7 +4196,7 @@ }, "response": [ { - "id": "590df586-777d-4339-8f1e-7ea43706798d", + "id": "2fd079bd-212f-44a2-8b58-22987032d681", "name": "Created", "originalRequest": { "url": { @@ -4236,7 +4260,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -4247,7 +4271,7 @@ } }, { - "id": "c11c02a7-73f1-4dd7-8bc0-79c780544d0a", + "id": "0cfc5652-55c3-4fed-a3c0-cbd0b79c70e6", "name": "Update a container custom field", "request": { "name": "Update a container custom field", @@ -4311,7 +4335,7 @@ }, "response": [ { - "id": "e68b0ac7-f14d-4897-9867-49bac674b14c", + "id": "40f19516-543d-4207-8234-d8056324773c", "name": "OK", "originalRequest": { "url": { @@ -4386,7 +4410,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -4397,7 +4421,7 @@ } }, { - "id": "0c339740-d8a1-4da8-b127-60b19c469e57", + "id": "ccd7b595-fb7c-4b77-b8fc-5702a502ad45", "name": "Delete a container custom field", "request": { "name": "Delete a container custom field", @@ -4442,7 +4466,7 @@ }, "response": [ { - "id": "d4bdd221-fae8-44f7-ab16-83f258b31249", + "id": "1444b268-db46-4c66-9330-5972b720730b", "name": "No Content", "originalRequest": { "url": { @@ -4511,7 +4535,7 @@ "description": "", "item": [ { - "id": "ecc83162-533a-42c1-81ba-cd53ee4d5c6d", + "id": "40228195-ead1-46c6-afad-5536a5f01e46", "name": "List custom field definitions", "request": { "name": "List custom field definitions", @@ -4584,7 +4608,7 @@ }, "response": [ { - "id": "2817cd74-c549-463f-9214-cb36beb7c802", + "id": "3ff62571-139e-4f22-bc22-f143f29f1891", "name": "OK", "originalRequest": { "url": { @@ -4668,7 +4692,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Container\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"number\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": 5401.992165513655\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"boolean\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": 1787.6277284335795,\n \"key_1\": 424\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"number\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": false,\n \"key_1\": 3346\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"TrackingRequest\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"boolean\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": 697.797071541788,\n \"key_1\": \"string\"\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -4679,7 +4703,7 @@ } }, { - "id": "fcb5ff0d-a35b-4863-b249-1411950e9528", + "id": "73ef9a01-488b-49dd-b4e1-3418036d8575", "name": "Create a custom field definition", "request": { "name": "Create a custom field definition", @@ -4707,7 +4731,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"enum_multi\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": true,\n \"key_1\": 2813.6182618768635\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"datetime\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": 8033\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -4719,7 +4743,7 @@ }, "response": [ { - "id": "6fdeb931-50f6-4416-ae59-408ae3bc84f1", + "id": "2bb766ba-14dc-428c-adf2-7c8e59c699fb", "name": "Created", "originalRequest": { "url": { @@ -4753,7 +4777,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"enum_multi\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": true,\n \"key_1\": 2813.6182618768635\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"datetime\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": 8033\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -4770,7 +4794,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"date\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": 5830\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"TrackingRequest\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"enum\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": \"string\"\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -4781,7 +4805,7 @@ } }, { - "id": "5bc8b47f-90f4-4f0a-9cf0-0f5f43ad3802", + "id": "d451be06-36e0-42b8-be5c-62b33272847c", "name": "Get a custom field definition", "request": { "name": "Get a custom field definition", @@ -4820,7 +4844,7 @@ }, "response": [ { - "id": "7836cc9a-d513-4e6d-a2f7-267976934f73", + "id": "cbd8e1ff-aac5-4c17-81da-73be157c4130", "name": "OK", "originalRequest": { "url": { @@ -4870,7 +4894,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"date\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": 5830\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"TrackingRequest\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"enum\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": \"string\"\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -4881,7 +4905,7 @@ } }, { - "id": "339855b0-0285-4349-a867-610bae539474", + "id": "dcea5916-8f41-4313-af15-3fd6fa17d163", "name": "Update a custom field definition", "request": { "name": "Update a custom field definition", @@ -4921,7 +4945,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"display_name\": \"\",\n \"description\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": true,\n \"key_2\": true,\n \"key_3\": 6190.054413578288\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"display_name\": \"\",\n \"description\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": true\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -4933,7 +4957,7 @@ }, "response": [ { - "id": "fae50da3-0ab8-4f3b-b1b7-5bf2ecf43962", + "id": "6b39d3a8-2eb6-4663-bec4-6aa3e0d3028f", "name": "OK", "originalRequest": { "url": { @@ -4979,7 +5003,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"display_name\": \"\",\n \"description\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": true,\n \"key_2\": true,\n \"key_3\": 6190.054413578288\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"display_name\": \"\",\n \"description\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": true\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -4996,7 +5020,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"Shipment\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"date\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": 5830\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field_definition\",\n \"attributes\": {\n \"entity_type\": \"TrackingRequest\",\n \"api_slug\": \"\",\n \"display_name\": \"\",\n \"data_type\": \"enum\",\n \"description\": \"\",\n \"reference_type\": \"\",\n \"validation\": {\n \"key_0\": \"string\",\n \"key_1\": \"string\"\n },\n \"default_format\": \"\",\n \"default_value\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -5007,7 +5031,7 @@ } }, { - "id": "71b7022a-90f5-4b8e-9453-ee9b8de8d281", + "id": "1ba95aef-e3d1-4b27-9c58-a90c5c1fdc14", "name": "Delete a custom field definition", "request": { "name": "Delete a custom field definition", @@ -5040,7 +5064,7 @@ }, "response": [ { - "id": "6a94a2c5-bdac-4ce1-a835-954830aa5759", + "id": "5efa6386-2ab6-45af-8c2f-ad7ee9cee786", "name": "OK", "originalRequest": { "url": { @@ -5097,7 +5121,7 @@ "description": "", "item": [ { - "id": "6d47aa6c-0768-4ff1-b4d1-d3069ed9349d", + "id": "3d5a8cb4-d8bc-4c73-8e2d-f71ac91e6c09", "name": "List custom field options", "request": { "name": "List custom field options", @@ -5137,7 +5161,7 @@ }, "response": [ { - "id": "07431484-cec2-420e-894a-1c90f43feeb8", + "id": "3ec781cb-6fa8-4b53-9fcb-8374028479a3", "name": "OK", "originalRequest": { "url": { @@ -5199,7 +5223,7 @@ } }, { - "id": "218365e4-b0e5-4d3d-86ce-b5a5a8778376", + "id": "83f58973-34d6-48d6-83e8-326f0f59944e", "name": "Create a custom field option", "request": { "name": "Create a custom field option", @@ -5252,7 +5276,7 @@ }, "response": [ { - "id": "711c22b4-953c-47e1-a685-8b76df4fb160", + "id": "59f00d09-4522-4b61-b843-efb47135a504", "name": "Created", "originalRequest": { "url": { @@ -5327,7 +5351,7 @@ } }, { - "id": "589d1e3a-751d-4218-a9d3-06e2daa38cab", + "id": "98b4db9c-7194-49fc-8b87-f887a03f2ebf", "name": "Get a custom field option", "request": { "name": "Get a custom field option", @@ -5378,7 +5402,7 @@ }, "response": [ { - "id": "b7d64557-fcc4-41d0-a3a8-d863183b57af", + "id": "8c70a6c9-3493-4a8a-9930-b8eceddf9c76", "name": "OK", "originalRequest": { "url": { @@ -5451,7 +5475,7 @@ } }, { - "id": "9a7ec980-b742-415c-809e-01628db27e9e", + "id": "4dc60d05-8fee-4bd0-89a6-539acb5cc71a", "name": "Update a custom field option", "request": { "name": "Update a custom field option", @@ -5515,7 +5539,7 @@ }, "response": [ { - "id": "26f632ae-22d2-490c-8196-244c49c8c4b3", + "id": "afa0c91c-7389-4162-81cb-8d7c505ba843", "name": "OK", "originalRequest": { "url": { @@ -5601,7 +5625,7 @@ } }, { - "id": "e0cc3e99-74f0-45a7-8397-6800079ec595", + "id": "0a36749c-5253-4e62-bfda-551cbc7c1ef8", "name": "Delete a custom field option", "request": { "name": "Delete a custom field option", @@ -5646,7 +5670,7 @@ }, "response": [ { - "id": "447cb277-a99f-4abf-9f56-83e90957cdd9", + "id": "8a6a2ac2-2559-40fc-9c6f-5d4749b96b4f", "name": "OK", "originalRequest": { "url": { @@ -5715,7 +5739,7 @@ "description": "", "item": [ { - "id": "be49ef49-7edd-400d-a32d-835ab78b6c9c", + "id": "12cbabf9-fb81-4d51-8bd9-58a3d68365a3", "name": "List custom fields", "request": { "name": "List custom fields", @@ -5788,7 +5812,7 @@ }, "response": [ { - "id": "c4c70fd6-00a2-468b-b0b4-e54d5a470cec", + "id": "0bd67042-7f04-415d-8223-674727e4c211", "name": "OK", "originalRequest": { "url": { @@ -5872,7 +5896,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"shipment\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -5883,7 +5907,7 @@ } }, { - "id": "6a40a226-33e5-4670-80b3-2f1e9db68f26", + "id": "8eed38ec-4722-4b7a-86ac-6d005e7c79d4", "name": "Create a custom field", "request": { "name": "Create a custom field", @@ -5911,7 +5935,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"shipment\",\n \"id\": \"\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -5923,7 +5947,7 @@ }, "response": [ { - "id": "6d0b9149-9fdf-4c88-89c9-e970bb9eeba5", + "id": "d7a96d81-0b1b-45c7-9bb7-82dd96f06811", "name": "Created", "originalRequest": { "url": { @@ -5957,7 +5981,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"shipment\",\n \"id\": \"\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -5974,7 +5998,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -5985,7 +6009,7 @@ } }, { - "id": "48c1faca-377a-4212-8292-9d2c26294226", + "id": "09803e3c-88c4-4ee4-948b-ed1640818fbf", "name": "Get a custom field", "request": { "name": "Get a custom field", @@ -6024,7 +6048,7 @@ }, "response": [ { - "id": "c9ba1d92-a2e3-4b5c-a757-ccf95eac90d8", + "id": "db0ac9ec-ba7e-4dd2-9263-ceb3cf1c61f3", "name": "OK", "originalRequest": { "url": { @@ -6074,7 +6098,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -6085,7 +6109,7 @@ } }, { - "id": "4147a014-fe32-4330-b49a-b03d6054ecc5", + "id": "45c385c3-af68-473b-b83c-9f7c7d47d2a8", "name": "Update a custom field", "request": { "name": "Update a custom field", @@ -6137,7 +6161,7 @@ }, "response": [ { - "id": "5bd0f88f-a210-4f6d-a33b-abbce3ac73d0", + "id": "b6012441-dd9f-4db8-8123-4560af679b31", "name": "OK", "originalRequest": { "url": { @@ -6200,7 +6224,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -6211,7 +6235,7 @@ } }, { - "id": "e905a758-0ef8-4497-92b8-8949291ca359", + "id": "9881ca22-6b28-41ce-94be-cd5239d4fa1e", "name": "Delete a custom field", "request": { "name": "Delete a custom field", @@ -6244,7 +6268,7 @@ }, "response": [ { - "id": "bd225e1a-b2d0-4ebc-bb43-ee728ccccee4", + "id": "5a772ccf-b6f6-452e-8b37-0767a30efde0", "name": "OK", "originalRequest": { "url": { @@ -6301,7 +6325,7 @@ "description": "", "item": [ { - "id": "207b42ce-3554-4c86-bc2d-ecbdb68bddc7", + "id": "92f40712-a23a-46f8-860d-5e8b88ae6852", "name": "List shipments", "request": { "name": "List shipments", @@ -6459,7 +6483,7 @@ "type": "text/plain" }, "key": "filter[voyage_status]", - "value": "arrived" + "value": "on_ship" }, { "disabled": true, @@ -6773,7 +6797,7 @@ }, "response": [ { - "id": "354d4304-10d9-48a5-8679-80ccbac22279", + "id": "55c56c47-44bb-42bf-8afe-4f5a014f75a0", "name": "OK", "originalRequest": { "url": { @@ -6926,7 +6950,7 @@ "type": "text/plain" }, "key": "filter[voyage_status]", - "value": "arrived" + "value": "on_ship" }, { "disabled": true, @@ -7226,12 +7250,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"past_full_out_window\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"tank\",\n \"equipment_length\": null,\n \"equipment_height\": \"standard\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"extended_dwell_time\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"on_rail\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"reefer\",\n \"equipment_length\": 20,\n \"equipment_height\": null,\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"extended_dwell_time\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"grounded\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"past_arrival_window\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"tank\",\n \"equipment_length\": 20,\n \"equipment_height\": \"high_cube\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"not_available\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"bulk\",\n \"equipment_length\": 20,\n \"equipment_height\": \"high_cube\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"total\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"exam\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"on_ship\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "f812e59c-4d4e-4c81-ad2c-9d2d91a4a6c1", + "id": "2e0af7c6-652e-4f76-ad5d-1cfc01266b7c", "name": "Malformed supported filter value, operator, range, or strict boolean. The error identifies the invalid parameter where available.", "originalRequest": { "url": { @@ -7384,7 +7408,7 @@ "type": "text/plain" }, "key": "filter[voyage_status]", - "value": "arrived" + "value": "on_ship" }, { "disabled": true, @@ -7684,7 +7708,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -7695,7 +7719,7 @@ } }, { - "id": "66a0c8b3-8386-4721-8dc2-59ff03de33d6", + "id": "0fac7f6c-053d-49f6-b868-5acc537c2ae1", "name": "Get a shipment", "request": { "name": "Get a shipment", @@ -7756,7 +7780,7 @@ }, "response": [ { - "id": "631ddfb3-f2a7-47ad-a8fe-b33752b79548", + "id": "ddba50a4-064d-4bc5-abe4-f38597d57c2a", "name": "OK", "originalRequest": { "url": { @@ -7825,12 +7849,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"open top\",\n \"equipment_length\": null,\n \"equipment_height\": null,\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"on_ship\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"tank\",\n \"equipment_length\": 40,\n \"equipment_height\": \"standard\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"demurrage\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"extended_dwell_time\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"on_ship\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n ]\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"dry\",\n \"equipment_length\": 45,\n \"equipment_height\": \"high_cube\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"pending\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"exam\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"exam\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"new\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"container\",\n \"attributes\": {\n \"number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"equipment_type\": \"tank\",\n \"equipment_length\": 20,\n \"equipment_height\": \"standard\",\n \"weight_in_lbs\": \"\",\n \"created_at\": \"\",\n \"seal_number\": \"\",\n \"pickup_lfd\": \"\",\n \"pickup_appointment_at\": \"\",\n \"availability_known\": \"\",\n \"available_for_pickup\": \"\",\n \"pod_arrived_at\": \"\",\n \"pod_discharged_at\": \"\",\n \"pod_full_out_at\": \"\",\n \"terminal_checked_at\": \"\",\n \"pod_full_out_chassis_number\": \"\",\n \"location_at_pod_terminal\": \"\",\n \"final_destination_full_out_at\": \"\",\n \"empty_terminated_at\": \"\",\n \"holds_at_pod_terminal\": [\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n },\n {\n \"name\": \"\",\n \"status\": \"hold\",\n \"description\": \"\"\n }\n ],\n \"fees_at_pod_terminal\": [\n {\n \"type\": \"extended_dwell_time\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n },\n {\n \"type\": \"other\",\n \"amount\": \"\",\n \"currency_code\": \"\"\n }\n ],\n \"pod_timezone\": \"\",\n \"final_destination_timezone\": \"\",\n \"empty_terminated_timezone\": \"\",\n \"pod_rail_carrier_scac\": \"\",\n \"ind_rail_carrier_scac\": \"\",\n \"pod_last_tracking_request_at\": \"\",\n \"shipment_last_tracking_request_at\": \"\",\n \"pod_rail_loaded_at\": \"\",\n \"pod_rail_departed_at\": \"\",\n \"ind_eta_at\": \"\",\n \"ind_ata_at\": \"\",\n \"ind_rail_unloaded_at\": \"\",\n \"ind_facility_lfd_on\": \"\",\n \"import_deadlines\": {\n \"pickup_lfd_terminal\": \"\",\n \"pickup_lfd_rail\": \"\",\n \"pickup_lfd_line\": \"\"\n },\n \"current_status\": \"grounded\"\n },\n \"relationships\": {\n \"shipment\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"pickup_facility\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"terminal\"\n }\n },\n \"transport_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"transport_event\"\n }\n ]\n },\n \"raw_events\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n },\n {\n \"id\": \"\",\n \"type\": \"raw_event\"\n }\n ]\n }\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "e8d69bcb-43c3-43b6-960f-b0fa38ed94d8", + "id": "b7483b4f-02cb-4665-9cef-9b6569feac7b", "name": "Not Found", "originalRequest": { "url": { @@ -7899,12 +7923,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "f3efebc3-81fe-4368-8c4b-402a8887b0ca", + "id": "18497a46-aa47-4ab6-8276-33f22eb8a9bd", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -7973,7 +7997,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -7984,7 +8008,7 @@ } }, { - "id": "12506961-0908-4517-b7c6-f52b86618f27", + "id": "921d6c16-f74f-4f28-8385-259fe5f3b218", "name": "Edit a shipment", "request": { "name": "Edit a shipment", @@ -8039,7 +8063,7 @@ }, "response": [ { - "id": "bf2a88d2-71dd-4ce2-8837-ce95b81f496e", + "id": "89faa5ea-b875-4b8b-ad45-4daed0a3ae46", "name": "OK", "originalRequest": { "url": { @@ -8102,7 +8126,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"no_updates_at_line\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -8113,7 +8137,7 @@ } }, { - "id": "ad10480b-dd6d-4893-b9db-f07f1df3ee5f", + "id": "c6f4264b-658a-46df-9105-1c3e41b6037f", "name": "Stop tracking a shipment", "request": { "name": "Stop tracking a shipment", @@ -8156,7 +8180,7 @@ }, "response": [ { - "id": "8611d4f8-da1b-43a3-b58e-1e516f8e761f", + "id": "10757750-e1aa-493e-a95b-298e76ccf2cc", "name": "OK", "originalRequest": { "url": { @@ -8207,7 +8231,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"no_updates_at_line\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -8218,7 +8242,7 @@ } }, { - "id": "9e20293b-c5ac-432b-bd67-a234d0115c97", + "id": "6e1862b0-cc09-492d-b4c8-e3e589e360b2", "name": "Resume tracking a shipment", "request": { "name": "Resume tracking a shipment", @@ -8261,7 +8285,7 @@ }, "response": [ { - "id": "87c04054-4582-4be0-b8c3-045d84fc089d", + "id": "ea0a4c37-5f21-457d-aa22-9bd0d3221d16", "name": "OK", "originalRequest": { "url": { @@ -8312,7 +8336,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"all_containers_terminated\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\",\n \"attributes\": {\n \"bill_of_lading_number\": \"\",\n \"normalized_number\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"tags\": [\n \"\",\n \"\"\n ],\n \"port_of_lading_locode\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_locode\": \"\",\n \"port_of_discharge_name\": \"\",\n \"destination_locode\": \"\",\n \"destination_name\": \"\",\n \"shipping_line_scac\": \"\",\n \"shipping_line_name\": \"\",\n \"shipping_line_short_name\": \"\",\n \"customer_name\": \"\",\n \"pod_vessel_name\": \"\",\n \"pod_vessel_imo\": \"\",\n \"pod_voyage_number\": \"\",\n \"pol_etd_at\": \"\",\n \"pol_atd_at\": \"\",\n \"pod_eta_at\": \"\",\n \"pod_original_eta_at\": \"\",\n \"pod_ata_at\": \"\",\n \"destination_eta_at\": \"\",\n \"destination_ata_at\": \"\",\n \"pol_timezone\": \"\",\n \"pod_timezone\": \"\",\n \"destination_timezone\": \"\",\n \"line_tracking_last_attempted_at\": \"\",\n \"line_tracking_last_succeeded_at\": \"\",\n \"line_tracking_stopped_at\": \"\",\n \"line_tracking_stopped_reason\": \"no_updates_at_line\"\n },\n \"relationships\": {\n \"destination\": {\n \"data\": {\n \"type\": \"metro_area\",\n \"id\": \"\"\n }\n },\n \"port_of_lading\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"containers\": {\n \"data\": [\n {\n \"type\": \"container\",\n \"id\": \"\"\n },\n {\n \"type\": \"container\",\n \"id\": \"\"\n }\n ]\n },\n \"port_of_discharge\": {\n \"data\": {\n \"type\": \"port\",\n \"id\": \"\"\n }\n },\n \"pod_terminal\": {\n \"data\": {\n \"type\": \"terminal\",\n \"id\": \"\"\n }\n },\n \"destination_terminal\": {\n \"data\": {\n \"type\": \"rail_terminal\",\n \"id\": \"\"\n }\n },\n \"line_tracking_stopped_by_user\": {\n \"data\": {\n \"type\": \"user\",\n \"id\": \"\"\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -8323,7 +8347,7 @@ } }, { - "id": "a06e8ff7-22b1-4aaf-9302-10c8c5efc9d3", + "id": "c9f55e3a-26b5-40c8-838a-95002e8272af", "name": "List shipment custom fields", "request": { "name": "List shipment custom fields", @@ -8363,7 +8387,7 @@ }, "response": [ { - "id": "2cf40f48-31b4-4a8a-bb04-f500797c5018", + "id": "d88a5b03-aa87-4954-a2ef-5c20e5183a5c", "name": "OK", "originalRequest": { "url": { @@ -8414,7 +8438,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"shipment\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -8425,7 +8449,7 @@ } }, { - "id": "cfb2b1b7-9a92-4731-9fa4-fe9d5b185b60", + "id": "95962abe-68f1-4a57-8f44-5e02530b3fc9", "name": "Create a shipment custom field", "request": { "name": "Create a shipment custom field", @@ -8478,7 +8502,7 @@ }, "response": [ { - "id": "e7bc36b7-2064-448e-ac27-eeeddd753a83", + "id": "6c6f2ba6-40af-4fe2-9144-a8ec652685c0", "name": "Created", "originalRequest": { "url": { @@ -8542,7 +8566,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -8553,7 +8577,7 @@ } }, { - "id": "edb24b2d-11b9-4ee1-a71f-73e9f1c39881", + "id": "76af70fc-8b32-4032-8761-26622965fb03", "name": "Update a shipment custom field", "request": { "name": "Update a shipment custom field", @@ -8617,7 +8641,7 @@ }, "response": [ { - "id": "e44900b2-a8fa-43c0-8edd-4552dd145c0f", + "id": "79f05589-2b74-48e6-9b4b-737bd84e1b86", "name": "OK", "originalRequest": { "url": { @@ -8692,7 +8716,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -8703,7 +8727,7 @@ } }, { - "id": "f88718a0-5e43-4a60-bd69-a03c5dc02ce0", + "id": "850e9120-e9e6-4832-b0c3-5614a1f3631a", "name": "Delete a shipment custom field", "request": { "name": "Delete a shipment custom field", @@ -8748,7 +8772,7 @@ }, "response": [ { - "id": "73e13216-5abc-4805-83cc-6a7fc9c66562", + "id": "5885d5d3-ff04-4fbb-ae13-0ce6df8e0b8a", "name": "No Content", "originalRequest": { "url": { @@ -8827,7 +8851,7 @@ "description": "", "item": [ { - "id": "468f7b74-337e-44cc-8974-a371b2850174", + "id": "c29b5e25-3a37-4238-9ef4-e60cef3c197e", "name": "Create a tracking request", "request": { "name": "Create a tracking request", @@ -8858,7 +8882,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"bill_of_lading\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"container\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -8886,7 +8910,7 @@ }, "response": [ { - "id": "490a299f-b006-4303-a5c6-301f63a91de3", + "id": "22568cac-b142-4b62-9172-6775a6e652e7", "name": "Tracking Request Created", "originalRequest": { "url": { @@ -8920,7 +8944,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"bill_of_lading\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"container\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -8937,12 +8961,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"tracking_stopped\",\n \"request_type\": \"booking_number\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"retries_exhausted\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ]\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"created\",\n \"request_type\": \"bill_of_lading\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": null,\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "8838e39a-00ee-4438-8037-df3366698116", + "id": "3cec7bdd-b4d6-4fc6-ae96-84a45dd904ec", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -8976,7 +9000,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"bill_of_lading\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"container\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -8993,12 +9017,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "a17cfa44-273a-4450-a9ad-e215af06c6d7", + "id": "52a5f018-e313-4ccb-904f-282f84713568", "name": "Too Many Requests - You've hit the create tracking requests limit. Please try again in a minute.", "originalRequest": { "url": { @@ -9032,7 +9056,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"bill_of_lading\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_type\": \"container\",\n \"request_number\": \"\",\n \"scac\": \"\",\n \"auto_detect_vocc_scac\": false,\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"shipment_tags\": [\n \"\",\n \"\"\n ],\n \"initial_custom_fields\": {\n \"shipment\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\"\n }\n ],\n \"containers\": [\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n },\n {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"number\": \"\"\n }\n ]\n }\n },\n \"relationships\": {\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"shipper\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"consignee\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"notify_party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"customs_broker\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"freight_forwarder\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n },\n \"pickup_dray_carrier\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -9069,7 +9093,7 @@ } }, { - "id": "c0676922-abf3-467e-b86f-2b5de35138e4", + "id": "b8468c6b-f3bb-4d6a-95d3-f08e0a3c916c", "name": "List tracking requests", "request": { "name": "List tracking requests", @@ -9110,7 +9134,7 @@ "type": "text/plain" }, "key": "filter[status]", - "value": "pending" + "value": "created" }, { "disabled": true, @@ -9199,7 +9223,7 @@ }, "response": [ { - "id": "84b1be97-f853-41d7-af79-68af20c52b81", + "id": "a5748f22-3a1b-4b3b-b1e8-ab876d16fe9d", "name": "OK", "originalRequest": { "url": { @@ -9235,7 +9259,7 @@ "type": "text/plain" }, "key": "filter[status]", - "value": "pending" + "value": "created" }, { "disabled": true, @@ -9337,12 +9361,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"awaiting_manifest\",\n \"request_type\": \"bill_of_lading\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"retries_exhausted\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"awaiting_manifest\",\n \"request_type\": \"bill_of_lading\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"booking_cancelled\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ]\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"created\",\n \"request_type\": \"booking_number\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"retries_exhausted\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"awaiting_manifest\",\n \"request_type\": \"container\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"shipping_line_unreachable\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "0a333cf7-27ba-48ef-8606-a46f188bfc4b", + "id": "852af0ea-89a9-46d1-8fde-7410bee15305", "name": "Not Found", "originalRequest": { "url": { @@ -9378,7 +9402,7 @@ "type": "text/plain" }, "key": "filter[status]", - "value": "pending" + "value": "created" }, { "disabled": true, @@ -9480,7 +9504,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -9491,7 +9515,7 @@ } }, { - "id": "e41d9bea-7ddf-467e-965a-a297931c315c", + "id": "5687bc8d-7478-411a-b0cc-10c4f9ad4034", "name": "Infer Tracking Number", "request": { "name": "Infer Tracking Number", @@ -9551,7 +9575,7 @@ }, "response": [ { - "id": "26ddfcee-aa53-4473-8e2a-8d239fe9a897", + "id": "7fa5af20-8e63-42b0-ab53-b890c3e96e25", "name": "Successfully inferred number type and shipping line", "originalRequest": { "url": { @@ -9608,7 +9632,7 @@ "_postman_previewlanguage": "json" }, { - "id": "7a8319ed-827f-401d-9b5d-08058f6f098a", + "id": "fda806c5-bdfd-42e7-8cfa-3668a917478b", "name": "Unprocessable Entity - Invalid tracking number format", "originalRequest": { "url": { @@ -9665,7 +9689,7 @@ "_postman_previewlanguage": "json" }, { - "id": "bc9991b7-4a87-4e9a-8c97-8440409d8b7f", + "id": "97c4d585-8668-43fd-9ac3-f4ab61935dfd", "name": "Too Many Requests - Rate limit exceeded", "originalRequest": { "url": { @@ -9737,7 +9761,7 @@ } }, { - "id": "1ea088c4-861a-4fa5-a153-a3ad3b81a2b9", + "id": "6d6eeb77-eaf2-495a-b202-fb1c7f15bb8b", "name": "Get a single tracking request", "request": { "name": "Get a single tracking request", @@ -9789,7 +9813,7 @@ }, "response": [ { - "id": "1b89b25b-231e-4f73-b5f6-2658f65b4144", + "id": "3c8a1612-3aad-45a6-993f-ff55e90479f6", "name": "OK", "originalRequest": { "url": { @@ -9849,12 +9873,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"tracking_stopped\",\n \"request_type\": \"booking_number\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"retries_exhausted\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ]\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"created\",\n \"request_type\": \"bill_of_lading\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": null,\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "39bed141-e728-4802-8cc6-a32260e9e992", + "id": "6f5251ec-aed6-4526-b0e0-ace306bd9a6a", "name": "Not Found", "originalRequest": { "url": { @@ -9914,7 +9938,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -9925,7 +9949,7 @@ } }, { - "id": "00bc0ff0-ed33-4153-a3bd-880e9d8ae519", + "id": "d5c155e1-4ed5-4971-a418-97d15ad9fa85", "name": "Edit a tracking request", "request": { "name": "Edit a tracking request", @@ -9968,7 +9992,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_number\": \"\"\n },\n \"type\": 2324.6411300637615\n }\n}", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_number\": \"\"\n },\n \"type\": \"string\"\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -9980,7 +10004,7 @@ }, "response": [ { - "id": "b1621dab-fe54-4517-8da5-fd2543d49127", + "id": "6a56419a-a8a2-448e-bc43-b493eb92980b", "name": "OK", "originalRequest": { "url": { @@ -10026,7 +10050,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_number\": \"\"\n },\n \"type\": 2324.6411300637615\n }\n}", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"ref_number\": \"\"\n },\n \"type\": \"string\"\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -10043,7 +10067,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"tracking_stopped\",\n \"request_type\": \"booking_number\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"unrecognized_response\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"request_number\": \"\",\n \"status\": \"awaiting_manifest\",\n \"request_type\": \"booking_number\",\n \"scac\": \"\",\n \"created_at\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"tags\": [\n \"\",\n \"\"\n ],\n \"failed_reason\": \"duplicate\",\n \"updated_at\": \"\",\n \"is_retrying\": \"\",\n \"retry_count\": \"\"\n },\n \"relationships\": {\n \"tracked_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n },\n \"customer\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n }\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10054,7 +10078,7 @@ } }, { - "id": "6e575cc9-93ba-473a-b832-be9247fef98c", + "id": "3bb25ed3-32fa-433e-9205-3c3aef51a766", "name": "List tracking request custom fields", "request": { "name": "List tracking request custom fields", @@ -10094,7 +10118,7 @@ }, "response": [ { - "id": "77b52297-fea9-4d5b-8213-4b1a5b03d0d7", + "id": "c64de3b2-03c0-4e15-bf05-b6f162fdfc5d", "name": "OK", "originalRequest": { "url": { @@ -10145,7 +10169,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"shipment\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10156,7 +10180,7 @@ } }, { - "id": "c04099e5-dcc9-4c17-9d5f-65c0216ad9fe", + "id": "d74fe99d-a5ff-4952-859a-c12ae774160d", "name": "Create a tracking request custom field", "request": { "name": "Create a tracking request custom field", @@ -10209,7 +10233,7 @@ }, "response": [ { - "id": "83590c14-f55f-450e-961c-407c5abec517", + "id": "cb936dcd-baf5-4043-9267-cd32029ea44a", "name": "Created", "originalRequest": { "url": { @@ -10273,7 +10297,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10284,7 +10308,7 @@ } }, { - "id": "8be615b4-07ac-4c2e-a7db-5e35ca08d6f4", + "id": "a5299cd0-04ce-42a5-812c-4c5beb1d857b", "name": "Update a tracking request custom field", "request": { "name": "Update a tracking request custom field", @@ -10348,7 +10372,7 @@ }, "response": [ { - "id": "66007714-13c6-4d31-8592-101d4d2b59f0", + "id": "c3415f6f-f64c-4b17-919d-cb5ad0044e67", "name": "OK", "originalRequest": { "url": { @@ -10423,7 +10447,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"tracking_request\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"custom_field\",\n \"attributes\": {\n \"api_slug\": \"\",\n \"value\": \"\",\n \"display_value\": \"\"\n },\n \"relationships\": {\n \"entity\": {\n \"data\": {\n \"type\": \"container\",\n \"id\": \"\"\n }\n },\n \"definition\": {\n \"data\": {\n \"type\": \"custom_field_definition\",\n \"id\": \"\"\n }\n }\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10434,7 +10458,7 @@ } }, { - "id": "ef4801ad-9b92-4a4e-9b0a-917b9874540f", + "id": "09ecaef4-66e6-45be-a92d-3922cc523cda", "name": "Delete a tracking request custom field", "request": { "name": "Delete a tracking request custom field", @@ -10479,7 +10503,7 @@ }, "response": [ { - "id": "10d7218a-007e-45d9-8b55-169f5d443c2b", + "id": "fe9a07f2-9ab9-4547-8908-d46fec08c1f0", "name": "No Content", "originalRequest": { "url": { @@ -10548,7 +10572,7 @@ "description": "", "item": [ { - "id": "bd400361-7d7d-4b26-80f9-52c066dfa447", + "id": "25805f8e-7a3a-456f-9956-a29111d78031", "name": "Get single webhook", "request": { "name": "Get single webhook", @@ -10590,7 +10614,7 @@ }, "response": [ { - "id": "7c821abf-cbc1-41ec-a7e4-cfc2937fefda", + "id": "8b97545e-8397-43f8-b7c8-25be8efa1e55", "name": "OK", "originalRequest": { "url": { @@ -10640,7 +10664,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.transshipment_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.vessel_loaded\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10651,7 +10675,7 @@ } }, { - "id": "212965b6-92d1-4cbb-9c15-e84444bf6264", + "id": "b2078262-7584-499a-9b01-f528bf7040b4", "name": "Edit a webhook", "request": { "name": "Edit a webhook", @@ -10694,7 +10718,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"events\": [\n \"container.transport.feeder_arrived\"\n ],\n \"active\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"events\": [\n \"container.transport.rail_loaded\"\n ],\n \"active\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -10706,7 +10730,7 @@ }, "response": [ { - "id": "06758234-0c31-446a-9c5e-4e667becafd6", + "id": "812c5f90-a075-4a1e-92e3-a9c3e05a1ae9", "name": "OK", "originalRequest": { "url": { @@ -10752,7 +10776,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"events\": [\n \"container.transport.feeder_arrived\"\n ],\n \"active\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"events\": [\n \"container.transport.rail_loaded\"\n ],\n \"active\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -10769,7 +10793,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.transshipment_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.vessel_loaded\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10780,7 +10804,7 @@ } }, { - "id": "fea5c915-1ed7-402a-8c65-03f97cda253e", + "id": "a3309e25-fe48-4914-8391-9bd99d19a3f3", "name": "Delete a webhook", "request": { "name": "Delete a webhook", @@ -10816,7 +10840,7 @@ }, "response": [ { - "id": "4ab40b6c-0baf-416e-a35a-bc2bf514ee90", + "id": "c191e358-0d07-4dd4-9355-f2e0a3253132", "name": "OK", "originalRequest": { "url": { @@ -10867,7 +10891,7 @@ } }, { - "id": "668b1b0f-efe1-4b9c-9399-5aa9c52c34ed", + "id": "6c791451-b6ce-42dc-b5fc-5da36f23b072", "name": "List webhooks", "request": { "name": "List webhooks", @@ -10916,7 +10940,7 @@ }, "response": [ { - "id": "27ff14c2-8e56-4781-a032-906ee56586d9", + "id": "654782d5-574f-4b9a-bd66-5bed59892f03", "name": "OK", "originalRequest": { "url": { @@ -10973,7 +10997,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.transshipment_loaded\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.transshipment_loaded\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ],\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"tracking_request.failed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.transshipment_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ],\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -10984,7 +11008,7 @@ } }, { - "id": "b85e8fc0-4e0d-4635-8e81-e05d9c647f62", + "id": "2996d681-d30f-4c85-b685-5376e360959f", "name": "Create a webhook", "request": { "name": "Create a webhook", @@ -11015,7 +11039,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"active\": \"\",\n \"events\": [\n \"tracking_request.failed\"\n ],\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"active\": \"\",\n \"events\": [\n \"container.transport.feeder_discharged\"\n ],\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -11027,7 +11051,7 @@ }, "response": [ { - "id": "6b527ba6-b197-44ad-9a59-e3edad77e40a", + "id": "cde031aa-d24e-41ee-ab6d-9edee7b1a367", "name": "Create a test webhook endpoint", "originalRequest": { "url": { @@ -11061,7 +11085,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"active\": \"\",\n \"events\": [\n \"tracking_request.failed\"\n ],\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", + "raw": "{\n \"data\": {\n \"attributes\": {\n \"url\": \"\",\n \"active\": \"\",\n \"events\": [\n \"container.transport.feeder_discharged\"\n ],\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n },\n \"type\": \"webhook\"\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -11078,7 +11102,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.transshipment_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.vessel_loaded\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -11089,7 +11113,7 @@ } }, { - "id": "a92d6d7a-17b8-47aa-b1f7-28a97b56a36c", + "id": "e2e23bd5-ea80-4909-a3b9-dcd0d395694a", "name": "List webhook events", "request": { "name": "List webhook events", @@ -11120,7 +11144,7 @@ }, "response": [ { - "id": "7867d9ca-0ef7-4b03-a9e3-eed8a286c744", + "id": "b0bb3f9e-d2b3-4ef3-aef9-25ac23403bdf", "name": "OK", "originalRequest": { "url": { @@ -11170,7 +11194,7 @@ } }, { - "id": "0b6aa0ec-4950-42c0-ad52-0f0deefed6c9", + "id": "6b7ad99a-80af-4263-b7d1-9807c23e2026", "name": "List webhook IPs", "request": { "name": "List webhook IPs", @@ -11201,7 +11225,7 @@ }, "response": [ { - "id": "f870a875-e3e7-41a7-ad0c-2521fd816b2c", + "id": "8f5e62e8-6917-4f6e-9550-8c5e5e81753b", "name": "OK", "originalRequest": { "url": { @@ -11251,7 +11275,7 @@ } }, { - "id": "1d9ced82-59f3-404c-948d-04b2b40a1fef", + "id": "aa64ced5-17a1-4f11-8f7e-70b03273779d", "name": "Trigger a webhook test delivery", "request": { "name": "Trigger a webhook test delivery", @@ -11295,7 +11319,7 @@ }, "response": [ { - "id": "dc6a3156-cedc-40af-b183-07f794ce7a60", + "id": "88e3d630-3497-4527-88c7-3cf149c8c211", "name": "Webhook test delivery attempt result", "originalRequest": { "url": { @@ -11347,12 +11371,12 @@ "value": "application/json" } ], - "body": "{\n \"url\": \"\",\n \"succeeded\": \"\",\n \"error\": \"\",\n \"status_code\": \"\",\n \"request_headers\": {\n \"key_0\": 9040\n },\n \"request_body\": \"\",\n \"response_headers\": {\n \"key_0\": 9738.941555559588,\n \"key_1\": 5802.091490474044\n },\n \"response_body\": \"\"\n}", + "body": "{\n \"url\": \"\",\n \"succeeded\": \"\",\n \"error\": \"\",\n \"status_code\": \"\",\n \"request_headers\": {\n \"key_0\": false,\n \"key_1\": false\n },\n \"request_body\": \"\",\n \"response_headers\": {\n \"key_0\": 6969,\n \"key_1\": 206.43895341080466\n },\n \"response_body\": \"\"\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "1660a2d8-562b-4682-b20a-3108014f7446", + "id": "8e5dc551-fd37-4623-bdb7-79594dfc7fec", "name": "Validation error", "originalRequest": { "url": { @@ -11421,7 +11445,7 @@ "description": "", "item": [ { - "id": "17830797-a3f5-49bb-8096-e175abfe4378", + "id": "f575c06e-d5fd-434a-b172-ee02bd515530", "name": "Get a single webhook notification", "request": { "name": "Get a single webhook notification", @@ -11473,7 +11497,7 @@ }, "response": [ { - "id": "75bf185e-8628-4871-95db-8d66eb702162", + "id": "92af142d-3db4-4189-8dc7-d47b28545d6b", "name": "200", "originalRequest": { "url": { @@ -11533,7 +11557,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.transport.empty_out\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container_updated_event\"\n }\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.feeder_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.vessel_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ]\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.transport.estimated.vessel_arrived\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n }\n }\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.transport.rail_departed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"shipment.estimated.arrival\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -11544,7 +11568,7 @@ } }, { - "id": "f041fd7d-d787-4ed9-a33e-31054a58d6c6", + "id": "00daaf4a-5a20-4975-ba0b-e2199238daa9", "name": "List webhook notifications", "request": { "name": "List webhook notifications", @@ -11602,7 +11626,7 @@ }, "response": [ { - "id": "4bfcc83f-9cdd-4dab-87ce-ba4aefcae0cd", + "id": "6c63ffdc-fad9-42ed-8c3b-74f5e9ba5173", "name": "OK", "originalRequest": { "url": { @@ -11668,7 +11692,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.transport.estimated.vessel_departed\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.pod_terminal_changed\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container_updated_event\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.created\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.pickup_lfd_rail.changed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ]\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.created\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container_updated_event\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.transport.rail_loaded\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"tracking_request.tracking_stopped\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"shipment.estimated.arrival\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -11679,7 +11703,7 @@ } }, { - "id": "08a2a6f5-a99b-459a-9973-be363d16ccc0", + "id": "dc749a59-51c7-42d2-95ac-1939c2adfa59", "name": "Get webhook notification payload examples", "request": { "name": "Get webhook notification payload examples", @@ -11703,7 +11727,7 @@ "type": "text/plain" }, "key": "event", - "value": "container.transport.transshipment_departed" + "value": "container.pod_terminal_changed" } ], "variable": [] @@ -11720,7 +11744,7 @@ }, "response": [ { - "id": "6bb3e3de-1c60-416d-a5cd-e6a457452326", + "id": "a7b27fbe-1cfa-4555-be26-1ec7222e3024", "name": "OK", "originalRequest": { "url": { @@ -11739,7 +11763,7 @@ "type": "text/plain" }, "key": "event", - "value": "container.transport.transshipment_departed" + "value": "container.pod_terminal_changed" } ], "variable": [] @@ -11769,7 +11793,7 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.transport.estimated.vessel_departed\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"tracking_request\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.pod_terminal_changed\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container_updated_event\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.created\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"container.pickup_lfd_rail.changed\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ]\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.created\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"container_updated_event\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook_notification\",\n \"attributes\": {\n \"event\": \"container.transport.rail_loaded\",\n \"delivery_status\": \"pending\",\n \"created_at\": \"\"\n },\n \"relationships\": {\n \"webhook\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"webhook\"\n }\n },\n \"reference_object\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n },\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"tracking_request.tracking_stopped\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n },\n {\n \"id\": \"\",\n \"type\": \"webhook\",\n \"attributes\": {\n \"url\": \"\",\n \"active\": true,\n \"events\": [\n \"shipment.estimated.arrival\"\n ],\n \"secret\": \"\",\n \"headers\": [\n {\n \"name\": \"\",\n \"value\": \"\"\n },\n {\n \"name\": \"\",\n \"value\": \"\"\n }\n ]\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -11786,7 +11810,7 @@ "description": "", "item": [ { - "id": "b46c0202-bc76-47ca-8b49-d8f430a42d4a", + "id": "4d0675ee-84da-4b02-9c03-2367d95d3189", "name": "Get a port using the locode or the id", "request": { "name": "Get a port using the locode or the id", @@ -11828,7 +11852,7 @@ }, "response": [ { - "id": "3b28a03d-c071-4139-89c4-0e1aad11088c", + "id": "3b080135-380b-450e-960e-7d7c2d3e184f", "name": "OK", "originalRequest": { "url": { @@ -11895,7 +11919,7 @@ "description": "", "item": [ { - "id": "5d1731a7-5ebb-4ab4-a4c4-0afdcb9a0e44", + "id": "7ccc4d2d-81a9-4879-8d9b-c39120c57006", "name": "Get a metro area using the un/locode or the id", "request": { "name": "Get a metro area using the un/locode or the id", @@ -11937,7 +11961,7 @@ }, "response": [ { - "id": "38c74d47-2b78-491a-a00f-4feed8fc96be", + "id": "e77143f7-7318-487e-92d7-848c807b4c8e", "name": "OK", "originalRequest": { "url": { @@ -12004,7 +12028,7 @@ "description": "", "item": [ { - "id": "0d8b3efc-9884-4735-a4ba-c7afb925d012", + "id": "22021753-25a0-4b71-bc5c-92067c0b88dc", "name": "Get a terminal using the id", "request": { "name": "Get a terminal using the id", @@ -12046,7 +12070,7 @@ }, "response": [ { - "id": "1a4e7bbb-a79d-41b3-8854-1932fa284755", + "id": "a62f9fea-8f6c-4a41-842e-2fe1112527d4", "name": "OK", "originalRequest": { "url": { @@ -12113,7 +12137,7 @@ "description": "", "item": [ { - "id": "2e75d9db-4e50-458f-9674-0d358fbf1d71", + "id": "5c744ac4-eb5c-47be-8e70-191f69c45fae", "name": "Get container map GeoJSON", "request": { "name": "Get container map GeoJSON", @@ -12156,7 +12180,7 @@ }, "response": [ { - "id": "c19b4f48-2f31-4077-87a9-80c542e05388", + "id": "f44ececf-1735-4662-93d6-b1769a5d031f", "name": "OK", "originalRequest": { "url": { @@ -12212,7 +12236,7 @@ "_postman_previewlanguage": "json" }, { - "id": "e14d97f3-214d-4e60-bc60-615d71cb555b", + "id": "64f657cd-425a-448a-be66-0d8b6a10d0a8", "name": "Forbidden - Routing data feature is not enabled for this account", "originalRequest": { "url": { @@ -12274,7 +12298,7 @@ } }, { - "id": "314c633c-3187-4b81-9419-448c7983bf86", + "id": "bfc31b9f-5181-49c9-9d15-96b7e4e08d7f", "name": "Get vessel future positions", "request": { "name": "Get vessel future positions", @@ -12336,7 +12360,7 @@ }, "response": [ { - "id": "bbbd92fe-9161-49b1-8a49-d67448008ac9", + "id": "10fd2427-ca55-4186-9090-b947450251a4", "name": "OK", "originalRequest": { "url": { @@ -12411,7 +12435,7 @@ "_postman_previewlanguage": "json" }, { - "id": "03525c30-6f40-4022-9918-21f4bdf6f174", + "id": "ebd286af-94de-4231-83b3-f566c6964173", "name": "Forbidden - Routing data feature is not enabled for this account", "originalRequest": { "url": { @@ -12492,7 +12516,7 @@ } }, { - "id": "b3711299-22b3-4755-8a16-701476905c70", + "id": "8ec5e44c-4b47-4194-b84f-7a4d5c65e53d", "name": "Get vessel future positions from coordinates", "request": { "name": "Get vessel future positions from coordinates", @@ -12572,7 +12596,7 @@ }, "response": [ { - "id": "3f76e537-5e82-4566-9818-1da3beaec979", + "id": "172e4a0c-f3ce-42ea-88c4-4b7a6dab4174", "name": "OK", "originalRequest": { "url": { @@ -12665,7 +12689,7 @@ "_postman_previewlanguage": "json" }, { - "id": "b588c16d-f25f-449a-9e01-2de0ba19a94b", + "id": "c75f96b4-50cb-45c4-a400-539671ce8a64", "name": "Forbidden - Routing data feature is not enabled for this account", "originalRequest": { "url": { @@ -12770,7 +12794,7 @@ "description": "", "item": [ { - "id": "814bad63-2fb0-4450-8c00-d8f2b45d8f52", + "id": "b1b66f04-2148-4b6f-86ed-3ef5243fa01c", "name": "List documents", "request": { "name": "List documents", @@ -12864,7 +12888,7 @@ }, "response": [ { - "id": "a7e53ee2-5d0d-4a1d-8e1d-be76f570c99b", + "id": "e6696806-faf2-452e-85bd-1b3b8892b370", "name": "OK", "originalRequest": { "url": { @@ -12966,12 +12990,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"document\",\n \"attributes\": {\n \"id\": \"\",\n \"name\": \"\",\n \"document_type\": \"\",\n \"document_type_manual\": \"\",\n \"classification_notes\": \"\",\n \"source\": \"upload\",\n \"file_name\": \"\",\n \"file_content_type\": \"\",\n \"file_size_bytes\": \"\",\n \"parsed\": {\n \"packetSegment\": {\n \"startPage\": \"\",\n \"endPage\": \"\"\n }\n },\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"account\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n },\n \"user\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"user\"\n }\n },\n \"email_submission\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"email_submission\"\n }\n },\n \"last_document_representation\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document_representation\"\n }\n },\n \"parent_document\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n },\n \"shipments\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n ]\n },\n \"cargos\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"container\"\n },\n {\n \"id\": \"\",\n \"type\": \"container\"\n }\n ]\n }\n },\n \"links\": {\n \"self\": \"\",\n \"download\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"document\",\n \"attributes\": {\n \"id\": \"\",\n \"name\": \"\",\n \"document_type\": \"\",\n \"document_type_manual\": \"\",\n \"classification_notes\": \"\",\n \"source\": \"email\",\n \"file_name\": \"\",\n \"file_content_type\": \"\",\n \"file_size_bytes\": \"\",\n \"parsed\": {\n \"packetSegment\": {\n \"startPage\": \"\",\n \"endPage\": \"\"\n }\n },\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"account\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n },\n \"user\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"user\"\n }\n },\n \"email_submission\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"email_submission\"\n }\n },\n \"last_document_representation\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document_representation\"\n }\n },\n \"parent_document\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n },\n \"shipments\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n ]\n },\n \"cargos\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"container\"\n },\n {\n \"id\": \"\",\n \"type\": \"container\"\n }\n ]\n }\n },\n \"links\": {\n \"self\": \"\",\n \"download\": \"\"\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"document\",\n \"attributes\": {\n \"id\": \"\",\n \"name\": \"\",\n \"document_type\": \"\",\n \"document_type_manual\": \"\",\n \"classification_notes\": \"\",\n \"source\": \"upload\",\n \"file_name\": \"\",\n \"file_content_type\": \"\",\n \"file_size_bytes\": \"\",\n \"parsed\": {\n \"packetSegment\": {\n \"startPage\": \"\",\n \"endPage\": \"\"\n }\n },\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"account\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n },\n \"user\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"user\"\n }\n },\n \"email_submission\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"email_submission\"\n }\n },\n \"last_document_representation\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document_representation\"\n }\n },\n \"parent_document\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n },\n \"shipments\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n ]\n },\n \"cargos\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"container\"\n },\n {\n \"id\": \"\",\n \"type\": \"container\"\n }\n ]\n }\n },\n \"links\": {\n \"self\": \"\",\n \"download\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"document\",\n \"attributes\": {\n \"id\": \"\",\n \"name\": \"\",\n \"document_type\": \"\",\n \"document_type_manual\": \"\",\n \"classification_notes\": \"\",\n \"source\": \"upload\",\n \"file_name\": \"\",\n \"file_content_type\": \"\",\n \"file_size_bytes\": \"\",\n \"parsed\": {\n \"packetSegment\": {\n \"startPage\": \"\",\n \"endPage\": \"\"\n }\n },\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"account\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"account\"\n }\n },\n \"user\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"user\"\n }\n },\n \"email_submission\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"email_submission\"\n }\n },\n \"last_document_representation\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document_representation\"\n }\n },\n \"parent_document\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"document\"\n }\n },\n \"shipments\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n },\n {\n \"id\": \"\",\n \"type\": \"shipment\"\n }\n ]\n },\n \"cargos\": {\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"container\"\n },\n {\n \"id\": \"\",\n \"type\": \"container\"\n }\n ]\n }\n },\n \"links\": {\n \"self\": \"\",\n \"download\": \"\"\n }\n }\n ],\n \"included\": [\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"account\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "e7d72364-cbd4-401a-a39a-c2e8315334ae", + "id": "7318979a-116b-4f8b-8d7d-f39852612fba", "name": "Bad Request", "originalRequest": { "url": { @@ -13073,12 +13097,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "59bd324c-9734-4d7b-8a8b-74607736df97", + "id": "41a1270b-ef7e-443a-a6fe-8f0c8de39c74", "name": "Unauthorized", "originalRequest": { "url": { @@ -13180,7 +13204,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -13191,7 +13215,7 @@ } }, { - "id": "08c8c243-cd99-4f85-b3d0-2ce56bb0464e", + "id": "992ec86f-3143-4563-a882-9adf1efd8622", "name": "Upload a document", "request": { "name": "Upload a document", @@ -13234,7 +13258,7 @@ }, "response": [ { - "id": "00156b89-fa02-40f2-9474-e91b64a0efc6", + "id": "b7528a2a-3abe-42a6-bdb6-4c16e1b027f1", "name": "Created", "originalRequest": { "url": { @@ -13290,7 +13314,7 @@ "_postman_previewlanguage": "json" }, { - "id": "0063e1b8-7769-4131-8d27-ffaf04123476", + "id": "0838f8dd-85bd-41b4-aef6-4f70337f6984", "name": "Duplicate document", "originalRequest": { "url": { @@ -13346,7 +13370,7 @@ "_postman_previewlanguage": "json" }, { - "id": "c26a6231-d793-4f8d-95f4-f45868938551", + "id": "80fd9311-9200-4bbf-8812-cb491fcf43d5", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -13397,7 +13421,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -13408,7 +13432,7 @@ } }, { - "id": "9d333b20-49fa-4059-bc0b-a7929ff73919", + "id": "235e86b2-3e3f-4ceb-84ca-239f0ea9f7ee", "name": "List document types", "request": { "name": "List document types", @@ -13439,7 +13463,7 @@ }, "response": [ { - "id": "165499cd-1c67-460a-9ec4-9c77153d86e8", + "id": "d807d118-fdff-4e1d-bb27-f166b5e09331", "name": "OK", "originalRequest": { "url": { @@ -13483,7 +13507,7 @@ "_postman_previewlanguage": "json" }, { - "id": "fd01ccec-afa5-476a-be78-e6b5f80df615", + "id": "422168ea-48c9-4103-a9c0-87931f2f5cbe", "name": "Unauthorized", "originalRequest": { "url": { @@ -13522,7 +13546,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -13533,7 +13557,7 @@ } }, { - "id": "bfc938d6-fc5a-475b-92c0-db61fd1fd9d9", + "id": "d1e9985d-ecd4-492c-8ec7-ee8cd3a7eaa7", "name": "Get a document", "request": { "name": "Get a document", @@ -13582,7 +13606,7 @@ }, "response": [ { - "id": "4fdad83a-b0c7-42b6-8d83-0868932d45c9", + "id": "a33cde67-f8b0-40dd-83b0-895ae4de657c", "name": "OK", "originalRequest": { "url": { @@ -13647,7 +13671,7 @@ "_postman_previewlanguage": "json" }, { - "id": "9ea52ce0-9288-4ab5-99b4-ddcfec8ea328", + "id": "680cfbb1-b765-445e-a787-9ea37c98ba0e", "name": "Bad Request", "originalRequest": { "url": { @@ -13707,12 +13731,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "3ccc9990-f1d1-48af-b1a4-3c71a6b0d8bc", + "id": "b19dceb0-4f4f-4002-adb5-ba4c64b0eddf", "name": "Not Found", "originalRequest": { "url": { @@ -13772,7 +13796,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -13783,7 +13807,7 @@ } }, { - "id": "a41cc583-6dbc-43f2-9030-6810127d0434", + "id": "281ea6a7-7753-43af-8950-c9c1d98947c1", "name": "Edit a document", "request": { "name": "Edit a document", @@ -13826,7 +13850,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"document\",\n \"attributes\": {\n \"document_type_manual\": \"\",\n \"extracted_data_manual\": {\n \"key_0\": 299\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"document\",\n \"attributes\": {\n \"document_type_manual\": \"\",\n \"extracted_data_manual\": {\n \"key_0\": true\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -13838,7 +13862,7 @@ }, "response": [ { - "id": "91fbf246-c3a4-4806-a639-cf079d706069", + "id": "f30fe006-ee9f-49d5-8f4e-2afeff552393", "name": "OK", "originalRequest": { "url": { @@ -13884,7 +13908,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"document\",\n \"attributes\": {\n \"document_type_manual\": \"\",\n \"extracted_data_manual\": {\n \"key_0\": 299\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"document\",\n \"attributes\": {\n \"document_type_manual\": \"\",\n \"extracted_data_manual\": {\n \"key_0\": true\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -13906,7 +13930,7 @@ "_postman_previewlanguage": "json" }, { - "id": "7a67221b-5fc2-4725-9093-2f8d7ee7d9d7", + "id": "c5394195-1886-42f7-a982-8827d890131b", "name": "Not Found", "originalRequest": { "url": { @@ -13952,7 +13976,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"document\",\n \"attributes\": {\n \"document_type_manual\": \"\",\n \"extracted_data_manual\": {\n \"key_0\": 299\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"document\",\n \"attributes\": {\n \"document_type_manual\": \"\",\n \"extracted_data_manual\": {\n \"key_0\": true\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -13969,7 +13993,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -13980,7 +14004,7 @@ } }, { - "id": "ee5ff795-e930-4407-a95d-154878415c44", + "id": "34c1c744-f6bd-4330-b269-fa9c363ef4f5", "name": "Delete a document", "request": { "name": "Delete a document", @@ -14022,7 +14046,7 @@ }, "response": [ { - "id": "334b3e42-af0c-4f9d-a6f6-7a202acb8598", + "id": "df6d9600-02fa-43db-a8bb-d052b74770ce", "name": "No Content", "originalRequest": { "url": { @@ -14067,7 +14091,7 @@ "_postman_previewlanguage": "text" }, { - "id": "d55eb4fc-5584-4234-b3fb-50b35025c7d3", + "id": "e3792c59-592a-4e63-ac33-e89abb2aa7d0", "name": "Not Found", "originalRequest": { "url": { @@ -14117,7 +14141,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -14128,7 +14152,7 @@ } }, { - "id": "ff3c72be-e8c6-459f-90a0-66264ef5df9a", + "id": "7639b072-791d-4a06-847e-515542e07334", "name": "Get a document download URL", "request": { "name": "Get a document download URL", @@ -14171,7 +14195,7 @@ }, "response": [ { - "id": "cca62285-010e-4307-87d8-e7c0b2a0b329", + "id": "e1a151e9-bebe-4fa4-a8b6-762335821c48", "name": "OK", "originalRequest": { "url": { @@ -14227,7 +14251,7 @@ "_postman_previewlanguage": "json" }, { - "id": "25d33b46-127f-400f-b7c4-9bc3b881f9b8", + "id": "713f6889-4fb9-4e14-acd2-3ea7889904e7", "name": "Not Found", "originalRequest": { "url": { @@ -14278,12 +14302,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "f6247214-c523-466f-aa4e-12d8fcff9bb8", + "id": "0e14fa09-c3c7-47d1-92f3-9817afd25be6", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -14334,7 +14358,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -14345,7 +14369,7 @@ } }, { - "id": "c52750e7-235c-4fe2-8c9c-0dfecba2519b", + "id": "ffc15693-ecab-4aca-ad95-b7d37e7b3046", "name": "Re-extract a document", "request": { "name": "Re-extract a document", @@ -14388,7 +14412,7 @@ }, "response": [ { - "id": "4724804f-092d-4853-86ad-99b340f21dc8", + "id": "80cbe7a2-0ea1-4dad-bd67-823d571f2835", "name": "Accepted", "originalRequest": { "url": { @@ -14444,7 +14468,7 @@ "_postman_previewlanguage": "json" }, { - "id": "edfc269a-257f-47a9-a0ea-379349e3baa1", + "id": "3c5a026d-793b-4c91-8fc6-be8d7a92be33", "name": "Not Found", "originalRequest": { "url": { @@ -14495,7 +14519,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -14506,7 +14530,7 @@ } }, { - "id": "f7ac1a6b-7999-4b21-ba59-468f9009de65", + "id": "79301238-babb-4c4b-a9fa-f06b02ad9d71", "name": "Re-classify a document", "request": { "name": "Re-classify a document", @@ -14549,7 +14573,7 @@ }, "response": [ { - "id": "a27a7b3a-93cc-49d4-8b46-e710948d629b", + "id": "5e263be5-172d-44a3-82fd-d360815493c7", "name": "Accepted", "originalRequest": { "url": { @@ -14605,7 +14629,7 @@ "_postman_previewlanguage": "json" }, { - "id": "8d44e76b-7a4d-43ff-971a-3715e699c900", + "id": "f6c1282f-d676-4c84-9891-5359e4bb7e1c", "name": "Not Found", "originalRequest": { "url": { @@ -14656,7 +14680,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -14667,7 +14691,7 @@ } }, { - "id": "121a7194-421d-4929-8f5a-4b637589b474", + "id": "f929ce43-9323-4e18-9f42-3ce1472390b2", "name": "Re-link a document", "request": { "name": "Re-link a document", @@ -14710,7 +14734,7 @@ }, "response": [ { - "id": "cb0fa49b-e1fb-4b1e-b330-d8c7138904aa", + "id": "8fb66917-725d-4dae-bade-dc289acd2cdc", "name": "Accepted", "originalRequest": { "url": { @@ -14766,7 +14790,7 @@ "_postman_previewlanguage": "json" }, { - "id": "1e133611-bf77-482d-bb03-4f7f7e489789", + "id": "f1019069-ea57-4178-b18a-84bfbeb1274a", "name": "Not Found", "originalRequest": { "url": { @@ -14817,7 +14841,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -14828,7 +14852,7 @@ } }, { - "id": "d993dd14-82bd-4f13-9866-447e767b3934", + "id": "0a68a913-b917-472f-aae9-dd7bc8c9cd8d", "name": "Rotate a document", "request": { "name": "Rotate a document", @@ -14884,7 +14908,7 @@ }, "response": [ { - "id": "af00e440-7a56-47a2-97d2-9c13584c08c6", + "id": "de985089-1b13-4446-965d-f6ddbdecdc5d", "name": "Accepted", "originalRequest": { "url": { @@ -14953,7 +14977,7 @@ "_postman_previewlanguage": "json" }, { - "id": "63d9855e-ff73-430e-ae6f-fc97992c9d04", + "id": "3c7049ba-500a-427c-9972-a495ce9c64ba", "name": "Not Found", "originalRequest": { "url": { @@ -15017,12 +15041,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "3f043691-51d1-4dc9-976a-40cfc8f74669", + "id": "10668b4a-adcd-453d-85e3-b4c5821f252e", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -15086,7 +15110,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -15103,7 +15127,7 @@ "description": "", "item": [ { - "id": "216580e5-b662-46e3-b816-703a9dbc838e", + "id": "df9e206c-7529-4715-85fe-ec4899fb564e", "name": "List email submissions", "request": { "name": "List email submissions", @@ -15161,7 +15185,7 @@ }, "response": [ { - "id": "991214e4-f6d0-4562-aacf-f09e353b8d9c", + "id": "b5756693-17e7-45dc-a080-20fe6bc0710c", "name": "OK", "originalRequest": { "url": { @@ -15232,7 +15256,7 @@ "_postman_previewlanguage": "json" }, { - "id": "056ef85a-ba2f-4089-8e35-c232f0832d98", + "id": "3f631313-7ffa-4410-aac3-bb9be44f3259", "name": "Bad Request", "originalRequest": { "url": { @@ -15298,12 +15322,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "d0a93ee6-7619-4dfc-b077-eb5224aec3ed", + "id": "d1dd077c-2ac4-4326-93fb-26d633189ec1", "name": "Unauthorized", "originalRequest": { "url": { @@ -15369,7 +15393,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -15380,7 +15404,7 @@ } }, { - "id": "36037719-14c0-4f80-8777-2a48ec8b72a6", + "id": "7d602a89-c8b5-428f-b275-414b91c42592", "name": "Get an email submission", "request": { "name": "Get an email submission", @@ -15429,7 +15453,7 @@ }, "response": [ { - "id": "b7df6d22-1009-4944-b605-5b71aa0e8bb5", + "id": "2ca9b188-e199-447b-8250-2abff98ee3e8", "name": "OK", "originalRequest": { "url": { @@ -15494,7 +15518,7 @@ "_postman_previewlanguage": "json" }, { - "id": "24c332a5-5672-460e-95a7-334734c0b774", + "id": "4185e3a0-6be0-47b5-b778-72d96a749807", "name": "Bad Request", "originalRequest": { "url": { @@ -15554,12 +15578,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "4ebe24d5-f257-46bf-b402-93588939a034", + "id": "9bfe3a86-9dd0-4cf3-b2aa-6da600b112d0", "name": "Not Found", "originalRequest": { "url": { @@ -15619,7 +15643,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -15636,7 +15660,7 @@ "description": "", "item": [ { - "id": "ece8be8f-b7de-4780-869e-701307ec8675", + "id": "432de4de-1186-4c32-97da-77f2eec1066b", "name": "Get a document schema", "request": { "name": "Get a document schema", @@ -15675,7 +15699,7 @@ }, "response": [ { - "id": "afbe7dac-778d-4dd1-b95d-cc8a2c68d55f", + "id": "ca942366-e3ce-40d9-9f40-4e3bed54b63d", "name": "OK", "originalRequest": { "url": { @@ -15725,12 +15749,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"document_schema\",\n \"attributes\": {\n \"document_type\": \"\",\n \"label\": \"\",\n \"schema_version\": \"\",\n \"full_version\": \"\",\n \"current\": \"\",\n \"draft\": \"\",\n \"active_at\": \"\",\n \"schema_format\": \"json_schema\",\n \"description\": \"\",\n \"schema_payload\": {\n \"key_0\": \"string\",\n \"key_1\": \"string\"\n },\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"document_schema\",\n \"attributes\": {\n \"document_type\": \"\",\n \"label\": \"\",\n \"schema_version\": \"\",\n \"full_version\": \"\",\n \"current\": \"\",\n \"draft\": \"\",\n \"active_at\": \"\",\n \"schema_format\": \"json_schema\",\n \"description\": \"\",\n \"schema_payload\": {\n \"key_0\": 4629\n },\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"links\": {\n \"self\": \"\"\n }\n },\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "0d20b3bf-c368-48ac-b08c-94c1cd3da6ba", + "id": "00cc4ae5-702f-4000-9cfe-56ba1158d5a4", "name": "Unauthorized", "originalRequest": { "url": { @@ -15780,12 +15804,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "70c67290-4885-4caa-b507-fab02a3d91bc", + "id": "feb5bf21-2aa7-4640-9067-65633855551a", "name": "Not Found", "originalRequest": { "url": { @@ -15835,7 +15859,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -15852,7 +15876,7 @@ "description": "", "item": [ { - "id": "803c83db-a50a-45a3-a324-7bec553ca3be", + "id": "52fd733b-4ffd-4241-9076-c6317f64b424", "name": "Search shipments, containers, and tracking requests", "request": { "name": "Search shipments, containers, and tracking requests", @@ -15892,7 +15916,7 @@ }, "response": [ { - "id": "2ab6b107-6259-4d7a-9ef3-d2927218c82e", + "id": "a291e5bc-e44e-4b1b-9119-a56cb0a30ab1", "name": "Successful search results", "originalRequest": { "url": { @@ -15940,12 +15964,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"cargo\",\n \"attributes\": {\n \"entity_type\": \"\",\n \"number\": \"\",\n \"shipment_id\": \"\",\n \"scac\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_name\": \"\",\n \"containers_count\": \"\",\n \"tracking_stopped\": \"\",\n \"tracking_stopped_reason\": \"\",\n \"status\": \"\",\n \"failed_reason\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"updated_at\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"cargo\",\n \"attributes\": {\n \"entity_type\": \"\",\n \"number\": \"\",\n \"shipment_id\": \"\",\n \"scac\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_name\": \"\",\n \"containers_count\": \"\",\n \"tracking_stopped\": \"\",\n \"tracking_stopped_reason\": \"\",\n \"status\": \"\",\n \"failed_reason\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"updated_at\": \"\"\n }\n }\n ]\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"entity_type\": \"\",\n \"number\": \"\",\n \"shipment_id\": \"\",\n \"scac\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_name\": \"\",\n \"containers_count\": \"\",\n \"tracking_stopped\": \"\",\n \"tracking_stopped_reason\": \"\",\n \"status\": \"\",\n \"failed_reason\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"updated_at\": \"\"\n }\n },\n {\n \"id\": \"\",\n \"type\": \"tracking_request\",\n \"attributes\": {\n \"entity_type\": \"\",\n \"number\": \"\",\n \"shipment_id\": \"\",\n \"scac\": \"\",\n \"port_of_lading_name\": \"\",\n \"port_of_discharge_name\": \"\",\n \"containers_count\": \"\",\n \"tracking_stopped\": \"\",\n \"tracking_stopped_reason\": \"\",\n \"status\": \"\",\n \"failed_reason\": \"\",\n \"ref_numbers\": [\n \"\",\n \"\"\n ],\n \"created_at\": \"\",\n \"updated_at\": \"\"\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "42e6a8c6-238d-4152-b771-3154af545168", + "id": "4ba51129-e1dc-460f-9f03-197dc67870f7", "name": "Bad request — missing required `query` parameter", "originalRequest": { "url": { @@ -15998,7 +16022,7 @@ "_postman_previewlanguage": "json" }, { - "id": "e17f8092-3f38-4803-8a1b-337afb39c6ee", + "id": "6ef597b3-e689-4926-92f9-9fadbe1652e9", "name": "Unauthorized — missing or invalid API token", "originalRequest": { "url": { @@ -16046,7 +16070,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -16063,7 +16087,7 @@ "description": "", "item": [ { - "id": "600b5a23-0c1b-4898-b7b1-1269468ac49d", + "id": "3a7a97e2-f86f-48ff-9ec4-28a52700e9d5", "name": "list-parties", "request": { "name": "list-parties", @@ -16112,7 +16136,7 @@ }, "response": [ { - "id": "0ed13843-502d-4251-a600-7c1f4d2636e2", + "id": "fd8c4d37-d5ed-4f93-ac9c-d1a84217c66e", "name": "OK", "originalRequest": { "url": { @@ -16180,7 +16204,7 @@ } }, { - "id": "d7e674e4-16e8-4f38-b316-fc4a1686430f", + "id": "df6b8d3f-4b7b-473f-942c-7038f1316324", "name": "post-party", "request": { "name": "post-party", @@ -16211,7 +16235,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16223,7 +16247,7 @@ }, "response": [ { - "id": "90d74be0-c2da-46bb-bcb6-9ed31e235927", + "id": "e5c2a4d0-831f-4ab9-838c-352e3bbb5589", "name": "Party Created", "originalRequest": { "url": { @@ -16257,7 +16281,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16279,7 +16303,7 @@ "_postman_previewlanguage": "json" }, { - "id": "3fafb86e-154c-48c9-8cff-df46e57ebfe2", + "id": "ee89199c-87fc-46a9-b297-024089f22f11", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -16313,7 +16337,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16330,7 +16354,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -16341,7 +16365,7 @@ } }, { - "id": "07b1d57d-df53-4ba5-ad93-9d49e69b6e9a", + "id": "fe453c5c-4a75-4681-b76e-d21e8a9ec632", "name": "List shipment party roles", "request": { "name": "List shipment party roles", @@ -16384,7 +16408,7 @@ }, "response": [ { - "id": "410e8171-b71a-489d-888e-82aa4eff9779", + "id": "a87b14a2-2dc7-48b0-b780-101a036cfb04", "name": "OK", "originalRequest": { "url": { @@ -16435,12 +16459,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\",\n \"roleable_type\": \"Cargo\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"customs_broker\",\n \"roleable_type\": \"Shipment\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n ],\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\",\n \"roleable_type\": \"Cargo\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\",\n \"roleable_type\": \"Cargo\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n ],\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "91d6e12e-97d5-4d66-b6ca-747530645eee", + "id": "fcb4f73b-4458-4f40-8afe-bd01169822cd", "name": "Unauthorized. Also returned when the record belongs to another account.", "originalRequest": { "url": { @@ -16491,12 +16515,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "fe0ddcee-4cfe-46a4-98e4-81734c22ce2a", + "id": "8a16c331-cf8b-4819-b743-562654a4a657", "name": "Not Found", "originalRequest": { "url": { @@ -16548,7 +16572,7 @@ } }, { - "id": "00b707fe-2ea0-4960-8a0d-fb0fa7732e23", + "id": "c473ee1d-1830-4968-ac0d-d740c81002fd", "name": "Assign a shipment party role", "request": { "name": "Assign a shipment party role", @@ -16592,7 +16616,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16604,7 +16628,7 @@ }, "response": [ { - "id": "0be90e76-eb6f-4511-86fa-f7f9c1348925", + "id": "9510f19d-f8c8-47a4-8c3b-4901ca34072d", "name": "Created", "originalRequest": { "url": { @@ -16651,7 +16675,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16668,12 +16692,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"notify_party\",\n \"roleable_type\": \"Shipment\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\",\n \"roleable_type\": \"Shipment\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "4c6bff7a-f8ef-4a0b-9b55-88dca45174d9", + "id": "747bfcad-76fb-4299-9e8f-295564d82920", "name": "Unauthorized. Also returned when the party or the record belongs to another account.", "originalRequest": { "url": { @@ -16720,7 +16744,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16737,12 +16761,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "56634d58-8723-422a-8877-89da62e2eede", + "id": "74173d34-4fed-4074-a9a2-7e422bec657c", "name": "Not Found", "originalRequest": { "url": { @@ -16785,7 +16809,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16801,7 +16825,7 @@ "_postman_previewlanguage": "text" }, { - "id": "4920423e-af62-4e49-863c-d7137ae14875", + "id": "6c09b8e9-45ed-4e0f-a689-46b454287c0e", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -16848,7 +16872,7 @@ "method": "POST", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -16865,7 +16889,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -16876,7 +16900,7 @@ } }, { - "id": "0510bef5-14e3-4e43-ac74-55feb9600162", + "id": "e8a54e13-9428-4406-bcc9-1bb4a5103767", "name": "Remove a shipment party role", "request": { "name": "Remove a shipment party role", @@ -16930,7 +16954,7 @@ }, "response": [ { - "id": "37db6c9f-ab73-4f9f-8e7e-4e01c21efc27", + "id": "71c81eb4-40e5-4c52-953e-0f187f5b4d9a", "name": "No Content", "originalRequest": { "url": { @@ -16987,7 +17011,7 @@ "_postman_previewlanguage": "text" }, { - "id": "af4c6f63-a865-452e-98a2-80f9ef7bd879", + "id": "d921429e-5e49-4020-ae8d-d2c12c1d1fb2", "name": "Unauthorized. Also returned when the record belongs to another account.", "originalRequest": { "url": { @@ -17049,12 +17073,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "491c9c09-601f-492a-aa31-62c2d37946f0", + "id": "2285b7c5-9fc6-4eb8-af90-d0ec0573b24c", "name": "Not Found", "originalRequest": { "url": { @@ -17117,7 +17141,7 @@ } }, { - "id": "2860be91-47a1-408f-b1fc-f684614ff394", + "id": "5808869d-5ba4-40f0-ae9c-0a86e9d10c5c", "name": "List container party roles", "request": { "name": "List container party roles", @@ -17160,7 +17184,7 @@ }, "response": [ { - "id": "01306aa2-a4ca-4402-b2b0-0f9b0ad30868", + "id": "700134ae-b874-4e7b-b8c4-60d60553a56b", "name": "OK", "originalRequest": { "url": { @@ -17211,12 +17235,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\",\n \"roleable_type\": \"Cargo\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"customs_broker\",\n \"roleable_type\": \"Shipment\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n ],\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", + "body": "{\n \"data\": [\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\",\n \"roleable_type\": \"Cargo\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"shipper\",\n \"roleable_type\": \"Cargo\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n }\n ],\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"last\": \"\",\n \"next\": \"\",\n \"prev\": \"\",\n \"first\": \"\",\n \"self\": \"\"\n },\n \"meta\": {\n \"size\": \"\",\n \"total\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "ceba6355-137c-40b5-955b-83d26ef5ca1e", + "id": "73927759-94f5-4917-b4a1-60ed4e853736", "name": "Unauthorized. Also returned when the record belongs to another account.", "originalRequest": { "url": { @@ -17267,12 +17291,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "d1480069-5fd8-4f63-a8ff-8d65fff6e20f", + "id": "b0c1529e-4239-4cbb-8c0f-e2eac4b12b95", "name": "Not Found", "originalRequest": { "url": { @@ -17324,7 +17348,7 @@ } }, { - "id": "f1956c72-8dbe-4a85-90ab-2a6f236e68f0", + "id": "fbf2349b-8bba-4487-977d-c12fdce6cd00", "name": "Assign a container party role", "request": { "name": "Assign a container party role", @@ -17380,7 +17404,7 @@ }, "response": [ { - "id": "af63697b-d772-43ca-8202-8f0861cb0b7a", + "id": "cfa098cb-173f-4a81-8e7e-0902825f2b73", "name": "Created", "originalRequest": { "url": { @@ -17444,12 +17468,12 @@ "value": "application/json" } ], - "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"notify_party\",\n \"roleable_type\": \"Shipment\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"self\": \"\"\n }\n}", + "body": "{\n \"data\": {\n \"id\": \"\",\n \"type\": \"party_role\",\n \"attributes\": {\n \"role\": \"pickup_dray_carrier\",\n \"roleable_type\": \"Shipment\",\n \"roleable_id\": \"\",\n \"created_at\": \"\",\n \"updated_at\": \"\"\n },\n \"relationships\": {\n \"party\": {\n \"data\": {\n \"id\": \"\",\n \"type\": \"party\"\n }\n }\n }\n },\n \"included\": [\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n },\n {\n \"attributes\": {\n \"company_name\": \"\"\n },\n \"id\": \"\",\n \"type\": \"party\"\n }\n ],\n \"links\": {\n \"self\": \"\"\n }\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "2807b13d-934a-493c-9ce3-0c5e8e15f0d4", + "id": "3ba517e8-f178-48a0-a843-18d415653e35", "name": "Unauthorized. Also returned when the party or the record belongs to another account.", "originalRequest": { "url": { @@ -17513,12 +17537,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "62b47a95-1b32-441a-acab-1a6a5f711419", + "id": "17f01930-df98-402a-a43e-546c13f3dde2", "name": "Not Found", "originalRequest": { "url": { @@ -17577,7 +17601,7 @@ "_postman_previewlanguage": "text" }, { - "id": "8b043c18-e263-4624-8af4-ec17eddad173", + "id": "0f80a7db-f156-483d-97a4-6efdcf8755c0", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -17641,7 +17665,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -17652,7 +17676,7 @@ } }, { - "id": "cf49d616-1514-42f4-bf45-4859cbf3d524", + "id": "54fb9034-cd76-41e4-86ad-42e87fc6c330", "name": "Remove a container party role", "request": { "name": "Remove a container party role", @@ -17706,7 +17730,7 @@ }, "response": [ { - "id": "5a07c614-0e45-467b-889e-816d3351e1e9", + "id": "ea5b2ca1-ec55-4d6b-a61b-e22faff73827", "name": "No Content", "originalRequest": { "url": { @@ -17763,7 +17787,7 @@ "_postman_previewlanguage": "text" }, { - "id": "bb0953d4-366e-4a55-9f9e-38607102a2ed", + "id": "78c02956-99b2-4f8d-ba99-5bd7504bd881", "name": "Unauthorized. Also returned when the record belongs to another account.", "originalRequest": { "url": { @@ -17825,12 +17849,12 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" }, { - "id": "6b38c4a0-38fe-4779-94dc-a1cbd83cede9", + "id": "431760eb-470c-4c6e-b445-bf5b094c14fe", "name": "Not Found", "originalRequest": { "url": { @@ -17893,7 +17917,7 @@ } }, { - "id": "cc9592a4-71c6-43c3-88a8-0414dd0300ca", + "id": "697ba2bc-c395-4964-8aa5-e036d78f5746", "name": "get-parties-id", "request": { "name": "get-parties-id", @@ -17935,7 +17959,7 @@ }, "response": [ { - "id": "002e0890-e85c-4672-83f9-fdb1244d9c3c", + "id": "1ef33c81-012b-46fb-8df3-ab443422e797", "name": "OK", "originalRequest": { "url": { @@ -17996,7 +18020,7 @@ } }, { - "id": "79d3834a-9bc0-4450-8862-b54aaadf2227", + "id": "d34c0c9a-9658-4ec2-af79-7d18c0c2c01b", "name": "edit-party", "request": { "name": "edit-party", @@ -18039,7 +18063,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -18051,7 +18075,7 @@ }, "response": [ { - "id": "ed865cc3-2b40-4fb2-ab3e-6faebe283c3d", + "id": "dcd40fba-d515-434a-9e6e-901b7cd9fffb", "name": "OK", "originalRequest": { "url": { @@ -18097,7 +18121,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -18119,7 +18143,7 @@ "_postman_previewlanguage": "json" }, { - "id": "cd1272eb-33c3-4f72-904f-061ae0b2276d", + "id": "463bfdf8-0185-4aff-b085-06dfd7c5413e", "name": "Unprocessable Entity", "originalRequest": { "url": { @@ -18165,7 +18189,7 @@ "method": "PATCH", "body": { "mode": "raw", - "raw": "{\n \"data\": {\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", + "raw": "{\n \"data\": {\n \"type\": \"party\",\n \"attributes\": {\n \"company_name\": \"\"\n }\n }\n}", "options": { "raw": { "headerFamily": "json", @@ -18182,7 +18206,7 @@ "value": "application/json" } ], - "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 1166\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": false,\n \"key_2\": \"string\",\n \"key_3\": false\n }\n }\n ]\n}", + "body": "{\n \"errors\": [\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": 2042\n }\n },\n {\n \"title\": \"\",\n \"detail\": \"\",\n \"source\": {\n \"pointer\": \"\",\n \"parameter\": \"\"\n },\n \"code\": \"\",\n \"status\": \"\",\n \"meta\": {\n \"key_0\": \"string\",\n \"key_1\": 1533\n }\n }\n ]\n}", "cookie": [], "_postman_previewlanguage": "json" } @@ -18199,7 +18223,7 @@ "description": "", "item": [ { - "id": "792ebef7-2b97-48ea-b906-6b368bfcab2c", + "id": "3da529b7-8d04-45b2-a441-59af8d577722", "name": "Shipping Lines", "request": { "name": "Shipping Lines", @@ -18229,7 +18253,7 @@ }, "response": [ { - "id": "da42b281-f83b-4d86-8d27-58814485b537", + "id": "ae790647-8d7f-473e-822a-2ce2bca5a62b", "name": "OK", "originalRequest": { "url": { @@ -18278,7 +18302,7 @@ } }, { - "id": "1f946561-7921-469a-8900-1a5f1193a603", + "id": "436e2bee-ad4a-4626-b14f-125bd032e48d", "name": "Get a single shipping line", "request": { "name": "Get a single shipping line", @@ -18320,7 +18344,7 @@ }, "response": [ { - "id": "abdefcad-f777-44be-b3ea-01aba432a1ac", + "id": "3f5e5e4f-61bb-44bb-820e-0b5f3e88fe8c", "name": "OK", "originalRequest": { "url": { @@ -18387,7 +18411,7 @@ "description": "", "item": [ { - "id": "c1fde412-f00f-43c6-b24d-d6995c360b06", + "id": "eee466dc-7425-45ff-9082-0d739d0e4f5b", "name": "Get a vessel using the id", "request": { "name": "Get a vessel using the id", @@ -18448,7 +18472,7 @@ }, "response": [ { - "id": "64b103e4-6264-4346-8288-3d77dec0aecf", + "id": "77c7da3f-7a76-4ae9-8cf3-8250fc2eae65", "name": "OK", "originalRequest": { "url": { @@ -18522,7 +18546,7 @@ "_postman_previewlanguage": "json" }, { - "id": "a8e66528-26c5-486d-ba78-f2b1986dae92", + "id": "b3d9cab8-17e8-4d5e-b7ec-116e562162a0", "name": "Forbidden - Feature not enabled", "originalRequest": { "url": { @@ -18602,7 +18626,7 @@ } }, { - "id": "c984f85e-541b-42d3-839c-2ee67d6da390", + "id": "cb896fb1-8eaf-4818-b103-e4ec253e1e80", "name": "Get a vessel using the imo", "request": { "name": "Get a vessel using the imo", @@ -18663,7 +18687,7 @@ }, "response": [ { - "id": "51979a45-c417-4100-8b54-f90c4bdb5f6d", + "id": "7b7232a7-af48-4f6e-bf9f-77581f1a5380", "name": "OK", "originalRequest": { "url": { @@ -18737,7 +18761,7 @@ "_postman_previewlanguage": "json" }, { - "id": "584cf6af-ed3c-42bd-a0ac-efdadc8f0b43", + "id": "ad5b4368-ab34-4100-a947-ef7ccc915c6c", "name": "Forbidden - Feature not enabled", "originalRequest": { "url": { @@ -18817,7 +18841,7 @@ } }, { - "id": "7d04769a-b4ec-411b-8d5d-992e11cc167b", + "id": "6f894c69-9d19-4ca7-842a-6009ca3b2139", "name": "Get vessel future positions", "request": { "name": "Get vessel future positions", @@ -18879,7 +18903,7 @@ }, "response": [ { - "id": "48501678-2b22-4ef9-b8be-15a66084e164", + "id": "7231e73e-c8f0-42b2-9b98-4b99a2fc7c5e", "name": "OK", "originalRequest": { "url": { @@ -18954,7 +18978,7 @@ "_postman_previewlanguage": "json" }, { - "id": "d304c649-6def-40ff-af40-d3cf99142a51", + "id": "32806727-d085-4f9f-bd8c-b2cf7a09963b", "name": "Forbidden - Routing data feature is not enabled for this account", "originalRequest": { "url": { @@ -19035,7 +19059,7 @@ } }, { - "id": "17841ed1-a82d-4892-96da-097ce0fc8330", + "id": "10ce7408-d6b0-45a6-a9b4-dd1260c6fad5", "name": "Get vessel future positions from coordinates", "request": { "name": "Get vessel future positions from coordinates", @@ -19115,7 +19139,7 @@ }, "response": [ { - "id": "f357c776-e295-443f-b349-fa0d1b2ff1fe", + "id": "7eeb7dbf-f20f-4877-bcc9-a81fc9b324fa", "name": "OK", "originalRequest": { "url": { @@ -19208,7 +19232,7 @@ "_postman_previewlanguage": "json" }, { - "id": "e99494d5-e39b-49f8-8bc0-79645617e1d2", + "id": "b3420712-7a90-452e-aa79-c710e00477bb", "name": "Forbidden - Routing data feature is not enabled for this account", "originalRequest": { "url": { @@ -19337,7 +19361,7 @@ } ], "info": { - "_postman_id": "96191908-1b34-4cc6-933b-f6945fdaa025", + "_postman_id": "ec399f12-c442-4e7f-9e87-70bdbe253c53", "name": "Terminal49 API Reference", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "description": {