Short answer: The apple-app-site-association (AASA) file tells iOS which of your app's URLs should open the app. It lives at https://<domain>/.well-known/apple-app-site-association, has no file extension, must be served over HTTPS with no redirects, and lists app IDs and URL patterns under applinks. Test yours with curl -I on the file URL and swcutil on a Mac.
What is an apple-app-site-association file?
apple-app-site-association (AASA): a JSON file hosted on your domain that lists which iOS apps may open which URLs on that domain as universal links, and which apps may use the domain for shared web credentials and App Clips.
iOS reads it alongside your app's Associated Domains entitlement. Both halves must agree: the entitlement claims the domain, and the file on the domain names the app. Since iOS 14 and macOS 11, devices fetch the file from an Apple-managed CDN, which in turn fetches it from your server.
How is the file structured?
The root is an object. For universal links, the key that matters is applinks, which holds a details array. Each entry pairs a list of apps with the URL patterns they handle.
{
"applinks": {
"defaults": { "caseSensitive": false },
"details": [
{
"appIDs": ["ABCDE12345.com.example.app", "ABCDE12345.com.example.app2"],
"components": [
{ "#": "no_universal_links", "exclude": true, "comment": "Opt-out fragment" },
{ "/": "/buy/*" },
{ "/": "/help/website/*", "exclude": true },
{ "/": "/help/*", "?": { "articleNumber": "????" } }
]
}
]
},
"webcredentials": { "apps": ["ABCDE12345.com.example.app"] },
"appclips": { "apps": ["ABCDE12345.com.example.MyApp.Clip"] }
}
appIDs: each value is<Application Identifier Prefix>.<Bundle Identifier>, for exampleABCDE12345.com.example.app.components: an array of pattern objects, checked in order.defaults: global matching settings for every rule on the domain (iOS 14 and later).substitutionVariables: named lists of strings that patterns can reuse. Apple provides built-ins such aslangandregion.webcredentialsandappclips: use anappsarray. Apple notes the details dictionary "only applies to the applinks service type".
Components versus legacy paths
Apple has used two formats for rules. The current one is appIDs plus components, introduced with iOS 13 according to Apple's documentation metadata. The legacy one is appID (a string) plus paths (an array of strings, with NOT as an exclusion prefix).
| Key | Matches | Default |
|---|---|---|
/ | URL path | * |
? | Query, as a pattern or a dictionary of parameters | * |
# | Fragment | * |
exclude | Stops matching and keeps the URL on the web | false |
caseSensitive | Case of the pattern | true |
percentEncoded | Whether patterns are percent-encoded | true |
comment | Ignored text for notes | none |
Apple's advice on the two formats: "Please avoid mixing formats. Doing so may result in unexpected behavior." Use one format per file.
How does iOS decide which rule applies?
iOS checks rules in array order and stops at the first match. Apple says: "The order that you use to specify the patterns in the array determines the order the system follows when looking for a match. The first match wins."
- Put
excluderules above the broader rules they carve out. - A URL must match every key a rule specifies.
{"/":"abc","?":"def"}matches/abc?defbut not/abcalone. *matches zero or more characters,?matches exactly one, and?*matches one or more.
Run sudo swcutil verify on a Mac to see whether a URL matches your rules. If the wrong rule wins, see path not matched.
Where do you host the file?
- At
https://<fully qualified domain>/.well-known/apple-app-site-association, with no extension. - Over HTTPS "with a valid certificate and with no redirects".
- On every domain in the entitlement. Each subdomain "must serve its own apple-app-site-association file", although
applinks:*.example.comuses the file at the apex. - Open to "all geographical locations, from any IP address" and all user agents, so Apple's CDN can fetch it.
- As plain JSON. Apple's archived guide describes
application/json, which is also what Apple's CDN returns. - Under 128 KB uncompressed, the limit in Apple's archived documentation for iOS 9.3.1 and later.
Apple's archived Handoff guide mentions a fallback to the domain root, but current documentation only describes /.well-known/, and developer mode requires it. Host it there.
How do you test the file?
Test the file content and how your server delivers it:
curl -I https://example.com/.well-known/apple-app-site-associationfor a 200 and no redirect, thencurl -von the same URL to see the JSON body.curl -A "MyAgent-Bot/*" https://example.com/.well-known/apple-app-site-association, Apple's suggested user-agent check.- On a Mac:
sudo swcutil dl -d example.com, thensudo swcutil verify -d example.com -j apple-app-site-association -u https://example.com/buy/1. - On a device with Developer Mode on: Settings > Developer > Universal Links > Diagnostics.
- Paste a link into Notes, tap it, then long-press it to see both the app and browser options.
Apple's CDN fetches the file within 24 hours and devices check about once a week after install, so reinstall the app on test devices after each change, or use applinks:example.com?mode=developer while iterating. For the app side, see the universal links setup guide.