For the complete documentation index, see llms.txt. This page is also available as Markdown.

Well-Known URLs (beta)

Some external services will only accept a file at a fixed path on your app hostname, not under /api. The usual case is Apple Pay merchant domain verification:

https://your-app-domain/.well-known/apple-developer-merchantid-domain-association

Other examples: Apple Universal Links (apple-app-site-association), Android App Links (assetlinks.json), or a custom well-known file your PSP gives you. Let's Encrypt acme-challenge and Klai mcp.json are not yours to implement.

From 3.5.69, GET and HEAD to /.well-known/{file} (except the two platform paths below) are rewritten internally to /api/.well-known/{file} and dispatched to the same common hook as the API Callback Endpoint: onApiCall.

When to use this

Implement a FileMaker branch only if:

  • A payment provider (for example Apple Pay via a PSP) requires a domain association file on your Klai hostname, with no redirect.

  • You need another well-known file at the site root (Universal Links, Android Digital Asset Links, and similar).

  • The file content is tenant-specific (different blob per hostname or merchant).

Do not use this as a general website folder, for SSL issuance, or for MCP discovery.

Platform-owned paths

Path
Owner
What you should do

/.well-known/mcp.json

Klai

Leave it alone. Not sent to onApiCall.

/.well-known/acme-challenge/...

Certificate manager

Leave it alone. Not rewritten.

Any other GET/HEAD /.well-known/...

Your app, optional

Handle in onApiCall or let Klai return an empty 404.

POST / PUT / PATCH / DELETE on /.well-known are not rewritten. Direct calls to /api/.well-known/... still use normal /api behavior (no well-known 404 trap).

What Klai does

  1. Rewrites the public URL to /api/.well-known/... (no HTTP redirect).

  2. Calls your common hook onApiCall.

  3. If the script returns an explicit contentType of text, json, xml, or html and a 2xx status, Klai sends that body as-is.

  4. If contentType is missing, the result is empty, the status is 3xx / 401 / 403, or the script errors, Klai responds 404 with an empty text/plain body. It does not return the app HTML, a hash redirect, or a JSON not-found error.

That 404 trap exists because scanners probe many /.well-known paths. A default JSON onApiCall response on those URLs looks like an accidental API.

FileMaker script to edit

Edit the common API callback script:

BetterForms Hooks - onApiCallback - {MyAppCommonHooksetName}

Replace {MyAppCommonHooksetName} with your app's common hook set name (the same name you configured for common hooks).

Add the well-known branch at the top of the developer-editable area, before version/service routing, and exit so existing /api/V1/... routes are unchanged.

The payload Klai already builds for you:

  • params.methodGET (HEAD is dispatched as GET)

  • params.path — array, for Apple Pay: [".well-known", "apple-developer-merchantid-domain-association"]

  • params.wellKnowntrue on rewritten public well-known requests

  • state.subdomain — request host without port

You must set $contentType (for Apple Pay, "text"), $statusCode (200), and $response to the exact file bytes. Do not JSON-encode a text blob. Do not wrap it in HTML.

For every other .well-known path, do not return a 200. Leave $contentType empty so Klai 404s.

The existing footer that writes $$BF_Payload already supports text / html / xml vs JSON. You do not need to change the "do not edit below here" block if it already includes data.contentType, data.response, data.headers, and data.statusCode.

Example branch (Apple Pay file)

This is only the well-known part. Keep your existing dispatcher for /api/V1/....

If your script still parses the path with $pathList from params.route.0 instead of params.path, also match:

GetValue ( $pathList ; 1 ) = ".well-known" and GetValue ( $pathList ; 2 ) = "apple-developer-merchantid-domain-association"

(or values 2 and 3 if your list has a leading empty value). Prefer params.path[0] / params.path[1] when present.

Replace PASTE_APPLE_OR_PSP_DOMAIN_ASSOCIATION_FILE_HERE with the exact domain association file from Apple or your PSP. For a smoke test only, a short unique string is enough to prove pass-through; Apple’s crawler requires the real file, Content-Type: text/plain (or application/octet-stream), HTTPS, 200, and no redirect.

Verify

Last updated

Was this helpful?