Scopes

A scope is one question your app is allowed to ask. Users grant them individually, so assume you'll often hold a subset of what you requested.

Request the narrowest set that makes your product work. Every extra scope is another line in the connect dialog, another thing to justify in your developer application, and another reason for someone to decline.

Choosing between the tiers

The question to ask yourself is: would an answer do?

If you're drawing a live map with a moving dot, you need coordinates and the sensitive tier is honest. If you're deciding whether to unlock a door, send a notification, tag a photo, or verify a transaction, an answer does — and the standard tier is both easier to get approved and cheaper to hold.

Some common mistakes:

  • Reaching for location.latest.read to check proximity. Use location.verify.zone. You get inside/outside without ever holding a position, and without the sensitive-tier friction.
  • Reaching for location.history.read to build a timeline. Use location.visits.read. You get "arrived at the gym 9:15, left 10:40", which is what a timeline actually displays.
  • Polling current-place every thirty seconds. Register a rule instead. Polling burns your budget and still tells you late; a rule tells you when it happens.

Scopes that depend on places

Five scopes are about the user's own named places — location.place.current, location.place.presence, location.visits.read, location.lookup.place, and location.rules.place for standing rules.

For these, the user picks which places you may ask about when they connect you, and can change that later without re-minting your token. Holding the scope doesn't mean seeing every place: a place that wasn't shared with you is invisible, and indistinguishable from one that doesn't exist.

Design for the case where a user shares nothing. current-place will answer no_place forever, and that's a legitimate configuration, not an error.

Scope changes over time

Your app's declared scopes can be narrowed by an admin during review. Because the effective set is the intersection of the user's grant and your app's current declaration, that takes effect immediately on live tokens — a call you made yesterday may 403 today.

Handle 403 by degrading the feature, not by retrying.

Scope reference

Every scope, the endpoints it unlocks, and its tier.

ScopeTierGrants
location.verify.zone
POST /v1/answers/verify-zone
StandardAsk whether you are inside a zone the app names (yes/no only)
location.place.current
GET /v1/answers/current-place
StandardAsk which of your shared places you are at right now
location.place.presence
GET /v1/answers/places/:place_id/presence
StandardAsk whether you are at one specific shared place (yes/no only)
location.visits.read
GET /v1/visits
StandardRead your visit history as place labels and time windows
location.lookup.place
GET /v1/lookup/place?at=
StandardLook up which shared place you were at, at a specific moment
location.rules.place
POST/GET/DELETE /v1/rules/place
StandardGet notified when you arrive at or leave a shared place
location.rules.zone
POST/GET/DELETE /v1/rules/zone
StandardGet notified when you enter or leave a zone the app names
location.latest.read
GET /v1/locations/latest
SensitiveRead your exact current coordinates
location.history.read
GET /v1/locations/timerange
SensitiveRead your exact coordinates over time ranges
location.lookup
GET /v1/locations/lookup?at=
SensitiveRead your exact coordinates at a specific moment