MMashDiv

Licence attestations

The Licence Attestations console and the switch that makes it count — what enforcement changes, the nine features it gates, how a customer's country is decided, the exact refusals, the store country lists it produces, and why the dashboard warns about it even while it is off.

8 min readUpdated 26 September 2026admin, attestation, licensing, compliance, country, mobile

System → Compliance → Licence Attestations (/admin/system/attestation) records the licences you hold, one row per regulated feature per country: the feature (the console calls it the Module), the country, the entity that holds the licence, the regulator, the licence number and the expiry date. With enforcement switched on, the app serves each feature only to residents of the countries you have recorded it for. The website is never gated by this table, whatever it holds.

Why it exists: Apple and Google allow a crypto app to offer exchange services only where the publisher is licensed, and you publish the app under your own developer account. The table is where you say where that is. The same rows produce the country lists for App Store Connect and Play Console, so what you declare to the stores and what the app serves cannot drift apart. The policy side is in Licences by country.

Enforcement is a switch, and it ships off

Setting Where Default
Enforce Licence Attestations (Mobile App) (attestationEnforcement) System → Platform Settings → Features → Verification (/admin/system/settings) off
  • Off. The app serves every regulated feature exactly as the website does, in every country. Rows you record change nothing in the app; they only feed the store country lists. The console says so above the table: Enforcement is off. These rows are recorded but not applied ...
  • On. A regulated feature reaches an app user only when their country has a live row for that feature. Everything else is refused. An empty table reaches nobody: with enforcement on and no live rows, all nine features below are closed to every app user in every country. Their tiles and order forms stay on screen, locked, with the reason. The notice above the table then reads Enforcement is on. whether or not any licence is recorded, so check the rows themselves, or the dashboard line described below.

Turning enforcement on with an empty or incomplete table hides spot trading, futures, staking, P2P and the rest from every app user it does not cover, immediately. Nothing on the phone says a setting caused it: customers see a feature that is "not offered in your registered country", or are asked for their country. Fill in the table first, then switch it on.

Enforcement is only a gate on the app's requests. The server recognises those by the platform header (see Server settings). The website and the admin are unaffected.

The nine gated features

Module in the console Module ID What the server refuses to an app user without a licence Name in the refusal
Spot trading trade Placing spot orders, including orders on ecosystem (own-chain) pairs and OCO orders Spot trading
P2P trading p2p Creating an offer, and opening a trade against one P2P trading
Staking staking Opening a staking position Staking
Token offerings ico Buying into a token offering Token offerings
Futures futures Placing futures orders Futures
Ecosystem wallets ecosystem Sending funds from an ecosystem wallet to another user's wallet Ecosystem wallets
Copy trading copy-trading Following a trader, and creating or adding funds to a market allocation Copy trading
Merchant payments gateway Registering as a merchant Merchant payments
AI Investment ai-investment Opening an investment AI Investment

The server checks the actions above on every request, so a change to the table applies to them at once. The app has no copy-trading screens, so a country whose only row is for copy trading gets nothing in the app, although it still appears in the store country lists below. Everything else — the wallet, markets, deposits and withdrawals, account, support, blog, market news, the help centre, the store, NFTs, the support assistant, the bot console and the affiliate programme — is not gated by this table.

AI Investment also needs Allow AI Investment & MLM in the Mobile App on, and an app built with STORE_RESTRICTED_MODULES=true. A licence row alone does not bring it to the app. See Server settings.

Whose country counts

A customer's country of residence is:

  1. the country on their approved KYC applications, earliest first; or, if none carries one,
  2. the country on their profile.

It is never taken from an IP address or the phone's language or region, so a VPN or travel does not change it. A customer with neither is refused with a different message, one they can act on (below).

A row is live from the moment it is saved until its expiry date. There is no grace period: on the expiry date it stops serving its feature to that country's residents.

What app users see

The app decides which screens to show from the list it loads at sign-in and at start-up (Server settings). With enforcement on, a gated feature shows one of two messages:

Situation The app shows
Country known, no live licence "Feature is not offered in your registered country, because this platform is not licensed to provide it there. The rest of your account is unaffected."
Country not known "Tell us your country of residence to use Feature. Add it to your profile, or complete identity verification."

The first offers the customer nothing to do, because a licence is not something they can fix. On the Trade screen the second comes with an Add your country button that opens their profile.

If a request reaches the server anyway, it answers with a 403:

  • <Name> is not available in your country in the mobile app. This platform is not licensed to offer it where you live.
  • <Name> needs your country of residence confirmed before it can be used in the mobile app. Complete identity verification, or add your country to your profile, and try again.

<Name> is the name in the last column of the table above.

The app reads the list of available features at sign-in and each time it starts with a saved sign-in, and keeps it. It retries automatically only when that read failed, not when it succeeded with a refusal. So a customer who is signed in when you record a licence sees the feature after signing in again, or after closing the app fully and opening it again. The exception is Add your country on the Trade screen: the app reads the list again when the customer comes back from their profile. Withdrawing a feature is different: the server refuses the gated actions immediately, even while the app still shows the screen.

Recording a licence

Each row is one feature in one country. Add one with the console's create button; the form is titled Record a licence:

Field Required Notes
Module yes The feature this row makes available: one of the nine in the table above. It opens on Spot trading. Its help text carries Apple's separate test for futures and token offerings (guideline 3.1.5(iv): established banks, securities firms, futures commission merchants or other approved financial institutions)
Country yes A picker listing each country by name and ISO code. It does not open empty: it opens on the first country in the list, Afghanistan (AF), so check it before you save. Stored as an ISO 3166-1 code
Entity yes The legal entity that holds the licence, not the brand
Regulator yes
Licence no. yes
Expires yes Must be in the future. A lapsed row stops serving its country immediately; there is no grace period
Notes no

A licence that covers several features is recorded once per feature: add a row for each, with the same entity, regulator, licence number and expiry. A feature with no row for a country is not offered there.

Refusals you can meet when saving, whether recording or editing:

  • Country must be an ISO 3166-1 code, for example GB or GBR. A country name will not match any resident.
  • That expiry date has already passed, so this attestation would serve nobody. Record the current licence's expiry.
  • Expiry date is not a date.
  • "<module>" is not a module this platform serves. An attestation for an unknown module would match nothing and change nothing. Only a direct API call can meet this one, because the Module picker offers nothing else.

Nothing refuses a second row for the same module and country. Both are kept, and the feature is served in that country while either of them is live. So to withdraw a feature from a country, delete every live row for that pair, and when a licence renews, edit its rows rather than adding new ones.

The table lists Module, Country, Expires, Entity, Regulator, Licence no. and Notes. An expiry within 30 days shows as a badge counting the days left, and a past one shows as Lapsed with its date.

Editing and withdrawing

Edit in a row's menu opens Update this licence, with the same fields. An edit is checked exactly as a new row is, so a past expiry is refused here too: a row that has already lapsed cannot be edited without also renewing its date. When a licence renews, edit each of its rows and set the new expiry. Changing the Module or the Country moves the row, as the form warns: Changing the country or the module changes who is served, immediately. The old feature and country stop being served, and the new ones start.

Delete in a row's menu, or on several selected rows at once, withdraws them: that feature stops being served to that country's residents immediately. The row is kept rather than erased. Show Deleted in the toolbar lists withdrawn rows; their Edit is disabled, and their menu offers Restore, which serves the feature there again if the row's expiry has not passed, and Delete Permanently.

The console uses the Geo Restrictions permissions: access.geo.restriction to open it, and view.geo.restriction, create.geo.restriction, edit.geo.restriction and delete.geo.restriction for the actions.

The store country lists

Above the table, under the enforcement notice, Store targeting, derived from the rows above lists:

  • Apple storefronts — for App Store Connect → Pricing and Availability. It is the union across features: the app is listed wherever any part of it can be served.
  • Google Play countries — for Play Console → Countries / regions, and the same evidence again in the Financial features declaration.

Paste these rather than composing them by hand. They read the same rows the gate does. See Country targeting.

Below them, Runtime, per module — what the server will actually serve lists the countries each feature has a live row for, and Served to nobody: names, by module ID, any of the nine with no live row anywhere. Like the dashboard line below, that warning reads only the table and appears whether or not enforcement is on.

The dashboard warning

The admin dashboard's Platform health card has an Operator Licences line. It shows a warning whenever the table is not fully covered: when it is empty, when every licence has lapsed, when any of the nine features has no live licence anywhere, or when a licence expires within 30 days. For an empty table its text begins No licences are recorded, so no regulated module is served to anybody.

The health check reads only the table. With enforcement off, an empty table hides nothing, yet the card still warns and still says no regulated module is served. Ignore that line while enforcement is off. It also counts all nine features whether or not their add-ons are installed, so a feature you never offer keeps it on a warning even with enforcement on.

Not the same as Geo Restrictions

System → Compliance → Geo Restrictions (/admin/system/geo-restriction) decides by the country of the address a request comes from, and it applies to the website and the app alike. Licence attestations are an allow list decided by where the customer lives, for the app only. A customer can pass one and fail the other. See Geo restrictions.

What it deliberately does not do

  • It never gates the website. Web customers in an unlicensed country keep every feature. Use Geo Restrictions or switch the add-on off if you need that.
  • It does not read location. No IP lookup and no device region, by design: a regulator asks where a customer lives, not where their phone is today.
  • It does not treat an empty table as permission. With enforcement on, no rows means no regulated features, not all of them.
  • It is not automatic. Nothing checks your licences with a regulator. The table says what you tell it.