@lunch-money/developer-docs 2.11.2-preview.3 → 2.11.2-preview.5

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.
@@ -3,7 +3,7 @@
3
3
  Building a tool, plugin, or integration on top of Lunch Money? Use the official **Powered by Lunch Money** badge to credit the connection clearly — without implying that your app *is* Lunch Money.
4
4
 
5
5
  <a href="https://lunchmoney.app/assets/images/media-kit/powered-by-lunch-money-badge.png" download="powered-by-lunch-money-badge.png" target="_blank" rel="noopener noreferrer" title="Download Powered by Lunch Money badge">
6
- <img src="/v2/images/powered-by-lunch-money-badge.png" alt="Powered by Lunch Money badge" />
6
+ <img src="/v2/images/powered-by-lunch-money-badge.png" alt="Powered by Lunch Money badge" width="320" />
7
7
  </a>
8
8
 
9
9
  > [!TIP]
@@ -27,10 +27,10 @@ For a client in development, register an HTTP redirect using a supported loopbac
27
27
 
28
28
  You may choose any available port, but the complete redirect URI sent during authorization must match the registered value exactly. `localhost` and `127.0.0.1` are different hosts, so register the form your application sends. Non-loopback HTTP hosts, embedded credentials, and URI fragments are not supported.
29
29
 
30
- The user's browser—not Lunch Money's server—connects to the loopback listener. Keep PKCE and `state` protections in place just as you would for a hosted callback. Before requesting review, also register the HTTPS callback used by the deployed application; the loopback URI can remain available for local testing.
30
+ The user's browser—not Lunch Money's server—connects to the loopback listener. Keep PKCE and `state` protections in place just as you would for a hosted callback. Before requesting review, also register the HTTPS callback used by the deployed application; the loopback URI can remain available for local testing. After approval, you can add or keep a loopback redirect as long as that production HTTPS callback remains. See [after approval](/oauth/review-and-approval#after-approval).
31
31
 
32
32
  > [!NOTE] Test an approved client with your development team
33
- > After a client is approved, other team members can continue developing and testing the application's Lunch Money functionality. If the approved client has a loopback redirect registered, each developer who can run the application locally may authorize access to their own Lunch Money budgeting account. The client ID is public, but developers working on a confidential web client also need access to its client secret through your team's secure credential-management process. Do not share access tokens or refresh tokens between developers.
33
+ > After a client is approved, other team members can continue developing and testing the application's Lunch Money functionality. You can add or keep a loopback redirect on the approved client as long as the production HTTPS callback remains. If a loopback redirect is registered, each developer who can run the application locally may authorize access to their own Lunch Money budgeting account. The client ID is public, but developers working on a confidential web client also need access to its client secret through your team's secure credential-management process. Do not share access tokens or refresh tokens between developers.
34
34
 
35
35
  ## Repeat or reset authorization
36
36
 
@@ -15,7 +15,7 @@ Use Lunch Money's authorization-server discovery document and configure `token_e
15
15
 
16
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
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.
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. The loopback hosts are not interchangeable: a client registered with `http://127.0.0.1/cb` cannot authorize with `http://localhost:4000/cb` or `http://[::1]:4000/cb`, so register the host your app actually binds to.
19
19
 
20
20
  ## Store and renew tokens
21
21
 
@@ -32,6 +32,10 @@ A redirect URI tells Lunch Money where to return the user after authorization. R
32
32
 
33
33
  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.
34
34
 
35
+ After the client is approved, you can add or replace redirect URIs in the Developer Portal without submitting another initial review. An approved confidential web client must keep a production HTTPS callback. See [after approval](/oauth/review-and-approval#after-approval).
36
+
37
+ Each client can have up to 10 redirect URIs, and each URI can be up to 2,048 characters. If you reach the limit, remove a callback the application no longer uses before adding another.
38
+
35
39
  ## Register the OAuth client
36
40
 
37
41
  Open the [new OAuth client form](/oauth/applications/new) in the Developer Portal. Then:
@@ -43,11 +47,13 @@ Open the [new OAuth client form](/oauth/applications/new) in the Developer Porta
43
47
  5. Select the planned scopes.
44
48
  6. Accept the current Lunch Money API Terms of Use and select **Register OAuth client**.
45
49
 
50
+ You can own up to 25 non-deleted OAuth clients. If you reach the limit, delete a client you no longer use before registering another.
51
+
46
52
  After registration, record the client ID in your application configuration. A client ID identifies the registration but is not a secret.
47
53
 
48
54
  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.
49
55
 
50
- 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.
56
+ A confidential web client can have up to three non-revoked secrets. This allows you to introduce a replacement secret, update and verify the deployed application, and then revoke the old secret without interrupting authorization. Expired secrets still count toward the limit until you revoke them. Revoking an obsolete secret frees a slot, and revoked secrets no longer appear in the client's secret list. See [OAuth security guidance](/oauth/security#operate-credentials-safely) when planning ongoing rotation.
51
57
 
52
58
  You now have the client settings needed to connect your application to Lunch Money.
53
59
 
@@ -10,7 +10,7 @@ When the application is ready, submit its client for review in the Developer Por
10
10
  | --- | --- | --- |
11
11
  | `development` | The client has not been submitted for review; only its owner can authorize it | Configure and test, then request review. |
12
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. |
13
+ | `active` | The review was approved; other Lunch Money users may authorize the application | Keep configuration current; identity updates reach users after Lunch Money reviews them. |
14
14
  | `rejected` | Changes were requested | Read feedback, revise editable configuration, and resubmit. |
15
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
16
 
@@ -52,6 +52,10 @@ Native clients may be reviewed with loopback or private-use scheme redirects.
52
52
 
53
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
54
 
55
+ You can make up to five initial review submissions across all your clients in a rolling 24-hour period. Cancelled submissions and submissions made again after a rejection still count. Deleting a client does not remove its submissions from the window. Reviews opened automatically after you update the identity of an active client do not count toward this limit.
56
+
57
+ If you reach the limit, the Developer Portal tells you when you can submit again. Wait until that time before retrying; cancelling, deleting, or replacing a client does not reset the window.
58
+
55
59
  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
60
 
57
61
  ## If review is denied
@@ -62,8 +66,12 @@ There is no review comment thread, so use the new request's additional context t
62
66
 
63
67
  ## After approval
64
68
 
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.
69
+ An `active` client can be authorized by other users. Keep its configuration current in the Developer Portal. You do not need to contact Lunch Money to rename the application, move hosting, or update a support address.
70
+
71
+ Changes save immediately, and the client stays `active`. Redirect URIs, support email, description, and developer name take effect as soon as you save them. An approved confidential web client must keep at least one public HTTPS redirect.
72
+
73
+ Name, logo, homepage URL, and privacy policy URL also save immediately, but Lunch Money users continue to see the last approved identity on the consent screen and Connected Apps page until Lunch Money reviews the update. The Developer Portal shows that as an identity update in review; it is not a return to `rejected`, and existing authorizations keep working.
66
74
 
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.
75
+ Client-secret rotation and revocation remain available subject to lifecycle and security checks. Scopes and client type cannot be changed after registration. A scope change requires a replacement client and user reauthorization.
68
76
 
69
77
  Next: [Review the security checklist](/oauth/security).
@@ -19,25 +19,25 @@ View all supported Lunch Money data without changing it
19
19
 
20
20
  Import, export, organize, and manage transactions and their attachments
21
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)
22
+ [`me:read`](#scope-me-read), [`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
23
 
24
24
  ### Budgeting
25
25
 
26
26
  Analyze and manage budgets, categories, and tags
27
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)
28
+ [`me:read`](#scope-me-read), [`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
29
 
30
30
  ### Accounts
31
31
 
32
32
  Manage accounts, balances, and balance history
33
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)
34
+ [`me:read`](#scope-me-read), [`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
35
 
36
36
  ### Organize
37
37
 
38
38
  Manage categories and tags used to organize transactions
39
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)
40
+ [`me:read`](#scope-me-read), [`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
41
 
42
42
  ### Full access
43
43
 
@@ -47,7 +47,7 @@ Choose only the resource scopes needed for expected features. Add `offline_acces
47
47
 
48
48
  ## Operate credentials safely
49
49
 
50
- Rotate client secrets on a schedule appropriate for your application's risk and immediately when one may have been exposed. Use overlapping active secrets during a controlled rotation: create the replacement, deploy and verify it, and then revoke the old secret. Coordinate refreshes so two workers do not replay the same rotating token, and atomically persist every complete replacement credential set. Production storage needs database transactions, distributed per-connection locking, recovery when persistence fails, multi-instance coordination, and tenant isolation. Make logout or disconnect invalidate continuing refresh access as well as clear local state.
50
+ Rotate client secrets on a schedule appropriate for your application's risk and immediately when one may have been exposed. A client can have up to three non-revoked secrets, so confirm that it has room before starting a rotation. Expired secrets still count toward this limit until you revoke them. Use overlapping active secrets during a controlled rotation: create the replacement, deploy and verify it, and then revoke the old secret. Coordinate refreshes so two workers do not replay the same rotating token, and atomically persist every complete replacement credential set. Production storage needs database transactions, distributed per-connection locking, recovery when persistence fails, multi-instance coordination, and tenant isolation. Make logout or disconnect invalidate continuing refresh access as well as clear local state.
51
51
 
52
52
  If a credential may have been exposed, stop using it, revoke it, rotate the relevant client secret, review logs without copying secret values, and require reauthorization when the grant can no longer be trusted.
53
53
 
@@ -135,6 +135,18 @@ The `scope` parameter names every scope the endpoint requires, including any the
135
135
 
136
136
  Adding `scope` to an authorization URL cannot upgrade or narrow a grant. Lunch Money ignores the requested value and uses the client's complete registered scope set. To change scopes, create a replacement client, test all functionality, complete any required review, update the deployed client ID and credentials, and send every existing user through authorization again.
137
137
 
138
+ ## Client-management failures
139
+
140
+ The Developer Portal can return structured errors when you register clients, create client secrets, or submit a client for review. These errors use the Lunch Money response format, not OAuth protocol errors such as `invalid_grant`.
141
+
142
+ | Status and code | Meaning | What to do |
143
+ | --- | --- | --- |
144
+ | `422 quota_exceeded`, field `clients` | You already own 25 non-deleted OAuth clients. | Delete a client you no longer use before registering another. |
145
+ | `422 quota_exceeded`, field `secrets` | The client already has three non-revoked secrets. Expired secrets still count. | Revoke an obsolete or expired secret before creating another. |
146
+ | `429 review_quota_exceeded` | You have made five initial review submissions across your clients in the rolling 24-hour window. | Wait until the time shown in the Developer Portal before submitting again. API clients should also respect the `Retry-After` response header. |
147
+
148
+ Cancelled submissions, rejected-client resubmissions, and submissions for clients later deleted still count toward the review limit. Reviews opened automatically after an active client's identity changes do not count.
149
+
138
150
  ## Local callback failures
139
151
 
140
152
  For local development, use a supported loopback host: `localhost`, `127.0.0.1`, or `[::1]`. Matching depends on the client type:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunch-money/developer-docs",
3
- "version": "2.11.2-preview.3",
3
+ "version": "2.11.2-preview.5",
4
4
  "description": "Developer documentation content for Lunch Money APIs",
5
5
  "exports": {
6
6
  ".": "./package.json",
@@ -7,8 +7,10 @@ The Lunch Money API spec uses a modified version of SEMVER for its versioning me
7
7
 
8
8
  ## v2.11.2 - TBD
9
9
  - Add OAuth 2.0 bearer-token authentication to the v2 API, allowing applications to access Lunch Money on behalf of users who authorize them
10
- - Enforce required OAuth scopes for every v2 operation and publish the scope and scope-group catalog mapped to V2 `operationId` values
10
+ - Document and enforce required OAuth scopes for every v2 operation and publish the scope and scope-group catalog mapped to V2 `operationId` values.
11
+ - Added a new `403` `insufficient_scope` response
11
12
  - Document the OAuth 2.0 authorization-code flow used to obtain access tokens
13
+ - Add `include_files` query parameter to `GET /transactions/{id}`
12
14
 
13
15
  ## v2.11.1 - TBD
14
16
  - Add `GET /me/account/settings` and `PUT /me/account/settings` for account-level settings
package/v2/spec/AGENTS.md CHANGED
@@ -41,6 +41,12 @@ Follow these rules whenever editing `v2/spec/lunch-money-api-v2.yaml`:
41
41
  - Add links when they materially help consumers discover a related endpoint or relevant guide.
42
42
  - Do not add links that merely restate obvious navigation.
43
43
 
44
+ ### YAML formatting
45
+
46
+ - Write each description paragraph as a single line. Never hard-wrap prose to a column: inside a folded scalar a line break becomes a space, so a wrap landing beside punctuation or markup silently corrupts the rendered text.
47
+ - Use a folded block (`>-`) only when a description has more than one paragraph, separated by a blank line. A single-paragraph description stays on the key line.
48
+ - Never use a literal block (`|`, `|-`) for prose — newlines become significant, so reflowing later changes the output.
49
+
44
50
  ### Examples
45
51
 
46
52
  Examples are selective documentation aids, not a required artifact for every spec change.