Cashless
cashless.co ↗OAuth 2.0 is self-serve: create an app under Settings → Developer and it works unverified immediately — only the trust badge/directory listing needs review (3–5 business days). The real gate is identity: cashless.co publishes no OAuth metadata (both .well-known paths return HTML), while the live /oauth/authorize endpoint and all OAuth docs sit on app.cashpanel.io.
01Pick your path
02Time & effort
- DEVConfirm which domain owns the OAuth surface15–45 minutessourced[S3]Probes: developer.cashless.co unreachable; cashless.co/.well-known/* return 200 text/html; app.cashpanel.io/oauth/authorize returns 307 to /login. Docs describe CashPanel, not cashless.co.
- DEVCreate the OAuth app10–20 minutessourced[S3]Settings → Developer → Create OAuth app; name, description, website, redirect URIs, scopes. Client secret shown once.
- DEVImplement authorize → callback → token exchange1–3 hourssourced[S3]Docs ship a working Express/TypeScript example; time estimate is inferred.
- DEVWire token refresh and revocation30–90 minutessourced[S3]Access tokens live 1 hour; refresh tokens 30 days and rotate on each use.
- PRODOptional verification reviewwait 3–5 dayssourced[S1]Initial review is 3–5 business days; only needed for the badge and directory listing.
- PRODRe-review if changes requestedwait 2–3 dayssourced[S1]Feedback arrives by email with specific fixes; adding scopes or renaming may trigger this.
03Steps
Get a working connection
Probes show cashless.co answers /.well-known/openid-configuration and /.well-known/oauth-authorization-server with 200 text/html — SPA fallbacks, not RFC 8414 metadata — and developer.cashless.co does not resolve. The only live authorize endpoint found is app.cashpanel.io/oauth/authorize (307 to /login). Ask support which platform your users actually sign into before registering an app.
↗ app.cashpanel.io/oauth/authorize◆ prepared by agent · Email to the provider's support teamSubject: Is cashless.co the same platform as CashPanel? Hi — I'm integrating with cashless.co. I found OAuth 2.0 docs and a live /oauth/authorize endpoint at app.cashpanel.io, but cashless.co itself publishes no OAuth discovery metadata and developer.cashless.co is unreachable. Could you confirm: (1) do cashless.co users sign in with CashPanel credentials, and (2) which domain hosts OAuth app registration? If cashless.co is API-key only, please say so and point me at the key docs. Thanks.
In the dashboard go to Settings → Developer → Create OAuth app. Fill Name, Description, Website, Redirect URIs, then tick scopes and click Create. You get a Client ID and a Client Secret shown once — put the secret in your secret manager immediately.
“You'll receive: * Client ID: Public identifier for your app * Client Secret: Keep this secret (shown once)” — [S3] verified verbatim
↗ cashpanel.io/docs/build-oauth-app/◆ prepared by agent · App registration fieldsName: <real product name — do not use 'CashPanel'> Description: 1–2 sentences on what the agent does Website: https://yourapp.com (HTTPS) Redirect URIs: https://yourapp.com/callback (+ http://localhost:3000/callback for dev) Scopes: transactions.read invoices.read reports.read
Scopes follow resource.permission. Pick read-only scopes per feature; avoid the apis.read / apis.all meta scopes and skip write scopes unless the agent mutates data. Unused scopes are an explicit rejection reason and force re-authorization when added later.
“Scopes follow the pattern resource.permission:” — [S4] verified verbatim
↗ cashpanel.io/docs/oauth-scopes/◆ prepared by agent · Scope justification draft (for consent screen + review)transactions.read — read the user's transactions to build spend summaries. No edits. invoices.read — list invoices and their status. Read-only; we never send or delete. reports.read — pull revenue/runway figures for the dashboard. Not requested: apis.read / apis.all (broad read-all / full access), and every *.write scope — v1 performs no mutations.
Send the user to https://app.cashpanel.io/oauth/authorize with response_type=code, client_id, redirect_uri, space-separated (URL-encoded) scope, and a random state. Public clients (SPA, mobile) must add code_challenge and code_challenge_method=S256 and must not send a client_secret.
“Note: Public clients should not send client_secret.” — [S3] verified verbatim
↗ cashpanel.io/docs/build-oauth-app/◆ prepared by agent · Authorize URL builder (TypeScript)const url = new URL("https://app.cashpanel.io/oauth/authorize"); url.searchParams.set("response_type", "code"); url.searchParams.set("client_id", process.env.CASHPANEL_CLIENT_ID!); url.searchParams.set("redirect_uri", process.env.REDIRECT_URI!); url.searchParams.set("scope", "transactions.read invoices.read reports.read"); url.searchParams.set("state", state); url.searchParams.set("code_challenge", challenge); url.searchParams.set("code_challenge_method", "S256"); res.redirect(url.toString());POST JSON to https://api.cashpanel.io/v1/oauth/token with grant_type=authorization_code, code, redirect_uri, client_id and client_secret (or code_verifier for public clients). The response carries access_token, expires_in 3600, refresh_token and the granted scope — compare that scope string against what you asked for.
“Make a POST request to exchange the authorization code:” — [S3] verified verbatim
↗ cashpanel.io/docs/build-oauth-app/◆ prepared by agent · Token exchangecurl -X POST https://api.cashpanel.io/v1/oauth/token \ -H "Content-Type: application/json" \ -d '{"grant_type":"authorization_code","code":"AUTH_CODE","redirect_uri":"YOUR_REDIRECT_URI","client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET"}'Access tokens expire after 3600s. Refresh with grant_type=refresh_token; refresh tokens last 30 days and rotate on every use, so persist the new one each time or you lose access. Catch 401s and refresh automatically rather than surfacing failures to the user.
“Refresh tokens are valid for 30 days and rotate on each use.” — [S3] verified verbatim
↗ cashpanel.io/docs/build-oauth-app/POST to https://api.cashpanel.io/v1/oauth/revoke with the token, client_id and client_secret so users can disconnect your agent without revoking from the dashboard. This is what makes a 'disconnect' button honest.
“Allow users to disconnect your app by revoking tokens:” — [S3] verified verbatim
↗ cashpanel.io/docs/build-oauth-app/
Make it production-ready
Complete every app field, link a privacy policy from your website that explains collection, use, retention and deletion, confirm HTTPS everywhere and PKCE for public clients, then click Submit for review. Status goes to Pending with an email confirmation; expect 3–5 business days.
“* Initial review: 3-5 business days” — [S1] verified verbatim
↗ cashpanel.io/docs/app-review-process/◆ prepared by agent · Pre-submission checklist[ ] Name, Description, Developer name, Website all filled [ ] Privacy policy linked from site (collection, use, retention, deletion) [ ] All redirect URIs HTTPS (localhost allowed for dev only) [ ] PKCE S256 implemented for any public client [ ] Authorization flow tested end-to-end, including access_denied [ ] Token refresh works; rotated refresh token is persisted [ ] Every requested scope is actually used; no apis.read / apis.all [ ] Tokens never logged or committed; secret in a secret manager [ ] Tested against at least two different accounts
04Requirements, scopes & nuances
You'll need
- ▸HTTPS on every endpoint and redirect URI — localhost is the only dev exception. sourced ❝[S3][S1]
- ▸PKCE (S256) for public clients such as SPAs and mobile apps. sourced ❝[S1][S3]
- ▸A privacy policy linked from your website covering data collected, use, retention and deletion. sourced ❝[S1]
- ▸Complete app profile: name, 1–2 sentence description, developer name, website (logo and screenshots recommended). sourced ❝[S1]
- ▸A working end-to-end OAuth flow with graceful handling of authorization denials and token expiry. sourced ❝[S1]
- ▸Secure token storage; never log or expose access tokens or commit the client secret. sourced ❝[S1][S3]
Gotchas
- !cashless.co answers both /.well-known/oauth-authorization-server and /.well-known/openid-configuration with 200 text/html — SPA fallbacks, not discovery documents. Do not auto-discover; hardcode the endpoints from the docs. inferred[S3]
- !developer.cashless.co does not resolve at all, so there is no developer portal on that subdomain to register against. inferred
- !The client secret is displayed exactly once at app creation; regenerate it in app settings if you lose it, and the old secret dies instantly. sourced ❝[S3]
- !Refresh tokens rotate on every use — failing to persist the new token silently breaks the integration within 30 days. sourced ❝[S3]
- !Adding scopes later forces users to re-authorize and may trigger re-review, so over-scoping up front is a trap in both directions. sourced ❝[S4][S1]
- !Unused scopes, a missing privacy policy, HTTP endpoints and a non-working flow are the documented top rejection reasons. sourced ❝[S1]
- !Do not copy the Cashfree partner flow (S6) — it is an unrelated vendor with a partner-vetted OAuth model and says nothing about this provider. inferred[S6]
| Scope / permission | Tier | Note | Evidence |
|---|---|---|---|
| transactions.read | basic | Transactions, categories, attachments. The default read scope for a spending or dashboard agent. | sourced ❝[S4] |
| invoices.read | basic | View invoices and status. Read-only — safe default for reminders and accounting sync. | sourced ❝[S4] |
| customers.read | basic | View customer records; usually paired with invoices.read. | sourced ❝[S4] |
| reports.read | basic | Revenue, profit, runway and burn-rate figures. Read-only but financially revealing. | sourced ❝[S4] |
| bank-accounts.read | sensitive | Connected bank accounts and balances — cash-position data. Justify explicitly on the consent screen. | sourced ❝[S4] |
| documents.read | sensitive | Document vault contents; may include receipts and contracts. Pair with documents.write only if the agent uploads. | sourced ❝[S4] |
| invoices.write | sensitive | Create, update, send and delete invoices — sending is user-visible and irreversible. Gate behind confirmation. | sourced ❝[S4] |
| transactions.write | sensitive | Mutates categories, notes and attachments — an accounting-integrity risk. | sourced ❝[S4] |
| apis.read | restricted | Meta scope: read access to everything. Docs say use meta scopes sparingly; reviewers flag unused breadth. | sourced ❝[S4][S1] |
| apis.all | gated | Meta scope: full read and write across all resources. Effectively an account takeover token — expect scrutiny and re-authorization. | sourced ❝[S4] |
05If you get blocked
→ Email support@cashpanel.io (or hi@paycashless.com / admin@thecashless.ai) and confirm which domain issues credentials for the users you're integrating, before you register anything.
→ Hardcode authorize https://app.cashpanel.io/oauth/authorize and token https://api.cashpanel.io/v1/oauth/token from the docs; treat the provider as non-discoverable.
→ Request only scopes the flow actually calls, and drop apis.read / apis.all in favour of per-resource reads; scopes are validated against the app's registered set at authorize time.
→ Ship unverified first, then submit for review once the flow is stable; 3–5 business days gets the trust badge and removes the warning.
06Evidence: what was tested, sourced, and still uncertain
Sources read
- [S1] App Review Process third-party
- [S2] Welcome to Paycashless's Developer Portal - Paycashless Docs official
- [S3] Build an OAuth App third-party
- [S4] OAuth Scopes Reference third-party
- [S5] Developer Platform · CashlessAI · CashlessAI official
- [S6] Partner Platform OAuth Flow | Cashfree third-party
- [composio] Composio — Managed OAuth apps directory official
- [probe] Live HTTP probes run by the agent (dummy client_id, no credentials) probe
Still uncertain
- ? Nothing in the sources establishes that cashless.co and app.cashpanel.io/cashpanel.io are the same company; the brand match may be coincidental. Resolve this before trusting any step above.
- ? S2 (Paycashless) and S5 (CashlessAI) are separate products documenting API-key auth only — no third-party OAuth for acting on behalf of users. If either is 'Cashless', the correct verdict is 'API keys / partner only', not OAuth.
- ? S6 is Cashfree, an unrelated payments vendor pulled in by the fetch; it is not evidence about this provider and its partner-vetting model must not be assumed here.
- ? No source maps scopes to review tiers; the basic/sensitive/restricted/gated labels are my judgement, not documented policy.
- ? Verification appears optional ('unverified apps work fully'), but no source states whether unverified apps have user caps, rate limits or other hidden restrictions.
- ? All build-effort estimates (1–3 hours to a working flow) are inferred — the docs give code samples but no time figures.
- ? Generated automatically; no app was registered and no review was submitted.