User Stories
User Stories: {{PROJECT_NAME}}Drop — Fintech Payment App
Project:
{{PROJECT_NAME}}Drop — Remittance + QR Payments Version:{{VERSION}}1.0 Date:{{DATE}}2026-02-23 Author:{{AUTHOR}}John (AI Director) Status:Draft | In Review |Approved Reviewers:{{REVIEWERS}}Alem Bašić (CEO)
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | Initial |
1. Epic Overview
| Epic ID | Epic Name | Business Goal | Story Count | Status | Target Release |
|---|---|---|---|---|---|
| EP-01 | |||||
| EP-02 | Remittance (Send Money) | BO-01, BO-02 — revenue + users | 5 | Done (Phase 1) | Phase 1 |
| EP-03 | QR Merchant Payments | BO-01, BO-03 — revenue + merchants | 5 | Done (Phase 1) | Phase 1 |
| EP-04 | Open Banking (AISP) | BO-02 — user trust | 2 | Mock (Phase 2) | Phase 2 |
| EP-05 | Transaction History & Notifications | BO-02, BO-03 | 3 | Done (Phase 1) | Phase 1 |
| EP-06 | Merchant Analytics | BO-03 — merchant retention | 2 | Done (Phase 1) | Phase 1 |
| EP-07 | KYC & Compliance | BO-05 — regulatory | 2 | Mock (Phase 2) | Phase 2 |
2. Epic Templates
Epic: EP-01 — {{EPIC_NAME}}
Epic Statement:
As a {{PERSONA}}, I need {{CAPABILITY}} so that {{BUSINESS_VALUE}}.
Business Goal: {{BUSINESS_OBJECTIVE_REFERENCE}}
Priority: Must Have | Should Have | Could Have
Estimated Size: {{X}} story points (rough)
Target Sprint(s): Sprint {{X}} – Sprint {{Y}}
Acceptance Criteria at Epic Level:
{{HIGH_LEVEL_CRITERION_1}}{{HIGH_LEVEL_CRITERION_2}}{{HIGH_LEVEL_CRITERION_3}}
Stories in This Epic:
US-001: {{STORY_TITLE}}US-002: {{STORY_TITLE}}US-003: {{STORY_TITLE}}
3. Story Format Guide
Standard Story Format:
As a [persona/role],
I want [feature/action],
So that [benefit/outcome].
Acceptance Criteria Format (Given/When/Then):
Given [a precondition that must be true],
When [the user performs an action],
Then [the expected outcome occurs].
Key Principles:
Stories describe WHAT the user needs, not HOW to build itEach story must be independently valuable and testableStories should be completable within a single sprintIf a story takes > 8 story points, break it into smaller storiesAcceptance criteria should be written as tests (they become test cases)
4. Story Backlog
Epic EP-01: {{EPIC_NAME}}User Onboarding & Authentication
US-001: {{STORY_TITLE}}Account Registration (3-step onboarding)
| Attribute | Value |
|---|---|
| Epic | EP-01: |
| Priority | Must Have |
| Story Points | |
| Sprint | |
| Assigned To | |
| Status | |
| FR Reference | FR- |
| BR Reference | BR- |
Story:
As a {{PERSONA}}Norwegian resident (18+),
I want {{ACTION/FEATURE}}to register for Drop with my email and date of birth,
So that {{BENEFIT/OUTCOME}}I can access remittance and QR payments at lower fees than existing services.
Context:
{{ADDITIONAL_CONTEXT_THAT_HELPS_UNDERSTAND_THE_STORY}}3-step flow: (1) personal details + DOB validation, (2) OTP on Norwegian phone (+47), (3) PIN setup. BankID integration in Phase 2 replaces DOB validation with real SCA.
Acceptance Criteria:
- Given
{{PRECONDITION}}valid email, password ≥8 chars, Norwegian phone (+47), DOB ≥18 years, when{{USER_ACTION}},user submits registration, then{{EXPECTED_RESULT}}201 created; user proceeds to OTP step - Given
{{PRECONDITION}},DOB under 18 years, when{{USER_ACTION}},user submits, then{{EXPECTED_RESULT}}422 "Du må være minst 18 år" - Given
{{ERROR_CONDITION}},duplicate email, when{{USER_ACTION}},submitted, then{{ERROR_HANDLING}}409 "Email already in use" - Given OTP sent, when user enters correct 6 digits, then user proceeds to PIN setup
- Given valid 4-digit PIN entered and confirmed, when submitted, then account activated; JWT cookie set
Technical Notes:
{{TECHNICAL_CONSTRAINT_OR_HINT}}Age validation:(today - DOB) >= 18 years- OTP: 6-digit code; in MVP any code accepted (mock); real SMS in Phase 2
- Password: bcrypt 12 rounds
UI/UX Notes:
ScreenScreen:/ component: {{SCREEN_NAME}}mockups/figma-make-export/src/components/Onboarding.jsDesign3-stepreference:progress{{FIGMA_LINK_OR_FILE}}indicator Responsive behavior: {{NOTES}}shown
Dependencies:
- Blocked by:
{{US-XXXNone |None}} - Blocks:
{{US-XXX002,|US-003,None}} External: {{THIRD_PARTY_DEPENDENCY | None}}
Definition of Done:US-010
Code complete and follows coding standardsUnit tests written (≥ 80% coverage on new code)Code review approved by Tech LeadMerged todevelopDeployed to stagingAll acceptance criteria manually verifiedNo critical or high bugs openDocumentation updated (if applicable)
US-002: {{STORY_TITLE}}User Login
| Attribute | Value |
|---|---|
| Epic | EP-01 |
| Priority | Must Have |
| Story Points | |
| Sprint | |
| FR Reference | FR-002 |
Story: As a registered Drop user, I want to log in with my email and password, So that I can access my account and make payments.
Acceptance Criteria:
- Given valid email + password, when login submitted, then JWT cookie set; redirected to dashboard
- Given wrong password, when submitted, then 401 "Invalid email or password" (no enumeration)
- Given 10 failed attempts from same IP, when next attempt, then 429 rate limit error
Dependencies: Blocked by: US-001
US-003: Session Logout
| Attribute | Value |
|---|---|
| Epic | EP-01 |
| Priority | Must Have |
| Story Points | 1 |
| Sprint | Sprint 1 |
| Status | Done |
| FR Reference | FR-003 |
Story: As a logged-in Drop user, I want to log out of my account, So that my session is securely terminated on shared devices.
Acceptance Criteria:
- Given authenticated user, when they POST /api/auth/logout, then JWT cookie cleared; session revoked in DB
- Given logged-out user, when they access protected routes, then 401 redirect to login
Dependencies: Blocked by: US-002
US-004: BankID Verification (Phase 2)
| Attribute | Value |
|---|---|
| Epic | EP-01 |
| Priority | Must Have |
| Story Points | 8 |
| Sprint | Sprint 4 (Phase 2) |
| Status | Backlog |
| FR Reference | FR- |
Story:
As a {{PERSONA}}Norwegian resident,
I want {{ACTION}}to verify my identity via Norwegian BankID,
So that {{BENEFIT}}my account is secured with Strong Customer Authentication (SCA) as required by PSD2.
Acceptance Criteria:
- Given
{{PRECONDITION}},user at onboarding step 1, when{{USER_ACTION}},they complete BankID verification, then{{EXPECTED_RESULT}}DOB, name, and national ID extracted from BankID response - Given
{{PRECONDITION}},BankID shows DOB < 18 years, when{{USER_ACTION}},verification complete, then{{EXPECTED_RESULT}}registration rejected with age error - Given successful BankID, when verification complete, then kyc_status set to approved
Dependencies: Blocked by: {{US-001BaaS |provider None}}
Definition of Done: (same as standard DoD above)DEP-01)
Epic EP-02: {{EPIC_NAME}}Remittance (Send Money)
US-010: {{STORY_TITLE}}Send Money to Recipient
| Attribute | Value |
|---|---|
| Epic | EP-02: Remittance |
| Priority | Must Have |
| Story Points | 8 |
| Sprint | Sprint 1 |
| Status | Done |
| FR Reference | FR-020 |
| BR Reference | BR-003, BR-005 |
Story: As a Drop user who wants to support family abroad, I want to send money to a recipient in Serbia/Pakistan/Bosnia/Poland/Turkey/EUR zone at 0.5% fee, So that my family receives money faster and 10x cheaper than Western Union.
Context: "Amir wants to send 2,000 NOK to his mother Jasmina in Sarajevo. He opens Drop, taps 'Pošalji novac', selects Bosnia, enters Jasmina's IBAN, enters 2,000 NOK. Drop shows: mama receives 4,660 BAM, fee 10 NOK. He confirms. Mama gets SMS notification."
Acceptance Criteria:
- Given authenticated + KYC-approved user, when POST /api/transactions/remittance with amount 100-50,000 NOK and valid recipientId, then 201; transaction created; fee = amount × 0.005
- Given user with insufficient balance, when submitting, then 402 "Insufficient balance"
- Given amount < 100 NOK or > 50,000 NOK, when submitted, then 400 validation error
- Given unauthenticated user, when submitting, then 401 Unauthorized
- Given KYC-pending user, when submitting, then 403 "KYC verification required"
Technical Notes:
- 6 corridors in MVP: NOK→RSD, NOK→BAM, NOK→PKR, NOK→TRY, NOK→PLN, NOK→EUR
- In Phase 2: real PISP via BaaS
- Exchange rates from
exchange_ratestable, updated daily
UI/UX Notes: Screen: mockups/figma-make-export/src/components/SendMoney.js
Dependencies: Blocked by: US-001, US-012, US-013
US-011: View Exchange Rates
| Attribute | Value |
|---|---|
| Epic | EP-02 |
| Priority | |
| Story Points | |
| Sprint | |
| Status | |
| FR Reference | FR-021 |
Story:
As a {{PERSONA}}Drop user planning to send money,
I want {{ACTION}}to see current exchange rates before confirming a transfer,
So that {{BENEFIT}}I know exactly how much my recipient will receive.
Acceptance Criteria:
- Given
{{PRECONDITION}},any user, when{{USER_ACTION}},GET /api/rates, then{{EXPECTED_RESULT}}all 6 NOK exchange rates returned (RSD, BAM, PKR, TRY, PLN, EUR) - Given GET /api/rates/RSD, when called, then specific NOK→RSD rate returned
- Given GET /api/rates/XXX invalid, when called, then 404 Not Found
Dependencies: None
US-012: Add Recipient
| Attribute | Value |
|---|---|
| Epic | EP-02 |
| Priority | Must Have |
| Story Points | 3 |
| Sprint | Sprint 1 |
| Status | Done |
| FR Reference | FR-022 |
DefinitionStory:
As a Drop user sending money regularly to the same person,
I want to save recipient details (name, IBAN, country),
So that I don't have to re-enter them every time I send money.
Acceptance Criteria:
- Given authenticated user, when POST /api/recipients with valid name, IBAN, country, then recipient saved
- Given authenticated user, when GET /api/recipients, then all user's recipients returned
- Given invalid IBAN format, when submitted, then 422 validation error
Dependencies: Blocked by: US-002
Epic EP-03: QR Merchant Payments
US-020: Pay Merchant via QR Scan
| Attribute | Value |
|---|---|
| Epic | EP-03: QR Payments |
| Priority | Must Have |
| Story Points | 8 |
| Sprint | Sprint 2 |
| Status | Done |
| FR Reference | FR-030 |
| BR Reference | BR-004, BR-005 |
Story:
As a Drop user at a local merchant,
I want to scan the merchant's QR code and pay directly from my bank account,
So that I pay 1% merchant fee instead of Done:Vipps' 1.75-2.75%, without needing cash or card terminal.
Context: "Amir walks into Ahmet's kebab shop. On the counter is a Drop QR sticker. Amir opens Drop, taps 'Skeniraj', points camera at QR → 'Ahmetov Kebab' appears. He enters 129 NOK, taps 'Betal'. Ahmet's phone buzzes: 129 NOK received."
Acceptance Criteria:
- Given authenticated + KYC-approved user, when POST /api/transactions/qr-payment with valid merchantId and amount ≥1 NOK, then 201; merchant_fee = amount × 0.01
- Given invalid merchantId, when submitted, then 404 "Merchant not found"
- Given amount < 1 NOK, when submitted, then 400 validation error
- Given missing merchantId, when submitted, then 400 validation error
UI/UX Notes: Screen: mockups/figma-make-export/src/components/ScanQR.js
Dependencies: Blocked by: US-001, US-021
US-021: Merchant Business Registration
| Attribute | Value |
|---|---|
| Epic | EP-03 |
| Priority | Must Have |
| Story Points | 5 |
| Sprint | Sprint 2 |
| Status | Done |
| FR Reference | FR-031 |
Story: As a local business owner, I want to register my business in Drop and receive a QR code, So that I can start accepting payments at 1% fee within 5 minutes.
Acceptance Criteria:
- Given authenticated user, when POST /api/merchants with business_name, bank_account, address, then merchant created with unique QR code
- Given merchant, when GET /api/merchants/me, then merchant details + QR code returned
- Given QR code scanned by Drop consumer, when payment submitted, then merchant correctly identified
Dependencies: Blocked by: US-002
US-022: Merchant Dashboard
| Attribute | Value |
|---|---|
| Epic | EP-03 |
| Priority | Should Have |
| Story Points | 5 |
| Sprint | Sprint 2 |
| Status | Done |
| FR Reference | FR-032 |
Story: As a merchant using Drop, I want to see my daily/weekly/monthly transaction volume and fees, So that I can understand my Drop revenue and reconcile with my bank statement.
Acceptance Criteria:
- Given authenticated merchant, when GET /api/merchants/dashboard?period=week, then total_transactions, gross_volume, total_fees returned for that period
- Given GET with period=today, period=month, when called, then correct period data returned
Dependencies: Blocked by: US-021
Epic EP-04: Open Banking (standardAISP)
US-030: View Bank Account Balance
| Attribute | Value |
|---|---|
| Epic | EP-04: Open Banking |
| Priority | Should Have |
| Story Points | 5 |
| Sprint | Sprint 4 (Phase 2) |
| Status | Mock (Phase 2) |
| FR Reference | FR-040 |
Story: As a Drop user, I want to see my Norwegian bank account balance in the Drop app, So that I know if I have enough funds before sending money — without needing to open my banking app.
Acceptance Criteria:
- Given authenticated user with linked bank account, when GET /api/bank-accounts, then masked account number + balance returned
- Given no linked account, when viewing accounts screen, then prompt to link via BankID
Technical Notes: Real AISP requires BaaS partner (DEP-01) — currently mock data in demo
Dependencies: Blocked by: DEP-01 (BaaS partner)
Epic EP-05: Transaction History & Notifications
US-040: Transaction History
| Attribute | Value |
|---|---|
| Epic | EP-05 |
| Priority | Should Have |
| Story Points | 3 |
| Sprint | Sprint 1 |
| Status | Done |
| FR Reference | FR-050 |
Story: As a Drop user, I want to see a history of all my transactions, So that I can track my spending and verify payments went through.
Acceptance Criteria:
- Given authenticated user, when GET /api/transactions, then all user's transactions returned (most recent first)
- Given ?type=remittance query, when called, then only remittance transactions returned
Dependencies: Blocked by: US-010 or US-020
US-041: Transaction Notifications
| Attribute | Value |
|---|---|
| Epic | EP-05 |
| Priority | Should Have |
| Story Points | 3 |
| Sprint | Sprint 2 |
| Status | Done |
| FR Reference | FR-060 |
Story: As a Drop user or merchant, I want to receive notifications when transactions occur, So that I know immediately when money is sent or received.
Acceptance Criteria:
- Given completed transaction, when GET /api/notifications, then new notification appears in list
- Given user marks notification as read, when PATCH /api/notifications/[id], then status updated to read
Dependencies: Blocked by: US-010 or US-020
5. Story Estimation Guide
| Points | Complexity | Examples |
|---|---|---|
| 1 | Trivial | |
| 2 | Simple | |
| 3 | Moderate | CRUD for one entity, simple |
| 5 | Complex | Multi-step form, API |
| 8 | Very Complex | New module with CRUD + logic + UI + tests |
| 13+ | Too Large | Break into smaller stories |
Planning Poker: Use async estimation — each team member estimates independently, then compare and discuss outliers.
6. Definition of Ready Checklist
Before a story can be added toenters a sprint, verify:sprint:
- Story is
writtenin As a / I want / So that format - Story has at least 2 acceptance criteria
in(Given/When/Then formatThen) - Story has been estimated in story points
- Dependencies are identified and not blocking
- UI/UX design exists (
orFigmastoryMakeisexportbackend-only)for core screens) - Technical approach is understood
(no major unknowns) - Priority
isassigned (MoSCoW) - Story size
is≤ 8 points(or confirmed as a spike) Acceptance criteria are testable by QA- FR reference documented
7. Story Breakdown TechniquesMap
8. Story Mapping Visualization
USER JOURNEY: [Discovery]Register] → [Registration]Verify KYC] → [CoreSend Feature]Money] → [Management]Pay QR] → [Reporting]View MVPHistory]
Phase 1 US-001 US-020007(mock) US-030010 US-020 US-040
—(Demo) (ReleaseUS-002 1)
Release 2 —US-011 US-021 US-031 US-041
US-050
Release 3 — —003 US-032012 US-042022
Phase 2 US-051004 US-007(real) [Real PISP] [Real PISP] US-030
(Banking) (BankID) (Sumsub)
Replace with actual story IDs mapped to user journey steps and release priority
9.8. Backlog Summary
| Epic | Total Stories | Estimated Points | Done | Remaining | |
|---|---|---|---|---|---|
| EP-01: |
|||||
| EP-02: |
3 | 13 | 3 | 0 | |
| EP-03: QR Payments | 3 | 18 | 3 | 0 | |
| EP-04: Open Banking | 1 | 5 | 0 | 1 (Phase 2) | |
| EP-05: History/Notifications | 2 | 6 | 2 | 0 | |
| Total | 13 | 62 | 11 | 2 | (Phase 2) |
Velocity (last sprint): {{STORY_POINTS_COMPLETED}}
Projected completion: Sprint {{X}} ({{DATE}})
Approval
| Role | Name | Date | Signature |
|---|---|---|---|
| Author | John (AI Director) | 2026-02-23 | Approved |
| (AI) | |||
| Product Owner | John | 2026-02-23 | Approved |
| AI Director (John) | John | 2026-02-23 | Approved |