Geocompliance

Geocompliance enforces geographic restrictions on money movement. Frame Sonar — running in your client via frame-js or a mobile SDK — captures the account holder's location continuously; at charge time, Frame evaluates that location against your platform's geofences and blocks the transaction before it reaches the network if the account holder is inside a restricted territory.

Geocompliance is a background service. There's no hosted UX for the account holder, no consent screen, no "verify your location" step. The capability sits on the account; enforcement happens at the moment a charge is created.

When to use it

Request geo_compliance on accounts where regulatory or platform policy requires keeping money movement out of specific jurisdictions:

  • Gaming and gambling platforms blocking states where their license doesn't apply.
  • Cannabis or alcohol platforms restricted to licensed jurisdictions.
  • Sanctions-adjacent compliance where a buyer's physical location matters more than their billing address.
  • Any product where "where the account holder physically is right now" is a policy input.

If the policy concerns the destination of money (a payout to a sanctioned country, for example), that's a different shape — geocompliance evaluates the account holder's current location, not destination economics.

How it works

Location capture

When your client initializes Frame Sonar (automatically on Frame.init(), or whatever the mobile-SDK equivalent is), Sonar runs in the background and captures location signals. The captured location is bound to a Sonar session scoped to that client instance and associated with the account.

VPN detection runs alongside location capture. A detected VPN doesn't block account creation but does flag the session — and a flagged session can be blocked at transaction time depending on your platform's policy.

Evaluation at transaction time

When you create a charge for an account with geo_compliance active, Frame:

  1. Pulls the account's most recent Sonar session.
  2. Evaluates the location against your platform's geofences (Frame-provided defaults plus any custom ones configured for your account).
  3. Returns a binary outcome — proceed or block — before the charge hits the network.

The GET/v1/accounts/{account_id}/geo_compliance endpoint returns the current evaluation as a status + reason pair:

statusreason (typical values)Charge outcome
clearCharge proceeds
blockedrestricted_territory, vpn_detectedCharge rejected
unknownno_location_dataCharge rejected (fails closed)

You can pre-query an account's evaluation state if you want to check before initiating a charge — surface a "this product isn't available in your region" message in your UI rather than letting the charge attempt fail.

Charge-time block error codes

When a charge is blocked at transfer-create time, the failure carries a distinct error code (separate from the reason field on the evaluation endpoint above):

  • geo_compliance_blocked — the account holder's location is inside a restricted geofence.
  • geo_compliance_vpn_detected — a VPN was detected on the session, and your platform's policy treats VPN-flagged sessions as restricted.
  • sonar_session_required — no Sonar session exists for this account (the client didn't initialize Sonar, or the session expired).

Geofences

A geofence is a geographic boundary plus a set of rules. Frame ships with platform-level defaults covering common regulatory cases (state-level boundaries for gaming, etc.) that apply automatically once geocompliance is enabled on your platform.

Two geofence shapes:

  • Polygon — state, regional, or arbitrarily shaped boundaries.
  • Circle — radius-based restrictions around a point.

Each geofence has one or more rules with a trigger and an action:

TriggerDescription
enterBlock when the account holder crosses into the area
exitBlock when the account holder leaves the area
dwellBlock after the account holder has been inside the area for a configured duration

Custom geofences (different shapes, different rules, different jurisdictions than the defaults) are configured per-platform — talk to Frame about your specific needs.

Enabling geocompliance

Geocompliance is platform-gated — it has to be enabled on your account by Frame before you can request the geo_compliance capability on individual accounts. Reach out to Frame support to enable it. Once enabled:

  1. Make sure Frame Sonar is initialized in your client (frame-js, iOS, Android — whichever your platform uses).
  2. Add geo_compliance to the capabilities array when creating accounts.
  3. Frame handles the rest at charge time.

Requesting geo_compliance on a platform where it hasn't been enabled returns a 422 validation error with a message indicating geocompliance is not enabled for the merchant.

Platform scope

Frame Sonar runs in frame-js (browser) and in the native iOS / Android SDKs. The signal quality and refresh cadence depend on the client SDK and the user's device permissions — browser-based Sonar uses standard geolocation APIs; mobile SDKs use platform-native location services with permission prompts you handle in your app. V1 docs focus on the web flow; the mobile-SDK integration shape lives in the respective SDK docs.

Gotchas

Symptom: every transaction on a geocompliance-enabled account is blocked with sonar_session_required. Why: the client never initialized Frame Sonar before the charge call. Fix: confirm Frame.init() runs on page load (or whatever the mobile-SDK equivalent is) and that the user hasn't blocked geolocation permissions. Geocompliance fails closed — no session, no transaction.

Symptom: a charge succeeds in your test environment but fails in production with geo_compliance_vpn_detected. Why: your test setup is geographically clean; production users are more likely to be on corporate VPNs, mobile-VPN privacy apps, or networks Sonar flags. Fix: decide your platform's VPN policy explicitly — either accept the false positive rate, or work with Frame support to whitelist specific session patterns.

Symptom: an account holder physically moves into a restricted territory mid-session and the next charge succeeds. Why: the session's last location capture may pre-date the move. Sonar refreshes location, but there's a window between capture events. Fix: this is generally acceptable from a compliance standpoint — geofencing operates on captured snapshots, not real-time tracking. If your use case demands stricter freshness, contact Frame support.

Reference

For the geocompliance evaluation endpoint, see GET/v1/accounts/{account_id}/geo_compliance.