Meridian API Reference Download Bruno Collection Get API Key

Meridian API

Maritime container tracking SaaS by Arellano Global.

Track Master Bills of Lading (MBLs) and containers across all major carriers. One credit is charged per new MBL registered. All subsequent queries are free. Tracking automatically stops 10 days after confirmed arrival.

Authentication

All external API endpoints require an X-API-Key header. Obtain your API key from the Meridian Dashboard or contact support@arellanoglobal.com.

Bruno Collection

Download the Bruno API collection for local testing: meridian-api-collection.zip

Error Codes
CodeHTTPDescription
UNAUTHORIZED401Missing or invalid API key
INSUFFICIENT_CREDITS402Balance is zero; deposit credits first
INVALID_FORMAT400MBL or container number format is invalid
CARRIER_NOT_SUPPORTED400Carrier SCAC not in supported list
MBL_NOT_FOUND404MBL does not exist in your account
CONTAINER_NOT_FOUND404Container not linked to any tracked MBL
DUPLICATE_MBL200MBL already tracked — returns existing record
Quick Start
# Register an MBL (costs 1 credit)
curl -X POST https://shiptrack.arellanoglobal.cloud/v1/tracking/mbl \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"mbl_number":"MAEU123456789","carrier_code":"MAEU"}'

# Get MBL status
curl https://shiptrack.arellanoglobal.cloud/v1/tracking/mbl/MAEU123456789 \
  -H "X-API-Key: sht_your_key_here"

# Check your credit balance
curl https://shiptrack.arellanoglobal.cloud/v1/credits/balance \
  -H "X-API-Key: sht_your_key_here"
Base URLs
https://shiptrack.arellanoglobal.cloudProduction
https://shipment.staging.arellanoglobal.cloudStaging
http://localhost:3005Local development
Authentication
X-API-Key: sht_your_key_here

System

Health checks, readiness, metrics

Health check

GET/api/health

Returns service health and provider availability. No authentication required. Used by Traefik/Coolify for liveness checks.

🔒 Requires X-API-Key header

Responses

200Service is healthy
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/health" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "status": "ok",
  "service": "ag-shiptrack",
  "ts": "2026-05-30T00:00:00.000Z",
  "jsoncargo": true,
  "sinay": true,
  "terminal49": false
}

Readiness check

GET/api/ready

Verifies dependencies (Postgres and Redis) with short timeouts.

🔒 Requires X-API-Key header

Responses

200All dependencies reachable
503A dependency is down
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/ready" \
  -H "X-API-Key: sht_your_key_here"

Prometheus metrics

GET/metrics

Default process metrics plus HTTP request histogram and counter. Gated by the m2m admin key.

🔒 Requires X-API-Key header

Responses

200Prometheus text exposition
401Missing X-Admin-Key
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/metrics" \
  -H "X-API-Key: sht_your_key_here"

Admin (m2m)

Machine-to-machine ops endpoints (n8n) — static X-Admin-Key

Poll all active MBLs (n8n WF01)

POST/admin/tracking/poll-all
🔒 Requires X-API-Key header

Responses

200Queued count
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/tracking/poll-all" \
  -H "X-API-Key: sht_your_key_here"

Deactivate MBLs past auto-stop (n8n WF03)

POST/admin/tracking/auto-stop
🔒 Requires X-API-Key header

Responses

200Stopped count
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/tracking/auto-stop" \
  -H "X-API-Key: sht_your_key_here"

Re-queue failed webhook deliveries (n8n WF02)

POST/admin/webhooks/retry-failed
🔒 Requires X-API-Key header

Responses

200Retried count
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/webhooks/retry-failed" \
  -H "X-API-Key: sht_your_key_here"

Purge raw carrier payloads past retention (n8n WF04)

POST/admin/retention/purge-raw
🔒 Requires X-API-Key header

Request body

older_than_hours optional
integer

Responses

200Purged count
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/retention/purge-raw" \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"older_than_hours":48}'

Admin Console

Superadmin god-view — requires the Keycloak ag-admin realm role

Platform KPI overview

GET/admin/overview
🔒 Requires X-API-Key header

Responses

200Accounts, MBLs, credits and revenue rollups
401Missing or invalid token
403Missing ag-admin role
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/overview" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "accounts": {
    "total": 2,
    "active": 2,
    "new_7d": 0
  },
  "mbl_tracking": {
    "total": 309,
    "active": 305,
    "new_7d": 0,
    "by_status": {
      "ARRIVED": 4,
      "IN_TRANSIT": 0,
      "PENDING": 302,
      "UNKNOWN": 3
    }
  },
  "total_credits": 542,
  "credits_consumed": 309,
  "revenue": {
    "total_usd": 0,
    "payments": 0
  }
}

Deep system health (Postgres, Redis, Keycloak, provider)

GET/admin/health
🔒 Requires X-API-Key header

Responses

200Per-subsystem status and latencies (cached snapshot)
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/health" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "healthy": true,
  "checked_at": "2026-01-01T00:00:00Z",
  "cached": true,
  "age_ms": 1200,
  "postgres": {
    "status": "ok",
    "latency_ms": 5,
    "error": "string"
  },
  "redis": {
    "status": "ok",
    "latency_ms": 5,
    "error": "string"
  },
  "keycloak": {
    "status": "ok",
    "latency_ms": 5,
    "error": "string"
  },
  "provider_jsoncargo": {
    "status": "ok",
    "latency_ms": 5,
    "error": "string"
  }
}

Daily timeseries (signups, MBLs, credits, revenue)

GET/admin/kpi/timeseries
🔒 Requires X-API-Key header

Query parameters

days optional
integer

Responses

200Gap-filled day series
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/kpi/timeseries?days=30" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "days": 30,
  "series": [
    {
      "day": "2026-06-07",
      "signups": 0,
      "mbls": 12,
      "credits_consumed": 12,
      "revenue_usd": 0
    }
  ]
}

Revenue and credit economics

GET/admin/revenue
🔒 Requires X-API-Key header

Responses

200All-time and 30-day revenue, per-package, per-tier and credit flow
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/revenue" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "all_time": {
    "revenue_usd": 0,
    "payments": 0
  },
  "last_30d": {
    "revenue_usd": 0,
    "payments": 0
  },
  "by_package": [
    {
      "package_id": "string",
      "payments": 0,
      "revenue_usd": 0
    }
  ],
  "by_tier": [
    {
      "tier": "string",
      "accounts": 0,
      "credits": 0
    }
  ],
  "credits_flow": {
    "deposited": 0,
    "consumed": 0,
    "refunded": 0,
    "adjusted": 0
  }
}

Top tenants by lifetime consumption

GET/admin/top-accounts
🔒 Requires X-API-Key header

Query parameters

limit optional
integer

Responses

200Ranked tenants
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/top-accounts?limit=10" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "accounts": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "tier": "string",
      "consumed": 0,
      "balance": 0,
      "active_mbls": 0,
      "total_mbls": 0
    }
  ]
}

Live activity feed

GET/admin/activity
🔒 Requires X-API-Key header

Responses

200Recent accounts, MBLs, transactions and payments
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/activity" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "accounts": [
    {}
  ],
  "mbls": [
    {}
  ],
  "transactions": [
    {}
  ],
  "payments": [
    {}
  ]
}

Admin audit trail (append-only)

GET/admin/audit-log
🔒 Requires X-API-Key header

Query parameters

actor optional
string
action optional
string
limit optional
integer

Responses

200Audit entries
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/audit-log?actor=string&action=string&limit=100" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "total": 42,
  "limit": 100,
  "offset": 0,
  "entries": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "actor": "christian@arellanoglobal.org",
      "action": "credit_deposit",
      "target_type": "credit",
      "target_id": "string",
      "detail": {},
      "outcome": "success",
      "ip": "string",
      "created_at": "2026-01-01T00:00:00Z"
    }
  ]
}

List tenant accounts (paginated)

GET/admin/accounts
🔒 Requires X-API-Key header

Query parameters

search optional
string
status optional
enum
page optional
integer
limit optional
integer

Responses

200Account page
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/accounts?search=string&status=all&page=1&limit=20" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "total": 0,
  "page": 0,
  "limit": 0,
  "accounts": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "email": "string",
      "tier": "string",
      "active": true,
      "balance": 0,
      "mbl_count": 0
    }
  ]
}

Create tenant account and initial API key

POST/admin/accounts
🔒 Requires X-API-Key header

Responses

201Account plus api_key (returned once)
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/accounts" \
  -H "X-API-Key: sht_your_key_here"
201application/json
{
  "account": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "email": "string",
    "tier": "string",
    "created_at": "2026-01-01T00:00:00Z"
  },
  "api_key": "string"
}

Deposit credits to an account

POST/admin/credits/deposit
🔒 Requires X-API-Key header

Request body required

account_id required
string
amount required
integer
note optional
string

Responses

200New balance
400Invalid amount
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/credits/deposit" \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"account_id":"00000000-0000-0000-0000-000000000000","amount":0,"note":"string"}'
200application/json
{
  "account_id": "00000000-0000-0000-0000-000000000000",
  "new_balance": 0,
  "credits_added": 0,
  "credits_deducted": 0
}

Deduct credits from an account

POST/admin/credits/deduct
🔒 Requires X-API-Key header

Request body required

account_id required
string
amount required
integer
note optional
string

Responses

200New balance
400Missing account_id / invalid amount
402Insufficient balance
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/admin/credits/deduct" \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"account_id":"00000000-0000-0000-0000-000000000000","amount":0,"note":"string"}'
200application/json
{
  "account_id": "00000000-0000-0000-0000-000000000000",
  "new_balance": 0,
  "credits_added": 0,
  "credits_deducted": 0
}

Activate or suspend an account

PATCH/admin/accounts/{id}/status
🔒 Requires X-API-Key header

Path parameters

id required
string

Request body required

active required
boolean

Responses

200Updated status
400active (boolean) required
RequestcURL
curl -X PATCH "https://shiptrack.arellanoglobal.cloud/admin/accounts/00000000-0000-0000-0000-000000000000/status" \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"active":true}'
200application/json
{
  "id": "00000000-0000-0000-0000-000000000000",
  "active": true
}

DB security posture (RLS/role audit, read-only)

GET/admin/maintenance/db-audit
🔒 Requires X-API-Key header

Responses

200Role attributes and per-table RLS status
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/admin/maintenance/db-audit" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "db_user": "shiptrack_user",
  "is_superuser": true,
  "bypasses_rls": true,
  "tenant_isolation": "string",
  "tables": [
    {
      "table_name": "string",
      "rls_enabled": true,
      "rls_forced": true,
      "owner": "string",
      "policies": 0
    }
  ]
}

Dashboard

Tenant self-service API (Keycloak user bearer) — consumed by the web dashboard

Current account profile + balance

GET/api/dashboard/me
🔒 Requires X-API-Key header

Responses

200Account + credit balance
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/me" \
  -H "X-API-Key: sht_your_key_here"

List this tenant's MBLs (paginated, client-side filtered)

GET/api/dashboard/mbls
🔒 Requires X-API-Key header

Query parameters

page optional
integer
limit optional
integer
status optional
string

Responses

200mbls[] + total/page/limit/pages
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/mbls?page=1&limit=1000&status=string" \
  -H "X-API-Key: sht_your_key_here"

Register an MBL (KC dashboard path; debits 1 credit)

POST/api/dashboard/mbls
🔒 Requires X-API-Key header

Responses

201Tracking record
402Insufficient credits
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/api/dashboard/mbls" \
  -H "X-API-Key: sht_your_key_here"

MBL detail (this tenant)

GET/api/dashboard/mbls/{number}
🔒 Requires X-API-Key header

Path parameters

number required
string

Responses

200MBL + containers
404Not found
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/mbls/string" \
  -H "X-API-Key: sht_your_key_here"

MBL event timeline (this tenant)

GET/api/dashboard/mbls/{number}/events
🔒 Requires X-API-Key header

Path parameters

number required
string

Responses

200events[]
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/mbls/string/events" \
  -H "X-API-Key: sht_your_key_here"

Balance + recent transactions

GET/api/dashboard/credits
🔒 Requires X-API-Key header

Responses

200balance + transactions[]
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/credits" \
  -H "X-API-Key: sht_your_key_here"

List webhooks

GET/api/dashboard/webhooks
🔒 Requires X-API-Key header

Responses

200webhooks[]
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/webhooks" \
  -H "X-API-Key: sht_your_key_here"

List API keys (prefixes only)

GET/api/dashboard/keys
🔒 Requires X-API-Key header

Responses

200keys[]
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/api/dashboard/keys" \
  -H "X-API-Key: sht_your_key_here"

Create a new API key (full key returned once)

POST/api/dashboard/keys
🔒 Requires X-API-Key header

Responses

201key + api_key (shown once)
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/api/dashboard/keys" \
  -H "X-API-Key: sht_your_key_here"

General

Register MBL for tracking

POST/v1/tracking/mbl

Begin tracking a Master Bill of Lading. Deducts 1 credit from your balance.

If the MBL is already tracked on your account, returns the existing record with message: "Already tracking"no credit is charged.

An initial upstream query is fired asynchronously after registration. Status will be PENDING for a few seconds until the first query completes.

🔒 Requires X-API-Key header

Header parameters

Idempotency-Key optional
string

Optional client-supplied key; the first 2xx response is replayed for 24h on retry (no double credit charge).

Request body required

mbl_number required
string

Master Bill of Lading number

carrier_code optional
string

SCAC carrier code (optional — helps with format validation). Supported: MAEU, EGLV, MSCU, CMDU, HLCU, OOLU, APLU, COSU, YMLU, HDMU

Responses

200Already tracking — no credit charged
201Tracking started
400Validation error
401
402Insufficient credits
429
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/v1/tracking/mbl" \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"mbl_number":"MAEU0001234567","carrier_code":"MAEU"}'
200application/json
{
  "message": "Already tracking",
  "mbl": {
    "id": "00000000-0000-0000-0000-000000000000",
    "mbl_number": "MAEU0001234567",
    "carrier_code": "MAEU",
    "status": "IN_TRANSIT",
    "last_queried_at": "2026-01-01T00:00:00Z",
    "arrival_confirmed_at": "2026-01-01T00:00:00Z",
    "auto_stop_at": "2026-01-01T00:00:00Z",
    "active": true,
    "created_at": "2026-01-01T00:00:00Z",
    "containers": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "container_number": "MSDU7640904",
        "iso_code": "45G1",
        "size_type": "40ft HC",
        "status": "DISCHARGED"
      }
    ]
  }
}
201application/json
{
  "message": "Tracking started",
  "mbl": {
    "id": "00000000-0000-0000-0000-000000000000",
    "mbl_number": "MAEU0001234567",
    "carrier_code": "MAEU",
    "status": "IN_TRANSIT",
    "last_queried_at": "2026-01-01T00:00:00Z",
    "arrival_confirmed_at": "2026-01-01T00:00:00Z",
    "auto_stop_at": "2026-01-01T00:00:00Z",
    "active": true,
    "created_at": "2026-01-01T00:00:00Z",
    "containers": [
      {
        "id": "00000000-0000-0000-0000-000000000000",
        "container_number": "MSDU7640904",
        "iso_code": "45G1",
        "size_type": "40ft HC",
        "status": "DISCHARGED"
      }
    ]
  },
  "credits_remaining": 46
}
400application/json
{
  "error": "INVALID_FORMAT",
  "message": "Maersk MBL must be exactly 10 digits"
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
402application/json
{
  "error": "INSUFFICIENT_CREDITS",
  "message": "Insufficient credits"
}
429application/json
{
  "error": "RATE_LIMITED",
  "message": "Rate limit exceeded (1200 requests/min for the enterprise tier)"
}

Get MBL status

GET/v1/tracking/mbl/{number}

Returns full shipment status including all containers. Free — no credit charge.

🔒 Requires X-API-Key header

Path parameters

number required
string

Responses

200MBL found
401
404MBL not tracked on this account
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/tracking/mbl/MAEU0001234567" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "id": "00000000-0000-0000-0000-000000000000",
  "mbl_number": "MAEU0001234567",
  "carrier_code": "MAEU",
  "status": "IN_TRANSIT",
  "last_queried_at": "2026-01-01T00:00:00Z",
  "arrival_confirmed_at": "2026-01-01T00:00:00Z",
  "auto_stop_at": "2026-01-01T00:00:00Z",
  "active": true,
  "created_at": "2026-01-01T00:00:00Z",
  "containers": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "container_number": "MSDU7640904",
      "iso_code": "45G1",
      "size_type": "40ft HC",
      "status": "DISCHARGED"
    }
  ]
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
404application/json
{
  "error": "MBL_NOT_FOUND",
  "message": "MBL not found"
}

Get MBL event timeline

GET/v1/tracking/mbl/{number}/events

Full ordered event timeline for all containers on this MBL. Free — no credit charge.

🔒 Requires X-API-Key header

Path parameters

number required
string

Responses

200Event timeline
401
404MBL not found
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/tracking/mbl/MAEU0001234567/events" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "mbl_number": "string",
  "events": [
    {
      "order_id": 0,
      "event_code": "DISC",
      "event_type": "EQUIPMENT",
      "description": "Container discharged at terminal",
      "date": "2026-01-01T00:00:00Z",
      "actual": true,
      "transport_type": "VESSEL",
      "location_locode": "USLAX",
      "location_name": "Los Angeles",
      "vessel_name": "EVER ACE",
      "vessel_imo": 9741406,
      "voyage": "0041E"
    }
  ]
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
404application/json
{
  "error": "INVALID_FORMAT",
  "message": "MBL number format invalid for carrier MAEU"
}

Get container status

GET/v1/tracking/container/{number}

Container status and its parent MBL. The container must belong to an MBL already tracked on your account.

🔒 Requires X-API-Key header

Path parameters

number required
string

Responses

200Container found
400Invalid container number format
401
404Container not found
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/tracking/container/MSDU7640904" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "id": "00000000-0000-0000-0000-000000000000",
  "container_number": "MSDU7640904",
  "iso_code": "45G1",
  "size_type": "40ft HC",
  "status": "DISCHARGED",
  "mbl_number": "string",
  "mbl_status": "string"
}
400application/json
{
  "error": "INVALID_CONTAINER",
  "message": "Container number must match CCCC1234567 format"
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
404application/json
{
  "error": "INVALID_FORMAT",
  "message": "MBL number format invalid for carrier MAEU"
}

Get vessel details

GET/v1/vessel/{imo}

Returns live AIS position data (vessel/pro) combined with static vessel specifications (vessel/specs). Results are cached in Redis — AIS data for 5 minutes, specs for 7 days. No credit charge.

🔒 Requires X-API-Key header

Path parameters

imo required
string

IMO vessel number

Responses

200Vessel found
401
404Vessel not found
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/vessel/9321483" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "uuid": "871983e3-d771-2c2a-63c4-7f7cb2cbc919",
  "name": "EMMA MAERSK",
  "imo": "9321483",
  "mmsi": "563254800",
  "lat": -10.018851,
  "lon": 73.783455,
  "speed": 19.1,
  "course": 237,
  "heading": 263,
  "current_draught": 16.5,
  "navigation_status": "Under way using engine",
  "destination": "ESALG",
  "dest_port_unlocode": "ESALG",
  "dep_port": "TANJUNG PELEPAS",
  "dep_port_unlocode": "MYTPP",
  "last_position_UTC": "2026-01-01T00:00:00Z",
  "atd_UTC": "2026-01-01T00:00:00Z",
  "eta_UTC": "2026-01-01T00:00:00Z",
  "timezone": "+05",
  "specs": {
    "teu": 15550,
    "gross_tonnage": 171542,
    "deadweight": 174239,
    "length": 397.71,
    "breadth": 56.55,
    "draught_avg": 12.8,
    "draught_max": 12.8,
    "year_built": "2006",
    "callsign": "9VCY3",
    "country_name": "Singapore",
    "home_port": "LYNGBY-TAARBAEK"
  }
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
404application/json
{
  "error": "VESSEL_NOT_FOUND",
  "message": "Vessel not found"
}

Get terminals at a port

GET/v1/vessel/terminal/{locode}

Returns all container terminals at the specified UN/LOCODE. Cached for 7 days. Useful for identifying the exact terminal for POL and POD enrichment. No credit charge.

🔒 Requires X-API-Key header

Path parameters

locode required
string

5-character UN/LOCODE

Responses

200Terminals found
401
404No terminals found for this UNLOCODE
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/vessel/terminal/DEHAM" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "locode": "DEHAM",
  "terminals": [
    {
      "unlocode": "DEHAM",
      "code": "CTA",
      "terminal_name": "HHLA CONTAINER TERMINAL ALTENWERDER (CTA)",
      "company_name": "HHLA (HAMBURGER HAFEN UND LOGISTIK AG)",
      "lat": "53.500944",
      "lon": "9.936306",
      "url": "https://example.com",
      "address": "Am Ballinkai 1, 21129 Hamburg, Germany"
    }
  ]
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
404application/json
{
  "error": "TERMINAL_NOT_FOUND",
  "message": "No terminals found for this UNLOCODE"
}

Get credit balance

GET/v1/credits/balance

Current credit balance and last 100 transactions.

🔒 Requires X-API-Key header

Responses

200Credit balance
401
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/credits/balance" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "balance": 47,
  "updated_at": "2026-01-01T00:00:00Z",
  "transactions": [
    {
      "amount": -1,
      "type": "deposit",
      "mbl_number": "string",
      "note": "string",
      "created_at": "2026-01-01T00:00:00Z"
    }
  ]
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}

List webhooks

GET/v1/webhooks

Returns all active webhook subscriptions on your account.

🔒 Requires X-API-Key header

Responses

200Webhook list
401
RequestcURL
curl -X GET "https://shiptrack.arellanoglobal.cloud/v1/webhooks" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "webhooks": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "url": "https://yoursystem.com/hooks/meridian",
      "events": [
        "status_changed"
      ],
      "active": true,
      "created_at": "2026-01-01T00:00:00Z"
    }
  ]
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}

Subscribe to MBL events

POST/v1/webhooks/subscribe

Register a URL to receive signed webhook notifications on MBL status changes.

{
  "event": "status_changed",
  "mbl_number": "MAEU0001234567",
  "ts": "2025-08-01T08:00:00.000Z",
  "data": { "status": "ARRIVED" }
}

Each request includes X-Meridian-Signature: sha256=<hmac> computed over the JSON body using your webhook secret + server salt. Verify before processing.

  • status_changed — any status transition; payload includes status and previous_status
  • arrived — shipment reached destination (triggers 10-day auto-stop countdown)
  • departed — vessel has loaded and departed port of loading (status: DEPARTED or LOADED)
  • delayed — status transitioned to DELAYED

> Note: Your webhook subscription must include the event name in the events array > to receive that event type. The default subscription only includes status_changed and arrived.

🔒 Requires X-API-Key header

Request body required

url required
string
events optional
string[]

Responses

201Webhook created
401
RequestcURL
curl -X POST "https://shiptrack.arellanoglobal.cloud/v1/webhooks/subscribe" \
  -H "X-API-Key: sht_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://yoursystem.com/hooks/meridian","events":["status_changed","arrived"]}'
201application/json
{
  "id": "00000000-0000-0000-0000-000000000000",
  "url": "https://yoursystem.com/hooks/meridian",
  "events": [
    "status_changed"
  ],
  "active": true,
  "created_at": "2026-01-01T00:00:00Z",
  "secret": "whs_abc123def456..."
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}

Delete webhook

DELETE/v1/webhooks/{id}

Permanently deactivates a webhook subscription.

🔒 Requires X-API-Key header

Path parameters

id required
string

Responses

200Webhook deactivated
401
404Webhook not found
RequestcURL
curl -X DELETE "https://shiptrack.arellanoglobal.cloud/v1/webhooks/00000000-0000-0000-0000-000000000000" \
  -H "X-API-Key: sht_your_key_here"
200application/json
{
  "message": "Webhook deactivated"
}
401application/json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid API key"
}
404application/json
{
  "error": "INVALID_FORMAT",
  "message": "MBL number format invalid for carrier MAEU"
}