Deeplinkly

Glossary/Android platform

Digital Asset Links

Definition

Digital Asset Links is an open protocol for publishing verifiable statements in which one digital asset, such as a website, grants a specific permission to another, such as a mobile app identified by its package name and signing certificate fingerprint.

It is routinely confused with the file that implements it. `assetlinks.json` is one serialisation of one statement type; the protocol is broader, and it is what Android App Links verification, Chrome credential sharing, Trusted Web Activities and Instant Apps all sit on top of. Understanding the protocol is what lets you debug the cases where the file looks correct and the permission still is not granted.

The statement, as the protocol defines it

A statement has exactly three parts: the source asset making the claim, the relation being granted, and the target asset receiving it. Everything else is transport.

A statement in its full form
{
  "source": {
    "web": { "site": "https://shop.example.com" }
  },
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "androidApp": {
      "package_name": "com.example.shop",
      "certificate": {
        "sha256_fingerprint":
          "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
      }
    }
  }
}

The file at /.well-known/assetlinks.json is an array of these objects with the source omitted, because the source is implied by where the file is hosted. That omission is the whole reason the protocol and the file get conflated — the file only ever expresses statements *from* the domain serving it.

Asset and relation types the protocol defines.
ElementValuesNotes
Source / target assetweb.site, androidAppA web asset is scheme, host and optional port — no path
delegate_permission/common.handle_all_urlsRelationGrants App Links URL handling — the one almost everyone needs
delegate_permission/common.get_login_credsRelationShares saved credentials between site and app
delegate_permission/common.use_as_originRelationUsed by Trusted Web Activities

A web asset has no path, and no wildcards

https://example.com and https://www.example.com are different assets, as are http and https and different ports. There is no wildcard host syntax. A statement list must be published on every hostname you want verified, which is why www and apex both need the file even when one redirects to the other — and a redirect does not satisfy verification.

Statement lists and the include mechanism

A statement list can delegate to another location rather than enumerating statements inline, which is how large organisations centralise the file across many hostnames.

An include, at /.well-known/assetlinks.json
[{
  "include": "https://central.example.com/.well-known/statements.json"
}]
  • The include target must be served over HTTPS with a valid certificate.
  • Statements in the included list still apply to the *including* host, not to the host serving them.
  • Nesting depth is limited, and a broken include invalidates the whole list rather than degrading to the inline statements.
  • It does not remove the need for the file on each hostname — it only removes the need to maintain the statement content in each place.

Includes trade one failure mode for another

You stop having to redeploy twelve hosts to rotate a fingerprint, and you start having a single URL whose outage breaks App Links verification on all twelve. If you use includes, monitor the include target as a production dependency.

Verifying a statement without a device

Google runs a public API that evaluates the protocol the same way Android does, which is the fastest way to distinguish "my file is wrong" from "my file is right and the device has not re-verified".

Google's Statement List API
curl -s 'https://digitalassetlinks.googleapis.com/v1/statements:list?\
source.web.site=https://shop.example.com&\
relation=delegate_permission/common.handle_all_urls' | jq

# A useful response contains "statements" and an empty "debugString".
# Errors you will actually see:
#   "Unable to fetch" ....... 404, auth wall, or a redirect
#   "Content-Type" .......... served as text/html instead of application/json
#   "malformed" ............. trailing comma, BOM, or a fingerprint with spaces

# And the device-side truth, which the API cannot tell you:
adb shell pm get-app-links com.example.shop
Where a Digital Asset Links problem actually lives.
Statement List API saysDevice saysDiagnosis
Statements returnedverifiedWorking
Statements returnednone or legacy_failureFile is fine; verification has not re-run. Reinstall or re-verify
Statements returnedFingerprint mismatchWrong signing key — likely upload key vs Play App Signing
Unable to fetchnoneHosting problem: redirect, 404 or auth wall
Wrong package_namenoneStatement targets a different app
Empty statementsnoneFile served, but the relation does not match

The overwhelmingly common cause of a valid-looking file that does not verify is the SHA-256 fingerprint: Play App Signing re-signs your app with a key you never handled, so the fingerprint from your local keystore is the wrong one to publish.

AASA and assetlinks generator

Our generator produces a statement list with the correct relation and fingerprint formatting for every hostname you need it on, alongside the iOS equivalent, so the two platforms' association files stay in step.

Open the aasa and assetlinks generator

Frequently asked questions

What is Digital Asset Links?
It is an open protocol for publishing verifiable statements in which one digital asset grants a specific permission to another — most commonly a website declaring that a particular Android app, identified by package name and signing certificate fingerprint, may handle its URLs. Android App Links verification, Chrome credential sharing and Trusted Web Activities are all built on it.
What is the difference between Digital Asset Links and assetlinks.json?
Digital Asset Links is the protocol, defining what a statement is and which relations exist; assetlinks.json is the file format that publishes those statements for a single hostname. The file omits the statement's source because it is implied by the domain serving it, which is why the two are so often conflated.
What relation types does Digital Asset Links support?
The one most developers need is delegate_permission/common.handle_all_urls, which grants an app the right to handle a site's URLs and underpins Android App Links. The protocol also defines delegate_permission/common.get_login_creds for sharing saved credentials between a site and an app, and delegate_permission/common.use_as_origin, used by Trusted Web Activities.
Can a Digital Asset Links statement use a wildcard domain?
No. A web asset is a scheme, host and optional port with no path and no wildcard syntax, so example.com and www.example.com are distinct assets requiring separate statement lists. A redirect between them does not satisfy verification either, which is why both hostnames need the file published directly.
How do I check a Digital Asset Links statement is valid?
Query Google's Statement List API at digitalassetlinks.googleapis.com with your site and the relation you expect, which evaluates the protocol exactly as Android does and returns a debug string naming the failure. Then check the device separately with adb shell pm get-app-links, since a valid statement and an unverified device are different problems with different fixes.

Related terms

  • assetlinks.jsonassetlinks.json is a Digital Asset Links statement file hosted at a domain's /.well-known/ path that authorises a named Android app, identified by package name and signing certificate fingerprint, to handle that domain's URLs.
  • Android App LinkAn Android App Link is an HTTPS URL that opens an Android app directly, without a chooser dialog, because the system has verified through a file on the domain that the app is authorised to handle it.
  • Android App Link VerificationAndroid App Link verification is the process by which Android confirms, at install time, that a domain named in an app's intent filter publishes an assetlinks.json file authorising that app to handle its URLs.
  • SHA-256 Certificate FingerprintA SHA-256 certificate fingerprint is the SHA-256 hash of an app signing certificate, written as 32 colon-separated hexadecimal bytes, used to prove that a specific build was signed by a specific key.
  • Validating assetlinks.jsonValidating assetlinks.json means confirming four separate things: that Android can fetch the file, that it parses as a valid statement list, that it names the fingerprint of the shipped build, and that verification passed on a device.