Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,31 @@ jobs:
echo "Vercel preview changed while the smoke test was running"
exit 1
fi

migrate:
runs-on: ${{ (startsWith(vars.CI_RUNNER, 'blacksmith-') && vars.CI_RUNNER) || 'blacksmith-4vcpu-ubuntu-2404' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v6
with:
node-version: 24
cache: 'npm'
cache-dependency-path: package-lock.json
- name: Install workspace dependencies
run: npm ci
- name: Build compatibility package
run: npm run build --workspace @terminal49/searates-compat
- name: Build migrate application
run: npm run build --workspace @terminal49/migrate-app
- name: Type-check compatibility package and migrate application
run: |
npm run type-check --workspace @terminal49/searates-compat
npm run type-check --workspace @terminal49/migrate-app
- name: Test compatibility package and migrate configuration
run: |
npm run test --workspace @terminal49/searates-compat
npm run test --workspace @terminal49/migrate-app
- name: Check compatibility package and migrate handlers
run: |
npm run lint --workspace @terminal49/searates-compat
npm run lint --workspace @terminal49/migrate-app
12 changes: 12 additions & 0 deletions apps/migrate/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Pass-through mode is the default: leave service-token variables unset and
# send a Terminal49 API key in the SeaRates-compatible `api_key` query.
T49_API_BASE_URL=https://api.terminal49.com/v2

# Service-token mode: clients send T49_SEARATES_CLIENT_SECRET as `api_key`.
# T49_SEARATES_API_TOKEN=YOUR_T49_API_KEY
# T49_SEARATES_CLIENT_SECRET=YOUR_GATEWAY_KEY

# Optional bounded polling settings.
# T49_SEARATES_POLL_TIMEOUT_MS=4000
# T49_SEARATES_POLL_INTERVAL_MS=500
# T49_SEARATES_REQUEST_TIMEOUT_MS=10000
3 changes: 3 additions & 0 deletions apps/migrate/api/container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createContainerHandler } from '@terminal49/searates-compat';

export default createContainerHandler();
3 changes: 3 additions & 0 deletions apps/migrate/api/info/sealines.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createShippingLinesHandler } from '@terminal49/searates-compat';

export default createShippingLinesHandler();
3 changes: 3 additions & 0 deletions apps/migrate/api/reference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createReferenceHandler } from '@terminal49/searates-compat';

export default createReferenceHandler();
3 changes: 3 additions & 0 deletions apps/migrate/api/tracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createTrackingHandler } from '@terminal49/searates-compat';

export default createTrackingHandler();
25 changes: 25 additions & 0 deletions apps/migrate/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@terminal49/migrate-app",
"version": "0.1.0",
"private": true,
"description": "Vercel application for vendor compatibility APIs",
"type": "module",
"scripts": {
"build": "tsc --noEmit",
"test": "node -e \"JSON.parse(require('fs').readFileSync('vercel.json', 'utf8'))\"",
"lint": "vp lint api && vp fmt --check api",
"format": "vp fmt --write api",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@terminal49/searates-compat": "0.1.0"
},
"devDependencies": {
"@types/node": "^24.10.13",
"typescript": "^5.6.3",
"vite-plus": "0.2.9"
},
"engines": {
"node": "24.x"
}
}
17 changes: 17 additions & 0 deletions apps/migrate/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"lib": ["ES2022"],
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"noEmit": true,
"types": ["node"]
},
"include": ["api/**/*"],
"exclude": ["node_modules"]
}
38 changes: 38 additions & 0 deletions apps/migrate/vercel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"version": 2,
"installCommand": "cd ../.. && npm ci",
"buildCommand": "cd ../.. && npm run build --workspace @terminal49/searates-compat && npm run build --workspace @terminal49/migrate-app",
"functions": {
"api/tracking.ts": {
"maxDuration": 30
},
"api/container.ts": {
"maxDuration": 30
},
"api/reference.ts": {
"maxDuration": 30
},
"api/info/sealines.ts": {
"maxDuration": 15
}
},
"rewrites": [
{
"source": "/searates-api/tracking",
"destination": "/api/tracking"
},
{
"source": "/searates-api/container",
"destination": "/api/container"
},
{
"source": "/searates-api/reference",
"destination": "/api/reference"
},
{
"source": "/searates-api/info/sealines",
"destination": "/api/info/sealines"
}
]
}
40 changes: 39 additions & 1 deletion docs/migrate/searates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,45 @@ description: "Map SeaRates tracking API fields, parameters, and errors to their

If you have the SeaRates tracking API in production, this page maps it onto Terminal49 field by field, so you can cut over without reverse-engineering our schema.

There is no compatibility shim. You will change your request code and your response parsing. For most integrations that is an afternoon.
You can migrate in either of two ways:

- **Keep the SeaRates wire format:** point your existing client at the Terminal49 SeaRates compatibility gateway.
- **Adopt the native Terminal49 API:** use the field mappings and webhook workflow in this guide.

## Keep your existing SeaRates client

The compatibility gateway accepts the SeaRates `api_key`, `number`, `sealine`, and `type` query parameters, then returns the SeaRates tracking envelope backed by Terminal49 data.

Set your client's base URL to:

```text
https://migrate.terminal49.com/searates-api
```

The gateway provides:

- `GET /tracking`
- `GET /container` for the deprecated singular-container response
- `GET /reference` for the deprecated Bill of Lading (BOL) and booking response
- `GET /info/sealines`

For example:

```bash
curl "https://migrate.terminal49.com/searates-api/tracking\
?api_key=YOUR_T49_API_KEY\
&number=MRKU9465770\
&sealine=MAEU\
&type=CT"
```

The compatibility deployment is separate from `mcp.terminal49.com`. If the custom domain is not available in your environment yet, use the Vercel deployment hostname with the same `/searates-api` path.

<Note>
The gateway covers ocean container, BOL, and booking tracking only. It does not implement SeaRates rates, schedules, air, parcel, road, AIS, route geometry, or history products.
</Note>

Continue with the rest of this guide when you are ready to adopt Terminal49's native JSON:API and webhook model.

## Start in sixty seconds

Expand Down
37 changes: 37 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
"private": true,
"description": "Terminal49 API with MCP Server",
"workspaces": [
"apps/*",
"packages/*",
"sdks/*"
],
"type": "module",
"scripts": {
"build": "npm run build --workspace @terminal49/sdk && npm run build --workspace @terminal49/mcp && npm run build --workspace @terminal49/cli",
"build": "npm run build --workspace @terminal49/sdk && npm run build --workspace @terminal49/mcp && npm run build --workspace @terminal49/searates-compat && npm run build --workspace @terminal49/migrate-app && npm run build --workspace @terminal49/cli",
"check": "npm run lint:api && npm run lint --workspaces && npm run type-check --workspaces",
"format": "vp fmt --write api && npm run format --workspaces",
"lint:api": "vp lint api && vp fmt --check api",
Expand Down
Loading
Loading