Quickstart
Three steps to push your first vessel:
- Generate an API key from your developer portal
- POST vessel data to
/api/v1/vessels - 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" }'
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.
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)" }
]
}
| Status | Error code | Meaning |
|---|---|---|
| 401 | missing_auth / invalid_key | No or invalid API key |
| 422 | validation_failed | IMO invalid, missing required field, bad date |
| 429 | rate_limited | 100 req/min exceeded; check retry_after |
| 500 | server_error | Contact support@canalclear.com |
Vessels
Push vessel particulars. Data is stored against the IMO number — subsequent pushes update the existing record (upsert).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| imo | string | REQUIRED | 7-digit IMO number (check digit validated) |
| vessel_name | string | optional | Name of vessel |
| flag | string | optional | Flag state (ISO 3166-1 alpha-2, e.g. "PA") |
| gross_tonnage | number | optional | Gross tonnage (GT) |
| net_tonnage | number | optional | Net tonnage (NT) |
| loa | number | optional | Length overall in metres |
| beam | number | optional | Beam in metres |
| draft | number | optional | Maximum draft in metres |
| vessel_class | string | optional | Classification society class notation |
| vessel_type | string | optional | e.g. "bulk_carrier", "tanker", "container" |
| call_sign | string | optional | Radio call sign |
| mmsi | string | optional | 9-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" } }
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.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| vessel_imo | string | REQUIRED | IMO of the vessel |
| voyage_ref | string | optional | TMS voyage number — used as upsert key |
| origin | string | optional | Departure port (UN/LOCODE or name) |
| destination | string | optional | Arrival port |
| eta | string | optional | ISO 8601 datetime e.g. 2026-06-01T08:00:00Z |
| etd | string | optional | ISO 8601 datetime — must be after eta if both provided |
| cargo_type | string | optional | e.g. "bulk", "crude_oil", "containers", "LNG" |
| cargo_quantity | number | optional | Metric tons |
| waterway | string | optional | One of: panama, suez, bosporus, malacca, cape |
Query parameters
| Param | Default | Description |
|---|---|---|
| vessel_imo | — | Filter to a specific vessel |
| limit | 50 | Max results (max 200) |
| offset | 0 | Pagination offset |
Crew
Push crew manifests for a vessel. Each POST appends the provided members — it does not replace existing crew.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| vessel_imo | string | REQUIRED | IMO of the vessel |
| voyage_ref | string | optional | Associate with a voyage |
| crew | array | REQUIRED | Array of crew member objects (see below) |
Crew member object
| Field | Type | Required | Description |
|---|---|---|---|
| full_name | string | REQUIRED | Full name of crew member |
| nationality | string | optional | ISO 3166-1 alpha-2 e.g. "PH" |
| rank | string | optional | e.g. "Master", "Chief Officer", "AB" |
| cert_number | string | optional | STCW certificate number |
| cert_type | string | optional | e.g. "STCW", "GMDSS" |
| cert_expiry | string | optional | YYYY-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.
Query parameters
| Param | Description |
|---|---|
| source | Label for this source (e.g. veson, q88) — appears in delivery log |
| mapping_id | ID 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" } }'
"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:
API Key Management
These endpoints use session auth (your dashboard login), not API key auth — use them from your fleet dashboard or internal scripts.
Body: { "label": "Veson prod" }
Returns all active and revoked keys for your account. Raw keys are never returned.
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.
Returns the 50 most recent webhook deliveries with status, source, and a payload preview.
Returns the complete headers and JSON payload for a single delivery. Statuses: received, mapped, ingested, invalid, error.
Last 50 inbound data pushes across vessels, voyages, and crew — with entity type, reference, source, and timestamp.