Authentication

To use the API, include your API key in the request headers. For example:

headers = {
    "Content-Type": "application/json", 
    "x-api-key": "YOUR_API_KEY_HERE"
}

The API key will be provided to you by Amphitrite giving you access to the requested API functions (forecast or hindcast).

To request an API key, please see our Contact and Support page.

Rate limiting

Rate limits are per API key (account). They are shared across the MetOcean and storms endpoints under a single counter.

Do not hard-code a default quota in your client. Read the contractual limits for your account with:

GET /user/rate-limit

import requests

r = requests.get(
    "https://YOUR_API_HOST/user/rate-limit",
    headers={"x-api-key": "YOUR_API_KEY_HERE"},
)
print(r.json())

Example response:

{
  "username": "acme",
  "limits": [
    {
      "count": 10,
      "period": "minute",
      "description": "10/minute",
      "unlimited": false
    }
  ]
}

Contractual behaviour

Aspect Value
Algorithm Token bucket. Your quota refills continuously, rather than resetting all at once at a period boundary.
Burst capacity Equal to your limit. With 500/minute you may send 500 requests back to back, then continue at the refill rate.
Refill rate Your limit divided by its period. 500/minute refills 8.33 requests per second, capped at 500.
Scope Shared across rate-limited MetOcean / storms endpoints for the same API key.
Multiple limits If your account has several (e.g. 500/minute and 500000/day), every one of them must admit the request.
HTTP 429 body {"error": "Rate limit exceeded: 500/minute. Retry after 0.12s."}
Retry-After Seconds until at least one request is available again — usually a fraction of a second.
Other headers X-RateLimit-Limit and X-RateLimit-Remaining on rate-limited responses, describing whichever of your limits is the most restrictive.

What this means in practice

Because the bucket refills continuously, exhausting your quota does not lock you out until the next period. On a 500/minute account, once the bucket is empty a new request becomes available every 120 ms — so Retry-After will typically read well under a second.

Two recommendations for clients:

  • Follow Retry-After rather than a fixed delay. A hard-coded "wait 60 seconds before retrying" wastes almost all of the recovery speed the token bucket gives you.
  • Stagger retries within a rejected batch. If several requests are refused at once they all receive the same Retry-After, but only one request's worth of credit is available at that moment. Spacing retries by a few tens of milliseconds lets the whole batch through without further rejections.

A burst is only rejected if it is genuinely tight: on a 500/minute account, 516 requests spread over two seconds or more all succeed, because the bucket refills while the batch is being sent.

Server busy (HTTP 503)

/MetOcean, /MetOcean/async and /2DMetOcean may answer HTTP 503 Service Unavailable when the server is temporarily overloaded, i.e. too many tasks are already waiting to be processed. The request is then not queued at all.

Unlike a 429, a 503 is not tied to your API key or your rate limit: it reflects the load of the whole platform and clears as soon as the backlog drains.

Aspect Value
HTTP 503 body {"detail": "Too many tasks are waiting to be processed. Please retry later."}
Retry-After Seconds to wait before retrying (currently 30).

Recommendations for clients:

  • Retry after Retry-After, not immediately: retrying in a tight loop only adds to the backlog.
  • Send large volumes through /MetOcean/async, spread over time, rather than as a burst of synchronous calls.