Throttling

    CarJam limits how fast a Development Connection may call the APIs, so that one busy integration cannot slow the register lookups down for everyone else. The limit is generous for ordinary use; you will only meet it when you fire requests in tight parallel loops or replay a backlog without pausing.

    The limit

    30 requests in any 10 second window, per Development Connection.

    • The window is rolling: at the moment a request arrives we count the requests you made in the previous 10 seconds. If that count has reached 30, the request is throttled. On /api/car/ the request being checked is already in that count, so keep to fewer than 30 in any 10 seconds to be safe.
    • The count is per Development Connection (per member), not per API key. Every API key you generate under the same connection shares the one allowance.
    • On /api/car/ every request that reaches your API usage log counts, including one answered from our cache and one that ended in an error. A request rejected before it is logged, for a missing or invalid API key, an invalid plate, or no products asked for, does not count.
    • On the /a/vehicle APIs a request counts once it is answered with data and charged. A null "still fetching" response and a repeat of the same plate within the hour, which is not charged, do not count.
    • The same limit applies on the test environment, so a load test against test behaves the way production will.

    A steady rate below 3 requests a second never trips it. Bursts above that are fine as long as they stay under 30 in any 10 seconds.

    What a throttled request looks like

    The APIs answer a throttled request in one of two ways, depending on the API.

    Vehicle queries (/api/car/)

    The throttle is checked when a request needs to go to the register: a basic lookup that is not in our cache, and every owners, owner, rucs and ppsr request. A basic-only request answered from cache is not throttled.

    A throttled request is answered with an error response, with the scode of err-too-many-requests. Nothing is fetched and nothing is charged for it. The HTTP status is 200, as with every other API error, so look at the top-level tag rather than the status code.

    <error>
        <code>-1</code>
        <scode>err-too-many-requests</scode>
        <message>Too many requests.</message>
        <class>apperror</class>
    </error>
    {
        "code": -1,
        "scode": "err-too-many-requests",
        "message": "Too many requests.",
        "class": "apperror"
    }

    Wait 2 seconds and send the same request again.

    ABCD, Extra vehicle info, Japan Lookup and Member reports (/a/...)

    These APIs, and the member reports lookup at /a/member:reports, already answer null with a Refresh: <seconds> HTTP header while data is being fetched (see ABCD for the pattern). A throttled request is answered the same way: the body is null, the Refresh header tells you how many seconds to wait, at least 2, and the X-Refresh-Notices header says why:

    HTTP/1.1 200 OK
    Content-Type: application/json
    Refresh: 2.000000
    X-Refresh-Notices: {"info":["Too many requests."]}
    
    null

    Nothing is charged for a null response. Wait the number of seconds the header names and repeat the request; the poll loop you already have for a null response handles this without any change.

    The other APIs

    At present only the APIs above are throttled. Please treat the limit as the guide for the others too; we may extend it to them without notice.

    Handling it

    • Read the response, not just the status code. A throttled request is an HTTP 200 in both shapes above. Treat err-too-many-requests and a null body with a Refresh header as "try again shortly", not as a failure of the lookup.
    • Retry with a pause. Wait at least the Refresh value (or 2 seconds for /api/car/) before retrying, and back off further if you are throttled again. Retrying immediately keeps you over the limit, and on /api/car/ every retry is logged and counts against the window too.
    • Pace bulk work. When you process a list of plates, keep a single worker below 3 requests a second, or space parallel workers so their combined rate stays under 30 requests in any 10 seconds. For large batches, Batch Reports processes a whole list for you without any pacing on your side.
    • Ask for what you need in one request. On /api/car/, basic=1&owners=1&ppsr=1 is one request against the limit; the same data as three separate calls is three.

    Throttling is separate from the null / Refresh answer you get while the register is being read. That one means the data is on its way; this one means you are asking too fast. Both are handled by the same wait-and-retry loop.

    If your integration genuinely needs a higher rate, please contact us and tell us about your use case.