Skip to content

Domain configuration for Apple Pay ​

To enable Apple Pay in your store, you must serve the .well-known/apple-developer-merchantid-domain-association file at the root of every domain where the payment button will be shown.

Required in every integration model

This step is required even if you install the Appmax app via the AppStore (integrated model, with a client_id/external_id per store). What changes between models is only who registers the domain with Apple — you always publish the .well-known file yourself. See Apple Pay payment for the full flow and the distinction between models.


What is this file for? ​

Apple requires this file as part of its domain verification process. It proves that Appmax is authorized to process Apple Pay payments on the domains you inform.

Apple uses this file to validate that the domain is correctly linked to the Merchant ID configured by Appmax. Without it, the "Pay with Apple Pay" button won't work in production — the PaymentSheet won't open, or domain validation fails on every transaction attempt.

The .well-known file is not the Apple Token

The Apple Token is the tokenized card, generated per transaction (see Apple Pay payment). The .well-known file is static, the same on every domain, tied to Appmax's merchantIdentifier — not to the transaction.


1. File content ​

Save the text below to a file named apple-developer-merchantid-domain-association (no extension). It is the same content for every domain in your implementation:

7b2276657273696f6e223a312c227073704964223a2238383637324534354136323336423032384645463731323938334343354338354339334633353231433430374142313338414543354144434641334330334442222c22637265617465644f6e223a313735323630333939333937337d

Copy it exactly as is — with no trailing newline

Apple validates the content byte for byte: one extra space or line break invalidates the domain verification.

This is the most common cause of failure, because virtually every text editor appends a \n on save, and echo does the same. The file is exactly 228 bytes. To create it without a trailing newline, use printf (not echo):

bash
printf '%s' '7b2276657273696f6e...' > apple-developer-merchantid-domain-association

If your editor can't save without the trailing newline, generate the file from the command line.


2. Publish the file on each domain ​

The file must be published at the following path on each domain where Apple Pay will be used, without renaming it:

https://<store-domain>/.well-known/apple-developer-merchantid-domain-association

Examples:

  • https://domain1.com/.well-known/apple-developer-merchantid-domain-association
  • https://domain2.com/.well-known/apple-developer-merchantid-domain-association
  • https://store3.com/.well-known/apple-developer-merchantid-domain-association

3. Verify accessibility ​

After publishing the file, confirm it's accessible:

bash
curl -sI https://<store-domain>/.well-known/apple-developer-merchantid-domain-association

The expected response should contain:

  • HTTP/2 200 OK (or HTTP/1.1 200 OK)
  • Content-Type: text/plain
  • No redirects (neither 301/302 from http to https, nor from www to the root domain or vice versa)

Check the size too — this is what catches the extra newline:

bash
# must print exactly 228
curl -s https://<store-domain>/.well-known/apple-developer-merchantid-domain-association | wc -c

curl -I alone proves nothing

On HEAD requests, many servers don't return Content-Type — so the command can give the impression everything is fine without checking the content at all. Run both: -sI for status and headers, and wc -c for the byte count.

The file has no extension ​

Because the filename has no extension, many servers and CDNs serve it as application/octet-stream, or force it to download as an attachment. Apple requires it to respond as text/plain. The three most common situations:

Nginx — declare the type for that exact path:

nginx
location = /.well-known/apple-developer-merchantid-domain-association {
    default_type text/plain;
    add_header Cache-Control "public, max-age=3600";
}

Apache — in the root .htaccess:

apache
<Files "apple-developer-merchantid-domain-association">
    ForceType text/plain
    Header set Cache-Control "public, max-age=3600"
</Files>

Frameworks (Next.js, Nuxt, Laravel) — when the static folder doesn't let you control the header, serve it from a dedicated route. Next.js (App Router) example:

ts
// app/.well-known/apple-developer-merchantid-domain-association/route.ts
export function GET() {
  return new Response(process.env.APPLE_MERCHANT_ASSOCIATION!, {
    headers: {
      'Content-Type': 'text/plain',
      'Cache-Control': 'public, max-age=3600',
    },
  });
}

Be careful when storing the content in an environment variable: some dashboards append a newline. A .trim() on the value avoids the problem.


4. Registering the domain with Apple ​

Once the file is published and accessible, how the domain gets registered with Apple depends on your integration model:

  • Integrated model (AppStore installation): registration is done by Appmax, via API, as soon as the domain is informed during app installation (the domain_name or domain_names parameter). The file just needs to already be published by then.
  • Direct flow: you register the domain yourself, in the Apple Developer portal, under your own Apple account. Apple validates the .well-known file at registration time.

In both cases, if the store's domain changes, the new domain is treated as a new one — republish the .well-known file on it and register it again (no need to create a new merchant).


Best practices ​

  • HTTPS is mandatory: the domain must respond only over a secure connection.
  • Avoid redirects: the URL must respond directly with a 200 status, without going through www, an http→https redirect, or any other redirect before reaching the file.
  • Don't change the file's content: its internal hash is validated by Apple.
  • Content-Type: serve the file as text/plain.
  • Suggested Cache-Control: public, max-age=3600.

If you have questions, contact Appmax technical support.