@lunch-money/developer-docs 2.11.1-preview.8 → 2.11.2-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/docs/STYLE_GUIDE.md +84 -0
- package/docs/amounts-and-balances.md +5 -5
- package/docs/branding-your-app.md +2 -2
- package/docs/currencies.md +8 -9
- package/docs/getting-started.md +23 -19
- package/docs/introduction.md +7 -6
- package/docs/locales.md +4 -4
- package/docs/oauth/authorization-code.md +80 -0
- package/docs/oauth/concepts.md +46 -0
- package/docs/oauth/development.md +57 -0
- package/docs/oauth/index.md +28 -0
- package/docs/oauth/native-apps.md +26 -0
- package/docs/oauth/oauth-scope-catalog-design.md +370 -0
- package/docs/oauth/register-client.md +52 -0
- package/docs/oauth/review-and-approval.md +69 -0
- package/docs/oauth/scopes.md +104 -0
- package/docs/oauth/security.md +44 -0
- package/docs/oauth/tokens.md +66 -0
- package/docs/oauth/troubleshooting.md +145 -0
- package/docs/pagination.md +43 -44
- package/docs/rate-limiting.md +45 -45
- package/docs/using-with-ai.md +2 -2
- package/manifest.json +101 -0
- package/package.json +3 -3
- package/v2/docs/intro-to-v2.md +12 -12
- package/v2/docs/migration-guide.md +2 -2
- package/v2/docs/version-history.md +5 -1
- package/v2/images/oauth-authorization-flow.svg +32 -0
- package/v2/images/oauth-token-lifecycle.svg +14 -0
- package/v2/spec/lunch-money-api-v2.yaml +349 -12
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# OAuth for native iOS and Android apps
|
|
2
|
+
|
|
3
|
+
Native apps are public clients: they cannot keep a client secret. Use authorization code with PKCE and launch Lunch Money sign-in and consent in a trusted platform authentication browser—not an embedded WebView.
|
|
4
|
+
|
|
5
|
+
## Recommended libraries
|
|
6
|
+
|
|
7
|
+
- iOS and macOS: [`AppAuth-iOS`](https://github.com/openid/AppAuth-iOS), presented through `ASWebAuthenticationSession`.
|
|
8
|
+
- Android: [`AppAuth-Android`](https://github.com/openid/AppAuth-Android), which uses a browser Custom Tab.
|
|
9
|
+
- Bare or non-Expo React Native: [`react-native-app-auth`](https://github.com/FormidableLabs/react-native-app-auth).
|
|
10
|
+
- Expo: Use [`expo-auth-session`](https://docs.expo.dev/versions/latest/sdk/auth-session/) for browser-based OAuth flows.
|
|
11
|
+
|
|
12
|
+
Use Lunch Money's authorization-server discovery document and configure `token_endpoint_auth_method=none`. Send the client ID at the token and revocation endpoints, but never invent or embed a client secret. You do not need to configure authorization-request scopes because the registered client receives its complete fixed set. If your OAuth library sends `scope`, Lunch Money ignores that value and uses the registered set.
|
|
13
|
+
|
|
14
|
+
## Redirects
|
|
15
|
+
|
|
16
|
+
Use a redirect mechanism that returns control to your app and that your platform can bind to it. Claimed Universal Links or Android App Links provide stronger app ownership than a custom URI scheme when correctly configured. A private-use scheme must contain a dot, such as `app.example.demo:/oauth/callback`, and must be protected against interception.
|
|
17
|
+
|
|
18
|
+
Native clients may use an HTTP loopback redirect with `localhost`, `127.0.0.1`, or `[::1]`. The scheme, host, path, and query string must exactly match the registered URI, but the port may differ so the application can bind an ephemeral port at runtime. The exception applies only to loopback redirects for native clients; native HTTPS and private-use scheme redirects must match every component of the registered URI exactly.
|
|
19
|
+
|
|
20
|
+
## Store and renew tokens
|
|
21
|
+
|
|
22
|
+
Store tokens in Keychain on Apple platforms. On Android, use current Keystore-backed storage guidance from your maintained library; do not start new work with deprecated `EncryptedSharedPreferences` APIs. Coordinate refresh-token use, persist replacements, and fall back to interactive authorization after terminal failure.
|
|
23
|
+
|
|
24
|
+
Platform code should delegate protocol validation to the maintained library while your application supplies safe configuration, lifecycle storage, API calls, revocation, and user-facing recovery. Full Lunch Money Swift and Kotlin sample apps are not part of this documentation phase; the upstream AppAuth projects provide maintained platform examples.
|
|
25
|
+
|
|
26
|
+
Next: [Review OAuth security guidance](/oauth/security).
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# OAuth scope catalog design proposal
|
|
2
|
+
|
|
3
|
+
Status: first-cut ENG-616 implementation and inventory, pending consumer review.
|
|
4
|
+
|
|
5
|
+
This document proposes a published, shared source of truth for OAuth scope
|
|
6
|
+
definitions and scope-group presets published with the canonical V2 OpenAPI
|
|
7
|
+
specification. It must still be reconciled with the server OAuth management API
|
|
8
|
+
and database implementation before the catalog is finalized.
|
|
9
|
+
|
|
10
|
+
## Context and decisions
|
|
11
|
+
|
|
12
|
+
The catalog is application code, not persistence. OAuth clients, grants, and
|
|
13
|
+
tokens store scope-name strings. Server, Developer Portal, and authorization UI
|
|
14
|
+
reconcile those strings with their installed catalog version.
|
|
15
|
+
|
|
16
|
+
The detailed OAuth technical specification currently contains an exploratory
|
|
17
|
+
read/write scope list and says write implies read. Those points are superseded
|
|
18
|
+
for this proposal: the final inventory will use independent `:read`, `:create`,
|
|
19
|
+
`:update`, and `:delete` authorities where CRUD applies, and no authority implies
|
|
20
|
+
another. Presets express common combinations without changing authorization
|
|
21
|
+
semantics. Names such as `resource:read` in this document are generic examples,
|
|
22
|
+
not production decisions.
|
|
23
|
+
|
|
24
|
+
This proposal makes these additional decisions:
|
|
25
|
+
|
|
26
|
+
- Keep `OAuthScopeCategory` as `identity | offline | api`. The category
|
|
27
|
+
distinguishes protocol scopes from API permissions. The published inventory
|
|
28
|
+
includes `offline_access` for requesting continued access through refresh
|
|
29
|
+
tokens, but does not publish OpenID Connect identity scopes (`openid`,
|
|
30
|
+
`email`, or `profile`).
|
|
31
|
+
- Add optional `lifecycleNotice` copy for deprecation and retirement warnings.
|
|
32
|
+
It is display metadata, not runtime authorization policy.
|
|
33
|
+
- Reject groups with identical member sets. This is simpler than display
|
|
34
|
+
priorities and makes exact matching unambiguous.
|
|
35
|
+
- Allow unmapped public operations during rollout, but require callers to make
|
|
36
|
+
the choice explicit through an option such as
|
|
37
|
+
`operationIdCoverage: 'allow-unmapped'`. Validation should switch to
|
|
38
|
+
`require-all-mapped` before OAuth scope enforcement is declared complete.
|
|
39
|
+
- Do not encode scope implication, expansion, grant rules, client approval,
|
|
40
|
+
refresh-token policy, or consent policy in the catalog.
|
|
41
|
+
- Use catalog `operationIds` as the authority for V2 endpoint permissions.
|
|
42
|
+
Server decorators must be generated from or validated against this mapping so
|
|
43
|
+
they cannot become a second source of truth.
|
|
44
|
+
- Scope V1 of this catalog to the V2 API only.
|
|
45
|
+
- Map non-CRUD mutations by effect: Plaid and synced-crypto refresh operations
|
|
46
|
+
use `:update`; transaction split/group and their reversals use
|
|
47
|
+
`transactions:update`; balance-history and budget upserts use `:update`.
|
|
48
|
+
- Keep attachment metadata and download access behind
|
|
49
|
+
`transaction_attachments:read`. The other `transaction_attachments:*` scopes
|
|
50
|
+
separately authorize attaching or deleting files.
|
|
51
|
+
|
|
52
|
+
## Package direction
|
|
53
|
+
|
|
54
|
+
The catalog ships as a browser-safe subpath of the existing
|
|
55
|
+
`@lunch-money/v2-api-spec` package so the catalog and V2 `operationId` values are
|
|
56
|
+
versioned atomically:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
src/oauth-scopes/ authored TypeScript catalog and helpers
|
|
60
|
+
oauth-scopes/ compiled published subpath
|
|
61
|
+
test/oauth-scopes/ catalog and V2 operationId validation
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The runtime entry point has no Node-only dependencies and performs no filesystem
|
|
65
|
+
or YAML work. OpenAPI parsing remains in build/test tooling and is not exported
|
|
66
|
+
from the browser-safe `@lunch-money/v2-api-spec/oauth-scopes` subpath.
|
|
67
|
+
|
|
68
|
+
## Public contract
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
type OAuthScopeName = string
|
|
72
|
+
type OAuthScopeCategory = 'identity' | 'offline' | 'api'
|
|
73
|
+
type OAuthScopeLifecycle = 'active' | 'deprecated' | 'retired'
|
|
74
|
+
type KnownOAuthScopeName = 'me:read' | /* ... */ 'budgets:delete'
|
|
75
|
+
|
|
76
|
+
interface OAuthScopeDefinition {
|
|
77
|
+
readonly name: KnownOAuthScopeName
|
|
78
|
+
readonly description: string
|
|
79
|
+
readonly category: OAuthScopeCategory
|
|
80
|
+
readonly operationIds: readonly string[]
|
|
81
|
+
readonly status: OAuthScopeLifecycle
|
|
82
|
+
readonly lifecycleNotice?: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface OAuthScopeGroupDefinition {
|
|
86
|
+
readonly id: string
|
|
87
|
+
readonly name: string
|
|
88
|
+
readonly description: string
|
|
89
|
+
readonly scopes: readonly KnownOAuthScopeName[]
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface OAuthCatalogDefinition {
|
|
93
|
+
readonly scopes: readonly OAuthScopeDefinition[]
|
|
94
|
+
readonly groups: readonly OAuthScopeGroupDefinition[]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The `oauth-scopes` subpath exports:
|
|
99
|
+
|
|
100
|
+
- The interfaces and aliases above, plus result and issue types.
|
|
101
|
+
- `validateOAuthCatalog(definition, options)` returns all structured issues.
|
|
102
|
+
- `getOAuthScopeDefinition(name)` returns a definition or `undefined`.
|
|
103
|
+
- `getOAuthScopeForOperationId(operationId)` returns the authoritative scope
|
|
104
|
+
definition for a V2 operation or `undefined`.
|
|
105
|
+
- `getOAuthScopeGroup(id)` returns a group or `undefined`.
|
|
106
|
+
- `matchOAuthScopeGroup(names)` returns a discriminated matched/no-match
|
|
107
|
+
result.
|
|
108
|
+
- Immutable `oauthCatalog`, `oauthScopes`, and `oauthScopeGroups` exports.
|
|
109
|
+
|
|
110
|
+
`OAuthScopeName` remains `string` for persisted and API-facing input so consumers
|
|
111
|
+
can preserve names newer than their installed library. `KnownOAuthScopeName`
|
|
112
|
+
provides autocomplete and compile-time checking for this catalog version.
|
|
113
|
+
|
|
114
|
+
## Runtime validation and immutability
|
|
115
|
+
|
|
116
|
+
The published definitions and nested arrays are frozen. Private lookup maps
|
|
117
|
+
support explicit failed lookups, and `validateOAuthCatalog` returns structured
|
|
118
|
+
issues for build/test tooling without importing Node-only code into the runtime.
|
|
119
|
+
|
|
120
|
+
Validation checks:
|
|
121
|
+
|
|
122
|
+
- stable lowercase colon-delimited scope names and lowercase underscore group IDs;
|
|
123
|
+
- required descriptions and valid category/lifecycle values;
|
|
124
|
+
- unique scope names and group IDs;
|
|
125
|
+
- non-empty API `operationIds`, except retired tombstones;
|
|
126
|
+
- no operation IDs on identity or offline scopes;
|
|
127
|
+
- duplicate operation IDs within a scope;
|
|
128
|
+
- conflicting operation ownership unless an ID is deliberately allowlisted;
|
|
129
|
+
- non-empty groups with unique members;
|
|
130
|
+
- group members exist and are not retired;
|
|
131
|
+
- offline scopes are excluded from groups;
|
|
132
|
+
- duplicate group member sets are rejected.
|
|
133
|
+
|
|
134
|
+
The runtime has no mutable singleton. Consumers import the frozen catalog or
|
|
135
|
+
construct catalog fixtures in tests. Public helpers return
|
|
136
|
+
`undefined` or discriminated results rather than using non-null assertions.
|
|
137
|
+
|
|
138
|
+
## Protocol scopes
|
|
139
|
+
|
|
140
|
+
`OAuthScopeCategory` includes `identity` and `offline` so validation can
|
|
141
|
+
distinguish protocol scopes from API permissions. The published catalog ships
|
|
142
|
+
`offline_access` alongside its API scopes.
|
|
143
|
+
|
|
144
|
+
Lunch Money's authorization server exposes OAuth 2.1 authorization-server
|
|
145
|
+
metadata, API scopes, and the `offline_access` protocol scope:
|
|
146
|
+
|
|
147
|
+
- no `openid`, `email`, or `profile` identity scopes;
|
|
148
|
+
- active `offline_access` with no V2 operation IDs;
|
|
149
|
+
- no ID tokens, UserInfo, or public signing keys.
|
|
150
|
+
|
|
151
|
+
`offline_access` represents a request for continued access when the user is not
|
|
152
|
+
actively using the app. The authorization server still owns the decision to
|
|
153
|
+
issue a refresh token based on the requested scope, client capability, consent,
|
|
154
|
+
and server policy.
|
|
155
|
+
|
|
156
|
+
No resource group may contain an offline-category scope. Identity scopes are
|
|
157
|
+
not categorically banned from a group; any future identity-oriented preset
|
|
158
|
+
should be an explicit catalog decision.
|
|
159
|
+
|
|
160
|
+
## Lifecycle and consumer behavior
|
|
161
|
+
|
|
162
|
+
Lifecycle is code-only metadata:
|
|
163
|
+
|
|
164
|
+
| Status | New assignment/request | Existing full replacement | Token issuance | Recognition/display |
|
|
165
|
+
| --- | --- | --- | --- | --- |
|
|
166
|
+
| `active` | allowed | allowed | allowed | yes |
|
|
167
|
+
| `deprecated` | rejected if newly introduced | preserved if already assigned | allowed for existing grants per server rollout | yes, with warning |
|
|
168
|
+
| `retired` | rejected | rejected | rejected | yes, as tombstone |
|
|
169
|
+
|
|
170
|
+
The library provides state and copy; consumers enforce transitions in context.
|
|
171
|
+
For example, only the server can know whether a deprecated name is newly added
|
|
172
|
+
or preserved during a full replacement. Lifecycle must never be copied into a
|
|
173
|
+
client row. A stored name absent from the installed catalog is `unknown`, not
|
|
174
|
+
implicitly retired.
|
|
175
|
+
|
|
176
|
+
Recommended reconciliation status for management APIs:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
type ScopeConfigurationStatus = 'valid' | 'needs_attention'
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`needs_attention` applies when stored configuration contains an unknown or
|
|
183
|
+
retired scope. A deprecated-only configuration remains valid but returns warning
|
|
184
|
+
metadata. The exact API response shape is a server-design coordination point.
|
|
185
|
+
|
|
186
|
+
## Compatibility baseline and change classes
|
|
187
|
+
|
|
188
|
+
After the first production catalog is approved, check in a canonical JSON
|
|
189
|
+
snapshot at `compatibility/catalog-baseline.json`. Future CI compares source
|
|
190
|
+
against this file and does not fetch npm. The baseline updates only as part of a
|
|
191
|
+
reviewed release and must represent the most recently published authority map.
|
|
192
|
+
Canonical ordering makes diffs stable.
|
|
193
|
+
|
|
194
|
+
Compatibility checks detect deletion, category changes/name reuse, authority
|
|
195
|
+
broadening, operation remapping, lifecycle changes, and group membership/removal.
|
|
196
|
+
The regular catalog validator separately detects broken references and duplicate
|
|
197
|
+
ownership.
|
|
198
|
+
|
|
199
|
+
Change classification:
|
|
200
|
+
|
|
201
|
+
- Patch-compatible: descriptions, names shown to users, and lifecycle notice
|
|
202
|
+
copy change without changing authority.
|
|
203
|
+
- Minor-compatible: a new scope or group is added. New scopes must not be added
|
|
204
|
+
to an existing group in the same classification; that is a membership change.
|
|
205
|
+
- Migration-requiring: deprecation, retirement, removal of authority from a
|
|
206
|
+
scope, any group membership change, or group removal.
|
|
207
|
+
- Breaking/forbidden without explicit migration: deleting a known scope rather
|
|
208
|
+
than retaining a tombstone, changing its category, reusing its name for a
|
|
209
|
+
different authority, or adding operation IDs to an existing scope.
|
|
210
|
+
|
|
211
|
+
Name reuse cannot be detected from names alone. Preserving every old definition
|
|
212
|
+
as a retired tombstone plus comparing category and operation ownership provides
|
|
213
|
+
the deterministic safeguard. Review policy must treat meaning changes not
|
|
214
|
+
visible in structured data as forbidden. A future `authorityFingerprint` could
|
|
215
|
+
make that stronger if V1 endpoints or non-operation authorities join the model.
|
|
216
|
+
|
|
217
|
+
A future comparison helper should treat a retired tombstone with removed
|
|
218
|
+
operation IDs as migration-requiring rather than breaking. Tombstones should
|
|
219
|
+
remain small while retaining enough description to diagnose old persisted names.
|
|
220
|
+
|
|
221
|
+
## Exact-set group matching
|
|
222
|
+
|
|
223
|
+
Groups are UI presets only. A selected group becomes its concrete member names;
|
|
224
|
+
the group ID is neither sent as authority nor persisted in client, grant, code,
|
|
225
|
+
or token configuration.
|
|
226
|
+
|
|
227
|
+
Matching performs these steps:
|
|
228
|
+
|
|
229
|
+
1. Reject a candidate containing an unknown or duplicate scope name with a
|
|
230
|
+
distinct no-match reason.
|
|
231
|
+
2. Canonically sort the complete candidate set.
|
|
232
|
+
3. Compare it with each complete canonical group member set.
|
|
233
|
+
4. Return exactly one matched group or `no_match`.
|
|
234
|
+
|
|
235
|
+
An additional recognized scope prevents a match. The helper never searches for
|
|
236
|
+
subsets, decomposes a set into overlapping groups, or infers historical preset
|
|
237
|
+
selection. A changed preset causes old clients to fall back to individual scope
|
|
238
|
+
display. Duplicate member sets are invalid, so ambiguity cannot enter a valid
|
|
239
|
+
catalog.
|
|
240
|
+
|
|
241
|
+
Product analytics may separately record that a preset was selected, but that
|
|
242
|
+
event is historical telemetry and has no authorization meaning.
|
|
243
|
+
|
|
244
|
+
## OpenAPI operationId validation
|
|
245
|
+
|
|
246
|
+
The V2 YAML is authoritative for public operation IDs. Node-only test tooling
|
|
247
|
+
parses `v2/spec/lunch-money-api-v2.yaml`, traverses HTTP operations, and returns a set
|
|
248
|
+
while rejecting missing or duplicate IDs. Catalog validation then:
|
|
249
|
+
|
|
250
|
+
- verifies every API-category operation ID exists in the spec;
|
|
251
|
+
- rejects conflicting ownership unless a deliberate `sharedOperationIds`
|
|
252
|
+
allowlist contains the ID;
|
|
253
|
+
- permits identity/offline scopes to have no operation IDs;
|
|
254
|
+
- reports stale and unknown IDs with catalog paths;
|
|
255
|
+
- optionally reports every unmapped public operation.
|
|
256
|
+
|
|
257
|
+
The validation modes are:
|
|
258
|
+
|
|
259
|
+
- `allow-unmapped`: rollout mode; catalog entries must be correct, but endpoints
|
|
260
|
+
can remain unmapped while enforcement is staged.
|
|
261
|
+
- `require-all-mapped`: completion mode; every public operation must have an
|
|
262
|
+
owner or be removed from the public spec.
|
|
263
|
+
|
|
264
|
+
If some public operations are intentionally unscoped (for example a protocol or
|
|
265
|
+
health endpoint represented in the same document), add a named exclusion list
|
|
266
|
+
with a justification per entry rather than silently omitting them. Shared
|
|
267
|
+
operation ownership should likewise be rare and explicit. The tooling never
|
|
268
|
+
modifies the OpenAPI document.
|
|
269
|
+
|
|
270
|
+
V1 endpoints are deliberately outside this catalog. Do not overload V2
|
|
271
|
+
operation IDs with invented V1 values.
|
|
272
|
+
|
|
273
|
+
## Consumer integration
|
|
274
|
+
|
|
275
|
+
### Server
|
|
276
|
+
|
|
277
|
+
- Pin an exact catalog package version in deploys.
|
|
278
|
+
- Persist only scope-name strings.
|
|
279
|
+
- Validate requested/client/grant scopes against the installed catalog.
|
|
280
|
+
- Reject newly introduced deprecated scopes and all retired/unknown scopes.
|
|
281
|
+
- Preserve deprecated scopes on an existing client's full replacement only
|
|
282
|
+
when they were already present.
|
|
283
|
+
- Enforce operation authority from the catalog without implication.
|
|
284
|
+
- Treat `offline_access` as a request for refresh-token-backed access while
|
|
285
|
+
retaining the server-owned issuance decision based on client capability and
|
|
286
|
+
consent policy.
|
|
287
|
+
- Return unknown names so operators and UIs can diagnose drift.
|
|
288
|
+
|
|
289
|
+
### Developer Portal
|
|
290
|
+
|
|
291
|
+
- Render active definitions and groups from the package.
|
|
292
|
+
- Render deprecated existing selections with `lifecycleNotice`; do not offer
|
|
293
|
+
them for new selection.
|
|
294
|
+
- Render retired/unknown stored names as needing attention.
|
|
295
|
+
- Submit concrete scope names, never group IDs.
|
|
296
|
+
- Use exact matching only as a display convenience.
|
|
297
|
+
|
|
298
|
+
### Authorization/consent UI
|
|
299
|
+
|
|
300
|
+
- Resolve the server-approved requested names using the same pinned catalog
|
|
301
|
+
compatibility range.
|
|
302
|
+
- Display groups only on exact match; otherwise display individual definitions.
|
|
303
|
+
- Call out API mutation scopes from structured category and scope data, while
|
|
304
|
+
keeping the actual consent/issuance decision server-owned.
|
|
305
|
+
- Fail closed on unknown or retired requested names.
|
|
306
|
+
|
|
307
|
+
Consumers must not independently copy definitions or group membership. During a
|
|
308
|
+
rolling deploy, the server is authoritative: it must not send a scope newly
|
|
309
|
+
introduced by a catalog version that the UI deployment cannot understand. Pinning
|
|
310
|
+
one exact version across a coordinated release is preferred.
|
|
311
|
+
|
|
312
|
+
## Versioning and publishing
|
|
313
|
+
|
|
314
|
+
Publish the catalog with `@lunch-money/v2-api-spec`. A spec-package version pins
|
|
315
|
+
both the YAML and its catalog, preventing operation mappings from drifting.
|
|
316
|
+
Use the change classes above when selecting the package version:
|
|
317
|
+
|
|
318
|
+
- patch for copy-only and implementation fixes;
|
|
319
|
+
- minor for additive catalog entries or backward-compatible API additions;
|
|
320
|
+
- major only with an approved migration for a public contract break;
|
|
321
|
+
- migration-requiring catalog changes may still use minor versions before 1.0,
|
|
322
|
+
but release notes and server coordination are mandatory.
|
|
323
|
+
|
|
324
|
+
Start with prereleases until all three consumers validate the contract. Existing
|
|
325
|
+
spec-package release tooling builds the subpath and verifies package contents
|
|
326
|
+
before publishing.
|
|
327
|
+
|
|
328
|
+
Each server release should pin an exact package version. Portal and consent UI
|
|
329
|
+
should use the same version or a declared compatibility window validated in CI.
|
|
330
|
+
Never depend on an npm `latest` lookup at application startup.
|
|
331
|
+
|
|
332
|
+
## Reconciliation required with the server design
|
|
333
|
+
|
|
334
|
+
Before this proposal becomes final, compare these exact artifacts:
|
|
335
|
+
|
|
336
|
+
1. Scope string grammar, especially resource separators and full CRUD verbs.
|
|
337
|
+
2. `identity | offline | api` categories and `active | deprecated | retired`
|
|
338
|
+
lifecycle values.
|
|
339
|
+
3. Group schema and the decision to reject duplicate member sets.
|
|
340
|
+
4. The discriminated exact-match result and unknown-scope handling.
|
|
341
|
+
5. `scope_configuration_status` semantics, warning/error details, and whether
|
|
342
|
+
deprecated-only configuration remains `valid`.
|
|
343
|
+
6. Management API request/response shapes: concrete scope names only, with no
|
|
344
|
+
persisted group authority.
|
|
345
|
+
7. Full-replacement rules for preserving deprecated scopes.
|
|
346
|
+
8. `offline_access` request and refresh-token issuance semantics, and
|
|
347
|
+
confirmation that OIDC identity scopes are rejected.
|
|
348
|
+
9. How server `tsoa` operation requirements consume catalog mappings without
|
|
349
|
+
creating a second source of truth.
|
|
350
|
+
10. Exact package versions supported by server, Portal, and consent deployments,
|
|
351
|
+
including rolling-deploy behavior.
|
|
352
|
+
11. The server database's representation of unknown names and its mapping to
|
|
353
|
+
`valid | needs_attention`.
|
|
354
|
+
|
|
355
|
+
The server OpenAPI management schemas should remain string-based so adding a
|
|
356
|
+
catalog name does not require an API schema revision.
|
|
357
|
+
|
|
358
|
+
## Recommended ENG-616 follow-up
|
|
359
|
+
|
|
360
|
+
1. Reconcile this proposal with the server agent's OpenAPI and database artifacts.
|
|
361
|
+
2. Confirm the V2 operation coverage/exclusion policy.
|
|
362
|
+
3. Review and approve the first-cut full-CRUD inventory and descriptions; do not
|
|
363
|
+
derive authority from the older read/write draft.
|
|
364
|
+
4. Check in the first canonical compatibility baseline with that inventory.
|
|
365
|
+
5. Add CI that builds/tests the spec package and validates the production catalog
|
|
366
|
+
against the local V2 YAML in the chosen coverage mode.
|
|
367
|
+
6. Select a prerelease version, verify the tarball, and test it through local
|
|
368
|
+
`file:` or packed dependencies in all consumers.
|
|
369
|
+
7. Publish only after server, Portal, and consent UI agree on the contract and
|
|
370
|
+
rolling-version policy.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Register an OAuth client
|
|
2
|
+
|
|
3
|
+
Before you add OAuth to your application code, register an OAuth client with Lunch Money. The client identifies your application during authorization and tells Lunch Money who is requesting access, where to return the user, and which permissions the application needs.
|
|
4
|
+
|
|
5
|
+
[Register a new OAuth client](/oauth/applications/new) in the Developer Portal when you are ready to begin.
|
|
6
|
+
|
|
7
|
+
> [!NOTE] Development access is owner-only
|
|
8
|
+
> A newly registered client starts in development. Only the Lunch Money user who owns it can authorize it until the client has been reviewed and approved.
|
|
9
|
+
|
|
10
|
+
## Plan the permissions
|
|
11
|
+
|
|
12
|
+
List the Lunch Money features your application will provide, then use the [scope catalog](/oauth/scopes) to choose the smallest complete set of permissions those features require. Select `offline_access` only if the application needs to continue making API requests after the initial access token expires and while the user is away.
|
|
13
|
+
|
|
14
|
+
Scopes cannot be changed after registration. While you are developing your application, creating a replacement client is inexpensive, so let the scope set evolve as you learn what the application needs. Aim to have the application's core functionality—and its required permissions—settled before you submit the client for review.
|
|
15
|
+
|
|
16
|
+
If functionality added after launch needs a scope that is not already registered, you must register a replacement client with the new complete scope set and have it reviewed before rollout. Existing authorizations do not transfer to the replacement client, so users must authorize it before they can use the new functionality. Treat that reauthorization as part of the feature launch: explain what the application can now do with their Lunch Money data and invite them to authorize the replacement client when they want to enable it.
|
|
17
|
+
|
|
18
|
+
## Choose the client type
|
|
19
|
+
|
|
20
|
+
Select the type based on whether your application code can keep a client secret secure:
|
|
21
|
+
|
|
22
|
+
- **Confidential web client:** Choose this when a trusted server can store a client secret, including for applications that are not traditional websites but use a centralized server.
|
|
23
|
+
- **Native or public client:** Choose this for standalone applications installed on a user-controlled device. These clients use PKCE without a client secret. Review the [native application guidance](/oauth/native-apps) before choosing redirects for this type.
|
|
24
|
+
|
|
25
|
+
The client type cannot be changed after registration. See [OAuth concepts](/oauth/concepts#client-types-and-credentials) for more detail about the two types.
|
|
26
|
+
|
|
27
|
+
## Register redirect URIs
|
|
28
|
+
|
|
29
|
+
A redirect URI tells Lunch Money where to return the user after authorization. Register every callback address your application will use. Confidential web clients must match every component of a registered URI, including its scheme, host, port, path, and query string. Native-client loopback redirects use the same exact matching except that the ephemeral port is ignored.
|
|
30
|
+
|
|
31
|
+
Web applications normally use an HTTPS callback. If you need a callback for local development, review the [loopback guidance](/oauth/development#local-loopback-callbacks) before registering one. Mobile and desktop applications may use a private-use scheme containing a dot, such as `app.example.demo:/oauth/callback`, or a verified HTTPS link accepted by the Developer Portal.
|
|
32
|
+
|
|
33
|
+
## Register the OAuth client
|
|
34
|
+
|
|
35
|
+
Open the [new OAuth client form](/oauth/applications/new) in the Developer Portal. Then:
|
|
36
|
+
|
|
37
|
+
1. Describe the application so Lunch Money users can understand who built it and what it does.
|
|
38
|
+
2. Provide a monitored support email where users can reach you if authorization fails.
|
|
39
|
+
3. Choose its client type.
|
|
40
|
+
4. Add at least one redirect URI.
|
|
41
|
+
5. Select the planned scopes.
|
|
42
|
+
6. Accept the current Lunch Money API Terms of Use and select **Register OAuth client**.
|
|
43
|
+
|
|
44
|
+
After registration, record the client ID in your application configuration. A client ID identifies the registration but is not a secret.
|
|
45
|
+
|
|
46
|
+
If you registered a **Confidential web client**, create a client secret from its details page. Lunch Money shows the secret value only once. Copy it immediately into a secret manager or protected server configuration; it cannot be retrieved later. Never commit it or expose it in browser or mobile code.
|
|
47
|
+
|
|
48
|
+
A confidential web client can have multiple active secrets. This allows you to introduce a replacement secret, update and verify the deployed application, and then revoke the old secret without interrupting authorization. See [OAuth security guidance](/oauth/security#operate-credentials-safely) when planning ongoing rotation.
|
|
49
|
+
|
|
50
|
+
You now have the client settings needed to connect your application to Lunch Money.
|
|
51
|
+
|
|
52
|
+
Next: [Implement authorization](/oauth/authorization-code).
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# OAuth client review and approval
|
|
2
|
+
|
|
3
|
+
Every new OAuth client starts in development, where only its owner can authorize it. This gives you time to build and test the application without making an unfinished integration available to other Lunch Money users.
|
|
4
|
+
|
|
5
|
+
When the application is ready, submit its client for review in the Developer Portal. A Lunch Money employee reviews the application information, requested permissions, redirect configuration, and other readiness requirements. Approval moves the client to `active`, allowing other Lunch Money users to authorize the application.
|
|
6
|
+
|
|
7
|
+
## Lifecycle states
|
|
8
|
+
|
|
9
|
+
| State | What it means | Owner action |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `development` | The client has not been submitted for review; only its owner can authorize it | Configure and test, then request review. |
|
|
12
|
+
| `pending_review` | Review has been requested and is waiting for or receiving review; review-critical fields are frozen | Continue owner testing or cancel the request. |
|
|
13
|
+
| `active` | The review was approved; other Lunch Money users may authorize the application | Operate within the approved identity and scope set. |
|
|
14
|
+
| `rejected` | Changes were requested | Read feedback, revise editable configuration, and resubmit. |
|
|
15
|
+
| `disabled` | Lunch Money disabled the client; its owner is notified, authorization is unavailable, and existing grants no longer work | Review the reason provided and contact developer support when appropriate. |
|
|
16
|
+
|
|
17
|
+
Deleted clients disappear from the owner's Developer Portal.
|
|
18
|
+
|
|
19
|
+
## Prepare for review
|
|
20
|
+
|
|
21
|
+
Submitting a client for review is how you make your application authorizable by Lunch Money users other than yourself. Registration already requires basic information, including a support email, but review requires a complete, user-facing application profile and production-ready configuration.
|
|
22
|
+
|
|
23
|
+
Before requesting review, make sure the client has:
|
|
24
|
+
|
|
25
|
+
- an application description, developer name, and logo so users can identify the application and who created it;
|
|
26
|
+
- a monitored support email where users and Lunch Money can reach you;
|
|
27
|
+
- a publicly accessible homepage URL where users can learn about the application;
|
|
28
|
+
- a publicly accessible privacy policy URL explaining how the application handles user data;
|
|
29
|
+
- at least one eligible redirect URI—a confidential web client needs a non-loopback production HTTPS redirect, while a native client may use a private-use scheme or loopback redirect;
|
|
30
|
+
- a recognized, supported scope set and an explanation of why the application needs each permission; and
|
|
31
|
+
- acceptance of the current Lunch Money API Terms of Use.
|
|
32
|
+
|
|
33
|
+
The privacy policy must be available at a direct, stable public URL and explain how the application collects, uses, stores, shares, and deletes user data. A published privacy-policy page in a public source-code repository can satisfy this requirement. An in-app page that requires installation or sign-in, or a link to source code without a clear privacy policy, does not.
|
|
34
|
+
|
|
35
|
+
Fully test the client before submission. A confidential web client also needs at least one active, non-expired secret; a native or public client does not.
|
|
36
|
+
|
|
37
|
+
Explain which features use each requested permission, how that access benefits users, and why narrower scopes are insufficient. If the client includes `offline_access`, explain why the integration must operate while the user is absent. You may also provide documentation, source-code, and demonstration URLs or context about changes made after earlier feedback.
|
|
38
|
+
|
|
39
|
+
Open-source applications are welcome. If your source code is public, include the repository URL in the review request's additional context. It can help the reviewer understand how your application uses Lunch Money data and the permissions it requests. Publishing source code is optional and is not required for approval.
|
|
40
|
+
|
|
41
|
+
A confidential web client may retain owner-only loopback callbacks alongside its production HTTPS callback, but it still needs a non-loopback production HTTPS redirect before review.
|
|
42
|
+
|
|
43
|
+
### Native applications
|
|
44
|
+
|
|
45
|
+
You do not need to create a standalone marketing website for a native application. Its public Apple App Store or Google Play listing can serve as the homepage if it clearly explains what the application does and identifies the developer. A public pre-release listing, project page, or README in a public source-code repository can also work.
|
|
46
|
+
|
|
47
|
+
If you provide a pre-release listing or beta-testing link, use the review request's additional context to explain how to access it. Include any required opt-in steps, supported platforms or devices, and other information the reviewer needs to evaluate the application. Do not include passwords, client secrets, tokens, or other credentials.
|
|
48
|
+
|
|
49
|
+
Native clients may be reviewed with loopback or private-use scheme redirects.
|
|
50
|
+
|
|
51
|
+
## Submit, cancel, or revise
|
|
52
|
+
|
|
53
|
+
Submitting the request moves the client to `pending_review` and temporarily freezes review-critical fields. Reviews are usually completed within a couple of business days. You can continue developing and testing the application as the client owner while you wait. If you need to change a frozen field, cancel the request to return the client to `development`, make the change, and submit it again.
|
|
54
|
+
|
|
55
|
+
Lunch Money emails you when the review is complete. You can also check the current status and review history on the client's page in the Developer Portal.
|
|
56
|
+
|
|
57
|
+
## If review is denied
|
|
58
|
+
|
|
59
|
+
If the review is denied, the Developer Portal shows feedback explaining what needs to change. Update the client's editable configuration and submit a new review request. Editing the client alone does not resubmit it or clear the `rejected` status.
|
|
60
|
+
|
|
61
|
+
There is no review comment thread, so use the new request's additional context to explain how you addressed the feedback. The Portal keeps the earlier request in the client's review history.
|
|
62
|
+
|
|
63
|
+
## After approval
|
|
64
|
+
|
|
65
|
+
An `active` client can be authorized by other users. Reviewed identity fields, redirect configuration, and the registered scope set remain frozen after approval. Client-secret rotation and revocation remain available subject to lifecycle and security checks.
|
|
66
|
+
|
|
67
|
+
For an exceptional identity or configuration change, contact [developer support](mailto:developer-support@lunchmoney.app). A scope change always requires a replacement client and user reauthorization.
|
|
68
|
+
|
|
69
|
+
Next: [Review the security checklist](/oauth/security).
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# OAuth scopes
|
|
2
|
+
|
|
3
|
+
Choose the smallest complete set of permissions your application needs. This page is generated from the published `@lunch-money/v2-api-spec/oauth-scopes` catalog; do not edit it by hand.
|
|
4
|
+
|
|
5
|
+
> [!NOTE] Scopes are fixed when you create a client
|
|
6
|
+
> Authorization requests omit `scope`. To change permissions later, create and review a replacement client, update your integration, and ask every user to authorize it.
|
|
7
|
+
|
|
8
|
+
## Scope groups
|
|
9
|
+
|
|
10
|
+
Groups are selection shortcuts, not extra permissions. A group expands to the exact scopes listed below.
|
|
11
|
+
|
|
12
|
+
### Read only
|
|
13
|
+
|
|
14
|
+
View all supported Lunch Money data without changing it
|
|
15
|
+
|
|
16
|
+
[`me:read`](#scope-me-read), [`summary:read`](#scope-summary-read), [`categories:read`](#scope-categories-read), [`crypto_manual:read`](#scope-crypto-manual-read), [`crypto_synced:read`](#scope-crypto-synced-read), [`balance_history:read`](#scope-balance-history-read), [`manual_accounts:read`](#scope-manual-accounts-read), [`plaid_accounts:read`](#scope-plaid-accounts-read), [`transactions:read`](#scope-transactions-read), [`transaction_attachments:read`](#scope-transaction-attachments-read), [`tags:read`](#scope-tags-read), [`recurring_items:read`](#scope-recurring-items-read), [`budgets:read`](#scope-budgets-read)
|
|
17
|
+
|
|
18
|
+
### Transactions
|
|
19
|
+
|
|
20
|
+
Import, export, organize, and manage transactions and their attachments
|
|
21
|
+
|
|
22
|
+
[`transactions:read`](#scope-transactions-read), [`transactions:create`](#scope-transactions-create), [`transactions:update`](#scope-transactions-update), [`transactions:delete`](#scope-transactions-delete), [`transaction_attachments:read`](#scope-transaction-attachments-read), [`transaction_attachments:create`](#scope-transaction-attachments-create), [`transaction_attachments:delete`](#scope-transaction-attachments-delete), [`categories:read`](#scope-categories-read), [`tags:read`](#scope-tags-read), [`manual_accounts:read`](#scope-manual-accounts-read), [`plaid_accounts:read`](#scope-plaid-accounts-read), [`recurring_items:read`](#scope-recurring-items-read)
|
|
23
|
+
|
|
24
|
+
### Budgeting
|
|
25
|
+
|
|
26
|
+
Analyze and manage budgets, categories, and tags
|
|
27
|
+
|
|
28
|
+
[`summary:read`](#scope-summary-read), [`budgets:read`](#scope-budgets-read), [`budgets:update`](#scope-budgets-update), [`budgets:delete`](#scope-budgets-delete), [`categories:read`](#scope-categories-read), [`categories:create`](#scope-categories-create), [`categories:update`](#scope-categories-update), [`categories:delete`](#scope-categories-delete), [`tags:read`](#scope-tags-read), [`tags:create`](#scope-tags-create), [`tags:update`](#scope-tags-update), [`tags:delete`](#scope-tags-delete), [`recurring_items:read`](#scope-recurring-items-read)
|
|
29
|
+
|
|
30
|
+
### Accounts
|
|
31
|
+
|
|
32
|
+
Manage accounts, balances, and balance history
|
|
33
|
+
|
|
34
|
+
[`manual_accounts:read`](#scope-manual-accounts-read), [`manual_accounts:create`](#scope-manual-accounts-create), [`manual_accounts:update`](#scope-manual-accounts-update), [`manual_accounts:delete`](#scope-manual-accounts-delete), [`plaid_accounts:read`](#scope-plaid-accounts-read), [`plaid_accounts:update`](#scope-plaid-accounts-update), [`crypto_manual:read`](#scope-crypto-manual-read), [`crypto_manual:create`](#scope-crypto-manual-create), [`crypto_manual:update`](#scope-crypto-manual-update), [`crypto_manual:delete`](#scope-crypto-manual-delete), [`crypto_synced:read`](#scope-crypto-synced-read), [`crypto_synced:update`](#scope-crypto-synced-update), [`balance_history:read`](#scope-balance-history-read), [`balance_history:update`](#scope-balance-history-update), [`balance_history:delete`](#scope-balance-history-delete)
|
|
35
|
+
|
|
36
|
+
### Organize
|
|
37
|
+
|
|
38
|
+
Manage categories and tags used to organize transactions
|
|
39
|
+
|
|
40
|
+
[`categories:read`](#scope-categories-read), [`categories:create`](#scope-categories-create), [`categories:update`](#scope-categories-update), [`categories:delete`](#scope-categories-delete), [`tags:read`](#scope-tags-read), [`tags:create`](#scope-tags-create), [`tags:update`](#scope-tags-update), [`tags:delete`](#scope-tags-delete), [`recurring_items:read`](#scope-recurring-items-read)
|
|
41
|
+
|
|
42
|
+
### Full access
|
|
43
|
+
|
|
44
|
+
View and manage all supported Lunch Money data
|
|
45
|
+
|
|
46
|
+
[`me:read`](#scope-me-read), [`me:update`](#scope-me-update), [`summary:read`](#scope-summary-read), [`categories:read`](#scope-categories-read), [`categories:create`](#scope-categories-create), [`categories:update`](#scope-categories-update), [`categories:delete`](#scope-categories-delete), [`crypto_manual:read`](#scope-crypto-manual-read), [`crypto_manual:create`](#scope-crypto-manual-create), [`crypto_manual:update`](#scope-crypto-manual-update), [`crypto_manual:delete`](#scope-crypto-manual-delete), [`crypto_synced:read`](#scope-crypto-synced-read), [`crypto_synced:update`](#scope-crypto-synced-update), [`balance_history:read`](#scope-balance-history-read), [`balance_history:update`](#scope-balance-history-update), [`balance_history:delete`](#scope-balance-history-delete), [`manual_accounts:read`](#scope-manual-accounts-read), [`manual_accounts:create`](#scope-manual-accounts-create), [`manual_accounts:update`](#scope-manual-accounts-update), [`manual_accounts:delete`](#scope-manual-accounts-delete), [`plaid_accounts:read`](#scope-plaid-accounts-read), [`plaid_accounts:update`](#scope-plaid-accounts-update), [`transactions:read`](#scope-transactions-read), [`transactions:create`](#scope-transactions-create), [`transactions:update`](#scope-transactions-update), [`transactions:delete`](#scope-transactions-delete), [`transaction_attachments:read`](#scope-transaction-attachments-read), [`transaction_attachments:create`](#scope-transaction-attachments-create), [`transaction_attachments:delete`](#scope-transaction-attachments-delete), [`tags:read`](#scope-tags-read), [`tags:create`](#scope-tags-create), [`tags:update`](#scope-tags-update), [`tags:delete`](#scope-tags-delete), [`recurring_items:read`](#scope-recurring-items-read), [`budgets:read`](#scope-budgets-read), [`budgets:update`](#scope-budgets-update), [`budgets:delete`](#scope-budgets-delete)
|
|
47
|
+
|
|
48
|
+
## Resource scopes
|
|
49
|
+
|
|
50
|
+
| Scope | What it allows | V2 operations |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| <a id="scope-me-read"></a>`me:read` | View your Lunch Money identity and account, user, and budget settings | `getMe`, `getAccountSettings`, `getUserSettings`, `getUserAccountSettings` |
|
|
53
|
+
| <a id="scope-me-update"></a>`me:update` | Update your Lunch Money account, user, and budget settings | `updateAccountSettings`, `updateUserSettings`, `updateUserAccountSettings` |
|
|
54
|
+
| <a id="scope-summary-read"></a>`summary:read` | View your budget summary | `getBudgetSummary` |
|
|
55
|
+
| <a id="scope-categories-read"></a>`categories:read` | View categories and category groups | `getAllCategories`, `getCategoryById` |
|
|
56
|
+
| <a id="scope-categories-create"></a>`categories:create` | Create categories and category groups | `createCategory` |
|
|
57
|
+
| <a id="scope-categories-update"></a>`categories:update` | Update categories and category groups | `updateCategory` |
|
|
58
|
+
| <a id="scope-categories-delete"></a>`categories:delete` | Delete categories and category groups | `deleteCategory` |
|
|
59
|
+
| <a id="scope-crypto-manual-read"></a>`crypto_manual:read` | View supported cryptocurrencies and manually managed cryptocurrency balances | `getAllCryptocurrencies`, `getAllCryptoManual`, `getCryptoManualById` |
|
|
60
|
+
| <a id="scope-crypto-manual-create"></a>`crypto_manual:create` | Add supported cryptocurrencies and create manually managed cryptocurrency balances | `createCryptocurrency`, `createCryptoManual` |
|
|
61
|
+
| <a id="scope-crypto-manual-update"></a>`crypto_manual:update` | Update manually managed cryptocurrency balances | `updateCryptoManual` |
|
|
62
|
+
| <a id="scope-crypto-manual-delete"></a>`crypto_manual:delete` | Delete manually managed cryptocurrency balances | `deleteCryptoManual` |
|
|
63
|
+
| <a id="scope-crypto-synced-read"></a>`crypto_synced:read` | View synced cryptocurrency accounts and balances | `getAllCryptoSynced`, `getCryptoSyncedById`, `getCryptoSyncedBalanceBySymbol` |
|
|
64
|
+
| <a id="scope-crypto-synced-update"></a>`crypto_synced:update` | Refresh balances for synced cryptocurrency accounts | `refreshCryptoSynced` |
|
|
65
|
+
| <a id="scope-balance-history-read"></a>`balance_history:read` | View balance history for accounts and synced cryptocurrency balances | `getBalanceHistory`, `getBalanceHistoryForAccount`, `getBalanceHistoryForCryptoSynced` |
|
|
66
|
+
| <a id="scope-balance-history-update"></a>`balance_history:update` | Create or update balance history and details for deleted accounts | `upsertBalanceHistoryForAccount`, `upsertBalanceHistoryForCryptoSynced`, `updateBalanceHistoryDetails` |
|
|
67
|
+
| <a id="scope-balance-history-delete"></a>`balance_history:delete` | Delete balance history for accounts and synced cryptocurrency balances | `deleteBalanceHistoryForAccount`, `deleteBalanceHistoryForCryptoSynced`, `deleteBalanceHistoryEntry` |
|
|
68
|
+
| <a id="scope-manual-accounts-read"></a>`manual_accounts:read` | View manually managed accounts | `getAllManualAccounts`, `getManualAccountById` |
|
|
69
|
+
| <a id="scope-manual-accounts-create"></a>`manual_accounts:create` | Create manually managed accounts | `createManualAccount` |
|
|
70
|
+
| <a id="scope-manual-accounts-update"></a>`manual_accounts:update` | Update manually managed accounts | `updateManualAccount` |
|
|
71
|
+
| <a id="scope-manual-accounts-delete"></a>`manual_accounts:delete` | Delete manually managed accounts | `deleteManualAccount` |
|
|
72
|
+
| <a id="scope-plaid-accounts-read"></a>`plaid_accounts:read` | View accounts connected through Plaid | `getAllPlaidAccounts`, `getPlaidAccountById` |
|
|
73
|
+
| <a id="scope-plaid-accounts-update"></a>`plaid_accounts:update` | Request a Plaid account refresh, which may import new transactions | `triggerPlaidAccountFetch` |
|
|
74
|
+
| <a id="scope-transactions-read"></a>`transactions:read` | View transactions, including split and group information | `getAllTransactions`, `getTransactionById` |
|
|
75
|
+
| <a id="scope-transactions-create"></a>`transactions:create` | Create transactions | `createNewTransactions` |
|
|
76
|
+
| <a id="scope-transactions-update"></a>`transactions:update` | Update, split, unsplit, group, and ungroup transactions | `updateTransactions`, `updateTransaction`, `groupTransactions`, `ungroupTransactions`, `splitTransaction`, `unsplitTransaction` |
|
|
77
|
+
| <a id="scope-transactions-delete"></a>`transactions:delete` | Delete transactions | `deleteTransactions`, `deleteTransactionById` |
|
|
78
|
+
| <a id="scope-transaction-attachments-read"></a>`transaction_attachments:read` | View transaction attachment metadata and get download access to attachments | `getTransactionAttachmentUrl` |
|
|
79
|
+
| <a id="scope-transaction-attachments-create"></a>`transaction_attachments:create` | Attach files to transactions | `attachFileToTransaction` |
|
|
80
|
+
| <a id="scope-transaction-attachments-delete"></a>`transaction_attachments:delete` | Delete transaction attachments | `deleteTransactionAttachment` |
|
|
81
|
+
| <a id="scope-tags-read"></a>`tags:read` | View tags | `getAllTags`, `getTagById` |
|
|
82
|
+
| <a id="scope-tags-create"></a>`tags:create` | Create tags | `createTag` |
|
|
83
|
+
| <a id="scope-tags-update"></a>`tags:update` | Update tags | `updateTag` |
|
|
84
|
+
| <a id="scope-tags-delete"></a>`tags:delete` | Delete tags | `deleteTag` |
|
|
85
|
+
| <a id="scope-recurring-items-read"></a>`recurring_items:read` | View recurring items | `getAllRecurring`, `getRecurringById` |
|
|
86
|
+
| <a id="scope-budgets-read"></a>`budgets:read` | View budget period settings | `getBudgetSettings` |
|
|
87
|
+
| <a id="scope-budgets-update"></a>`budgets:update` | Create or update budget amounts | `upsertBudget` |
|
|
88
|
+
| <a id="scope-budgets-delete"></a>`budgets:delete` | Delete budget amounts | `deleteBudget` |
|
|
89
|
+
|
|
90
|
+
## Continued access
|
|
91
|
+
|
|
92
|
+
<a id="scope-offline-access"></a>
|
|
93
|
+
|
|
94
|
+
### `offline_access`
|
|
95
|
+
|
|
96
|
+
Allow this app to maintain access without asking you to sign in and authorize it again
|
|
97
|
+
|
|
98
|
+
`offline_access` is not permission to a V2 resource. It allows an eligible token response to include a longer-lived, finite refresh token. Your application must still request every resource scope it needs when the client is created.
|
|
99
|
+
|
|
100
|
+
## Find the scope for an endpoint
|
|
101
|
+
|
|
102
|
+
The [V2 API reference](/v2/docs) displays the required OAuth scope for each operation. Scope requirements come from the same catalog and standard OpenAPI security metadata used to generate this page.
|
|
103
|
+
|
|
104
|
+
Next: [Implement the authorization-code flow](/oauth/authorization-code).
|