Developers
Building on Clear — integrating Pay with Clear into a shop — or working in this repository.
On this page
Integrating Pay with Clear
The public docs are generated by packages/pay-docs from the
/v1 schemas in packages/public-api-contracts,
and served at app.useclear.org/docs/. Edit the generator, not the output; a test fails if the
two drift.
@useclear/node@useclear/mcp, for a shop's agent/v1 endpointThe SDKs: @useclear/js ·
@useclear/node ·
@useclear/mcp.
Working in this repository
Start with setup.md — tools, installing, every .env, every dev port, the
checks to run before pushing, and how a change gets merged.
Apps — each has its own README: member ·
merchant · command ·
api · rewards/native.
Packages — domain · tokens ·
contracts-sdk ·
public-api-contracts ·
pay-docs. The rest are listed in the root README's
Repository layout.
The contracts are documented in Protocol.
Where the rules live
Some rules that read as co-op policy are constants in code, so they change only through a pull request. Their current values are in Governance → Parameters.
apps/api/src/services/payLedgerStore.ts (DEPOSIT_MATCH_PER_USD, DEPOSIT_MATCH_MONTHLY_CAP, RENT_BASE_CREDITS, BILL_CREDIT_RATE, BILL_CREDIT_CAP, GRACE_DAYS, VEST_DAYS, MAX_MULTIPLIER)ASSURANCE in apps/member/src/data/clearPlaceholder.ts, read by Savings through SAVINGS_IN_USE and SAVINGS_DAY_ONE. These are the values the app uses, although the file otherwise holds fixturesapps/api/src/services/credit/termLimitRule.ts (STARTER_CENTS, STEP_CENTS, CYCLES_PER_STEP, CEILING_CENTS). Whether it runs is AUTO_TERM_LIMITS (Going live → Off until set)Known limitations
These screens are visible in the apps but do not do what they show. Each row says what happens now
and where the code is. Paths are relative to the app's src/ unless they start with apps/ or packages/.
Fixtures. The member app's fixed data is
apps/member/src/data/clearPlaceholder.ts. Live
routes start from its *_DAY_ONE objects and replace fields as real reads arrive (see the comment
in pages/app/HomeRoute.tsx). SETTINGS, ASSURANCE_RESERVE, RESERVE_REPORTS, CLAIM_RECORD,
CLAIM_STEPS and CONTACTS are shown as they are, to every member.
Member app
WithdrawModal, opened by openWithdraw; only components/app-ui/QuickActions.tsx calls that, and nothing renders itwithdrawToBank in utils/apiClient.ts; components/app-ui/WithdrawModal.tsx; context/MoneyActionsContext.tsx; apps/api/src/routes/withdraw.tsonAdd or onSendBack, so neither Add nor the swapped Send … to your bank does anythingpages/app/HomePage.tsx; components/clear/AddMoneyDialog.tsxRequestMoneyDialog without onRequest, so its button does nothing. createPaymentRequest is called only by components/app-ui/RequestModal.tsx, which nothing opens (openRequest has no caller). POST /api/requests works: it finds the recipient by phone or email, refuses yourself, and notifies them. It stores no expiry, though the sheet says 7 days. The API has no route to list or answer a request, and no screen doespages/app/SendPage.tsx; components/clear/RequestMoneyDialog.tsx; apps/api/src/routes/requests.tsReplaceCardDialog's onReplace only closes the sheet. No card is closed or reissuedpages/app/CardPage.tsx; components/clear/card/ReplaceCardDialog.tsxcontrols in CARD_DAY_ONE; components/clear/CardControlsCard.tsxAdjustLimitsDialog's onSave sets local state only. The spend-limit route has no caller (Lithic → Known limitations)perTransactionLimit, perDayLimit in CARD_DAY_ONE; pages/app/CardPage.tsxuseState toggles. Not saved; notifications are sent regardlessnotificationGroups in SETTINGS; pages/app/SettingsPage.tsxLinkAccountDialog is rendered without onConnect or onManual, so Link another account links nothinglinked in SETTINGS; components/clear/LinkAccountDialog.tsxdevices, logins, lastLogin in SETTINGS; components/settings/TrustedDevicesDialog.tsx; components/settings/LoginHistoryPanel.tsxCONTACTS fixture. Choosing one sends and saves nothing. There is no recovery flow: the member-kit onboarding's recovery step is unreachable, because nothing passes onRecovercomponents/clear/RecoveryContactsDialog.tsx; packages/member-kit/src/onboarding/OnboardingFlow.tsxpermissions fixture; turning one off changes the screen only. lib/onboardingGrants.ts, which bundles the grants, is never importedpermissions in SETTINGS; components/settings/PermissionsPanel.tsxcomponents/settings/AdvancedDialog.tsxclosure fixture. CloseAccountDialog is rendered without onCloseAccount, so Close account does nothingclosure in SETTINGS; components/settings/CloseAccountDialog.tsxGET /api/assurance/record returns the real claim record, and the app does not read itASSURANCE_RESERVE, RESERVE_REPORTS, CLAIM_RECORD, CLAIM_STEPS; pages/app/AssuranceReservePage.tsx, ExplainerPage.tsx, ReserveReportsPage.tsx, ClaimPage.tsx; apps/api/src/routes/assurance.tsLendingPool.requestWithdrawal. Nothing in the apps calls claimWithdrawal or shows the queued request, so it is paid only if the member calls the contract themselves (Settlement → LendingPool)lib/sendCalls.ts; components/clear/ConnectedPoolMove.tsxConnectedPoolMove doesn't pass onRepayAndMove, so the button does nothingcomponents/clear/MoveMoneyDialog.tsx; components/clear/ConnectedPoolMove.tsxMerchant app
OFFLINE_BUILT = false; when true, offlineFor() allows it only for a Bluetooth reader (the M2), since Tap to Pay is online-only. The Capacitor Stripe Terminal plugin in use has no offline API. Settings › Payments › When the connection drops shows it locked. The settings offline_cards_enabled and offline_cards_limit_cents ($500.00 default) are saved, and the API returns the limit with each card tender as offlineLimitCents, but nothing stores a payment. A Clear charge's No connection sheet says a card would be storedreader/platform.ts; settings/panes.tsx; charge/phone.tsx; apps/api/src/services/merchant/shop/shopService.ts; apps/api/src/services/merchant/cards/cardTenders.tsone_person_close (owner_next_morning or wait_for_second) is saved with the shop's settings and read by nothing; nothing reaches the owner's Home the next morningapps/api/src/services/merchant/shop/shopService.ts; the drawer close in apps/api/src/services/merchant/drawer/ConfirmLeaveSheet is rendered without onLeave, so Leave Clear is disabled, and its payout and waiting figures are hard-coded. No API route ends a partnershippages/SettingsPage.tsx; settings/views.tsxmailto: to partners@useclear.org. Nothing in the code builds or submits a store app: a build made by hand through the shop's developer accounts is recorded with apps/api/scripts/store-build.ts, and Settings › Shop app shows that record (store-builds.md)settings/shopApp.tsx; apps/api/src/services/merchant/rewards/storeBuilds.tssettings/shopApp.tsxapps/merchant/capacitor.config.ts; apps/merchant/ios, apps/merchant/android