Skip to main content
reference 4 min read

Scopes

The permission catalog — what each scope grants, restrictions, and downscoping on refresh.

A scope is a permission token your integration asks the user (or themselves, for server-to-server) to grant. Each access token carries the list of granted scopes; each endpoint requires one.

Request multiple scopes by joining them with a single space:

scope=flights:read flights:write profile:read

Catalog

ScopeWhat it grantsStatus
flights:readList a user's flights; read scoring, metadata, summarised analysis; download the raw IGC file (planned endpoint)Stable
flights:writeUpload IGC files to the user's logbookStable
flights:deletePermanently remove flightsStable, destructive
profile:readRead display name, club, CIVL id, public-profile flagStable
profile:emailRead the account email address (in addition to profile:read)Stable
profile:writeUpdate display name, club affiliation, license info, and safety contactsStable, write
community:readRead public community data (takeoff sites, leaderboards, thermal hotspots, the screen gallery)Stable
tasks:readRead the pilot's competition tasks and waypoint collections; browse the shared task libraryStable
tasks:writeSave competition tasks and waypoint collections to the pilot's accountStable, write
screens:readRead the pilot's instrument screen layoutsStable
screens:writeCreate, update, delete and publish the pilot's screen layoutsStable, write
airspace:readRead airspace region descriptors and temporary activationsStable
live:writePublish live positions, mint share links, and raise take-off / landing / emergency notificationsStable, write

Restrictions

  • Pending applications can only obtain read-only scopes (flights:read, profile:read, profile:email, community:read, tasks:read, screens:read, airspace:read), and only for their own owner. Every write scope above therefore needs the application approved before it can be exercised even once. Once an admin promotes the app to approved, it can request the destructive scopes from arbitrary users.

  • API keys cannot grant flights:delete. The risk profile of a long-lived key bundled into a personal script is too high for a destructive scope — use OAuth for delete flows.

  • Public clients (SPAs, mobile apps with no server-side secret) must use PKCE and cannot use client_credentials. They CAN request any scope via Authorization Code, subject to user consent.

Notes on the newer scopes

tasks:* covers waypoints too. A competition task and a waypoint collection are the same thing to a pilot — the set of places this flight is about — and an integration that imports one almost always wants the other. Splitting them would have produced a consent screen with two lines that nobody could tell apart.

screens:*, not cockpits:*. The resource is a flight-instrument screen layout. we-fly's own /cockpit pages are its statistics dashboard, an unrelated feature that already owns that word — see the instrument guide.

live:write covers notifications as well as positions. From the pilot's point of view they are one act: telling we-fly where they are so that somebody else can be told. A separate notify:write would have asked them to reason about a distinction that only exists in our routing table.

Airspace activations are read with airspace:read but delivered per pilot. The scope gets you the endpoint; the data additionally requires the pilot to have connected their own autorouter account, because the underlying NOTAM source may not be redistributed under a shared one. A pilot without that connection gets 200 with an empty list and source.available: false — never a bare empty array, which would read as "no active airspace here".

Asking for fewer scopes later (downscoping)

When you refresh a token (grant_type=refresh_token) you may pass a scope parameter narrower than the original grant. The returned access+refresh pair will carry only the narrowed set, and the new refresh token cannot widen back. This is useful when you've decided your integration no longer needs (say) flights:write and you want to remove that capability without forcing a new user-consent screen.

You cannot widen a scope on refresh — the server will return invalid_scope. Get the user to re-authorise instead.

When a user authorises an app, they see a list of requested scopes with a short human description. The same scope catalog is applied identically on the server and the consent UI — partners cannot override the description.

Dangerous scopes (write, delete) are visually flagged.