REST API
Endpoint: https://api.vesselmcp.com. It is read-only and requires authentication. Paths must match exactly and query parameters are not accepted. Successful responses have the shape { "data": ... }. There is no CORS permission header, and responses disable caching.
Routes
| Method | Path | Successful data |
|---|---|---|
GET | /v1/vessels/{imo} | { "vessel": identity object } |
GET | /v1/vessels/{imo}/recent-ports | { "imo", "recentPorts", "fetchedAt" } |
See the query guide for field rules.
GET /v1/vessels/9331919
Authorization: Bearer vmcp_api_v1_<key-id>_<secret>{
"data": {
"vessel": {
"imo": "9331919",
"name": "OCEAN HIRYU",
"fetchedAt": "2026-09-06T01:02:03.456Z"
}
}
}Ports:
GET /v1/vessels/9331919/recent-ports
Authorization: Bearer vmcp_api_v1_<key-id>_<secret>{
"data": {
"imo": "9331919",
"recentPorts": [],
"fetchedAt": "2026-09-06T01:02:03.456Z"
}
}Only vmcp_api_v1_... keys are accepted. MCP keys cannot call this service.
Rate limits
Rate limiting first uses the requester IP address, then the non-sensitive key ID after successful authentication. Limits are counted per Cloudflare location, not as a global billing quota.
| Stage | Limit |
|---|---|
| Before authentication, by IP | 60 requests per 60 seconds |
| After authentication, by key ID | 30 requests per 60 seconds |
A limit is exceeded with 429 RATE_LIMITED and Retry-After: 60. Identity and ports each count as one request.
Errors
Errors have the shape { "error": { "code", "message" } }.
Validation runs in this order: IP rate limit, authentication, key-ID rate limit, exact path, HTTP method, then IMO checksum and query parameters. The route-related errors below assume authentication and both rate-limit stages have passed. For example, an unauthenticated request to an unknown path normally returns 401, not 404; a rate-limit or service failure may be returned earlier.
| HTTP | error.code | When |
|---|---|---|
| 400 | INVALID_REQUEST | GET on a recognized route with an invalid IMO checksum, 0000000, or query parameters |
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 404 | NOT_FOUND | Path does not exactly match either route, including malformed IMO segments, trailing slashes, or extra segments |
| 404 | VESSEL_NOT_FOUND | Identity is genuinely not found |
| 405 | METHOD_NOT_ALLOWED | Recognized route using a method other than GET; an unknown path returns 404 first |
| 429 | RATE_LIMITED | IP or key-ID limit exceeded |
| 502 | BACKEND_UNAVAILABLE | Query failure, timeout, or invalid result |
| 503 | SERVICE_UNAVAILABLE | Service temporarily unavailable |
A port-query failure does not become an empty array or VESSEL_NOT_FOUND.