filesoft.Discuss a project
← FileMaker guides

Worked tutorial · APIs

Handle HTTP 429 in FileMaker with limited retries

Give a read request a small retry budget, respect the service’s delay, and stop with a clear result.

By Plato · Filesoft · Published 21 October 2026

A rate limit is a reason to slow down

HTTP 429 means the service is limiting requests. Repeating the request immediately can make the situation worse. For a read-only GET, use a bounded retry policy with a visible stop condition, rather than a loop that runs until it eventually receives 200.

This tutorial proposes at most three attempts, including the first, a 20-second overall budget and a maximum foreground wait of five seconds. These are teaching choices, not universal API limits. Follow your provider’s quota and retry guidance.

Do not reuse this policy for record-creating POST requests. A failed response to a write can leave an uncertain remote outcome; that needs the operation-recovery design in the next pair of articles.

Separate transfer errors from HTTP results

Clear the response body and headers before every attempt. Use finite connection and total transfer timeouts. Immediately capture FileMaker’s transfer error; then inspect the final HTTP response and the expected body shape. A successful transfer can still carry HTTP 429.

FileMaker calculation · cURL options for one attempt

"--request GET --dump-header $responseHeaders" &
" --connect-timeout 5 --max-time 10"

This fragment belongs in Insert from URL’s cURL-options calculation, with SSL verification enabled. The literal $responseHeaders names a FileMaker output variable. It is not shell syntax. See supported cURL options.

A response may contain more than one header block, such as an interim response. Read the last applicable HTTP block and its Retry-After field together; do not combine a final status with an earlier block’s delay. Treat header names case-insensitively. Unexpected redirects, transfer failures and malformed response envelopes stop this example.

Handle both Retry-After formats

Header valuePolicy in this tutorial
3Wait at least three seconds, if the remaining budget permits
An HTTP-dateUse a verified UTC HTTP-date parser, or defer for manual/scheduled retry
MissingUse a bounded fallback of one second, then two seconds
Nonempty but unrecognizedDefer for review; do not guess the intended wait
120Defer; do not reduce the server’s requested delay to five seconds

HTTP-date values are not local FileMaker date strings. A production parser must understand the HTTP date grammar and time zone, account for clock differences, and reject invalid input. This teaching controller deliberately defers date-form values rather than guessing a local timestamp.

RFC 9110 defines the delay as seconds or an HTTP-date, and RFC 6585 defines 429. If the provider forbids retry without a valid header, replace the missing-header fallback with Defer. For concurrent workers, add provider-approved jitter that never retries earlier than the required delay.

Try the decision without calling an API

Set $attempt to 1 and $remaining to 20. This calculation produces a decision for a normalized integer HTTP status and one raw Retry-After value. It reserves up to ten seconds for the next request. It neither sleeps nor sends a request.

FileMaker calculation

Let ( [
    status = 429 ;
    raw = Trim ( "3" ) ;
    secondsOnly = not IsEmpty ( raw )
        and Exact ( Filter ( raw ; "0123456789" ) ; raw ) ;
    fallback = Min ( 2 ; $attempt ) ;
    wait = Case ( secondsOnly ; GetAsNumber ( raw ) ; fallback )
] ;
    Case (
        status = 200 ; "inspect_body" ;
        status ≠ 429 ; "stop_http" ;
        $attempt ≥ 3 ; "stop_attempt_limit" ;
        not IsEmpty ( raw ) and not secondsOnly ; "defer_unparsed_header" ;
        wait > 5 or wait + 10 > $remaining ; "defer_budget" ;
        "retry_after_seconds:" & wait
    )
)

This calculation accepts only integer seconds. Every nonempty noninteger value, including an HTTP-date or malformed text, defers. A production adapter can add a verified HTTP-date parser; it must not interpret those values as zero seconds. The fallback applies only when the header is absent.

Put the decision inside a bounded controller

Workflow pseudocode · bounded foreground GET

Record start time; attempt = 0.
Before each attempt:
    Stop if canceled or the time budget cannot allow another request.
    Increase attempt; clear body and headers.
    Send one GET with timeout no greater than remaining budget.
    Stop on a transfer error or malformed final response.
    If HTTP 200: validate the body and return success or invalid_body.
    If not HTTP 429: stop with the HTTP status.
    If attempt is 3: stop_attempt_limit.
    Parse Retry-After using the provider's contract.
    If date parsing is unavailable or wait exceeds budget: defer.
    Ask whether to retry; Cancel ends the operation.
    Wait in short increments, checking cancellation and elapsed time.
    Recheck the elapsed budget before sending again.

In a foreground FileMaker script, avoid one long uninterruptible wait. A short prompt before a retry and short pause intervals let the user stop. Return a clear outcome such as canceled, deferred, attempt_limit, invalid_body or success. A foreground pause is not a background job scheduler.

Walk through the failure cases

Sandbox sequenceExpected outcome
429 with 3 seconds, then valid 200Two attempts; success after the wait
429, 429, 429Stop after attempt three
429 with 120 secondsDefer without an early retry
429 with HTTP-date and no parserDefer; no guessed local date
401, or 200 with invalid bodyStop; do not loop
Cancel during the waitNo further request

Record actual attempts and elapsed time in a controlled sandbox before connecting a real service. Test that a response from an earlier attempt cannot be reused after a later transfer failure. Keep the API key out of the diagnostic report.

References

Primary references checked during preparation. Provider-specific contracts and native behavior still require review for your implementation.