REST API v1

TMS Integration API

Push vessel, voyage, and crew data directly into CanalClear from Veson, Q88, Dataloy, ShipNet, or any custom system. One API, every waterway.

Get API Key → Quickstart

Quickstart

Three steps to push your first vessel:

  1. Generate an API key from your developer portal
  2. POST vessel data to /api/v1/vessels
  3. Data auto-fills your filing wizards
# Push a vessel — replace with your API key and real IMO
curl -X POST https://canalclear.org/api/v1/vessels \
  -H "Authorization: Bearer cc_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "imo": "9321483",
    "vessel_name": "EVER GIVEN",
    "flag": "PA",
    "gross_tonnage": 219079,
    "loa": 399.94,
    "beam": 58.8,
    "draft": 14.5,
    "vessel_type": "container"
  }'
Base URL: https://canalclear.org/api/v1  ·  All requests and responses are JSON.

Authentication

Every request must include your API key as a Bearer token:

Authorization: Bearer cc_live_YOUR_KEY_HERE

API keys are generated from your developer portal. Each key is scoped to your account. Keys start with cc_live_ followed by 32 hex characters.

Key shown once. The full key is only returned at creation time. Store it immediately in your TMS or environment variables — it cannot be retrieved again.

Rate Limits

100 requests per minute per API key. Rate limit state is tracked in a sliding window per key.

Every response includes rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1748000060    # Unix timestamp when window resets

Exceeding the limit returns 429 with a retry_after field (seconds).

Error Responses

All errors return JSON with consistent structure:

{
  "success": false,
  "error": "validation_failed",
  "message": "Payload failed validation",
  "errors": [
    { "field": "imo", "message": "IMO check digit invalid (expected 3, got 2)" }
  ]
}
StatusError codeMeaning
401missing_auth / invalid_keyNo or invalid API key
422validation_failedIMO invalid, missing required field, bad date
429rate_limited100 req/min exceeded; check retry_after
500server_errorContact support@canalclear.com

Vessels

Push vessel particulars. Data is stored against the IMO number — subsequent pushes update the existing record (upsert).

POST /api/v1/vessels Create or update vessel

Request body

FieldTypeRequiredDescription
imostringREQUIRED7-digit IMO number (check digit validated)
vessel_namestringoptionalName of vessel
flagstringoptionalFlag state (ISO 3166-1 alpha-2, e.g. "PA")
gross_tonnagenumberoptionalGross tonnage (GT)
net_tonnagenumberoptionalNet tonnage (NT)
loanumberoptionalLength overall in metres
beamnumberoptionalBeam in metres
draftnumberoptionalMaximum draft in metres
vessel_classstringoptionalClassification society class notation
vessel_typestringoptionale.g. "bulk_carrier", "tanker", "container"
call_signstringoptionalRadio call sign
mmsistringoptional9-digit MMSI

Response 200

// Returns the stored/updated vessel record
{
  "success": true,
  "vessel": {
    "id": 42,
    "imo_number": "9321483",
    "vessel_name": "EVER GIVEN",
    "flag": "PA",
    "gross_tonnage": 219079,
    "loa": "399.94",
    "source": "api",
    "updated_at": "2026-05-13T10:22:00Z"
  }
}
GET /api/v1/vessels/:imo Retrieve vessel by IMO

Returns the stored particulars for a vessel by its 7-digit IMO number.

curl https://canalclear.org/api/v1/vessels/9321483 \
  -H "Authorization: Bearer cc_live_YOUR_KEY"

Voyages

Push voyage scheduling data. If voyage_ref is provided, subsequent pushes with the same ref update the record. Otherwise a new voyage is created.

POST /api/v1/voyages Create or update voyage

Request body

FieldTypeRequiredDescription
vessel_imostringREQUIREDIMO of the vessel
voyage_refstringoptionalTMS voyage number — used as upsert key
originstringoptionalDeparture port (UN/LOCODE or name)
destinationstringoptionalArrival port
etastringoptionalISO 8601 datetime e.g. 2026-06-01T08:00:00Z
etdstringoptionalISO 8601 datetime — must be after eta if both provided
cargo_typestringoptionale.g. "bulk", "crude_oil", "containers", "LNG"
cargo_quantitynumberoptionalMetric tons
waterwaystringoptionalOne of: panama, suez, bosporus, malacca, cape
GET /api/v1/voyages List voyages

Query parameters

ParamDefaultDescription
vessel_imoFilter to a specific vessel
limit50Max results (max 200)
offset0Pagination offset

Crew

Push crew manifests for a vessel. Each POST appends the provided members — it does not replace existing crew.

POST /api/v1/crew Add crew members

Request body

FieldTypeRequiredDescription
vessel_imostringREQUIREDIMO of the vessel
voyage_refstringoptionalAssociate with a voyage
crewarrayREQUIREDArray of crew member objects (see below)

Crew member object

FieldTypeRequiredDescription
full_namestringREQUIREDFull name of crew member
nationalitystringoptionalISO 3166-1 alpha-2 e.g. "PH"
rankstringoptionale.g. "Master", "Chief Officer", "AB"
cert_numberstringoptionalSTCW certificate number
cert_typestringoptionale.g. "STCW", "GMDSS"
cert_expirystringoptionalYYYY-MM-DD format
# Example: push 2 crew members
curl -X POST https://canalclear.org/api/v1/crew \
  -H "Authorization: Bearer cc_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vessel_imo": "9321483",
    "voyage_ref": "VOY-2026-041",
    "crew": [
      {
        "full_name": "Juan Santos",
        "nationality": "PH",
        "rank": "Master",
        "cert_number": "STCW-PH-20241",
        "cert_expiry": "2028-03-15"
      },
      {
        "full_name": "Li Wei",
        "nationality": "CN",
        "rank": "Chief Officer"
      }
    ]
  }'

Webhook Receiver

Configure your TMS to send webhooks to a single endpoint. CanalClear logs every delivery and optionally maps fields using a stored template before ingesting.

POST /api/v1/webhook Generic webhook receiver

Query parameters

ParamDescription
sourceLabel for this source (e.g. veson, q88) — appears in delivery log
mapping_idID of a stored field mapping template to apply before ingestion

Configure your Veson IMOS webhook URL as:

https://canalclear.org/api/v1/webhook?source=veson&mapping_id=1
Authorization: Bearer cc_live_YOUR_KEY

Response 202

{
  "success": true,
  "delivery_id": 187,          // use this to inspect the delivery log
  "status": "ingested",
  "ingested": {
    "vessel": "9321483",
    "voyage": 55
  }
}

Field Mapping

TMS systems use different field names. Create a mapping template once, then reference it with ?mapping_id=N on the webhook endpoint.

Mapping keys are CanalClear target fields. Values are dot-notation paths into the source JSON payload.

# Create a mapping template for Veson IMOS
curl -X POST https://canalclear.org/api/developer/webhook-mappings \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Veson IMOS Vessel Update",
    "source_name": "veson",
    "mapping": {
      "imo": "vessel.imo_no",
      "vessel_name": "vessel.vessel_code",
      "vessel_type": "vessel.vessel_type_description",
      "gross_tonnage": "vessel.gt",
      "loa": "vessel.loa",
      "beam": "vessel.beam",
      "draft": "vessel.draft_max"
    }
  }'
Dot notation: "vessel.imo_no" maps to payload.vessel.imo_no in the raw JSON. Nested objects work as expected.

TMS Compatibility

Works with any system that can make HTTP POST requests. Pre-built field mapping templates available for:

Veson IMOS
✓ REST webhook
Q88
✓ Vessel API
Dataloy
✓ REST export
ShipNet
✓ Event webhook
OneOcean
✓ REST API
Custom
✓ Any HTTP client
Need a pre-built mapping for your TMS? Email support@canalclear.com — typical turnaround is 1 business day.

API Key Management

These endpoints use session auth (your dashboard login), not API key auth — use them from your fleet dashboard or internal scripts.

POST /api/developer/keys Generate new API key

Body: { "label": "Veson prod" }

The raw key is only shown once. Store it immediately.
GET /api/developer/keys List all API keys (prefix only)

Returns all active and revoked keys for your account. Raw keys are never returned.

DELETE /api/developer/keys/:id Revoke a key

Immediately revokes the key. All future requests using it return 401. Irreversible.

Webhook Delivery Log

Every webhook delivery is logged. Use this to debug failed pushes or inspect raw payloads.

GET /api/developer/webhook-logs List recent deliveries

Returns the 50 most recent webhook deliveries with status, source, and a payload preview.

GET /api/developer/webhook-logs/:id Full payload inspection

Returns the complete headers and JSON payload for a single delivery. Statuses: received, mapped, ingested, invalid, error.

GET /api/developer/activity Inbound data activity feed

Last 50 inbound data pushes across vessels, voyages, and crew — with entity type, reference, source, and timestamp.