The Angular frontend communicates with the Flask API through /api, using frontend/proxy.conf.json during local development. Protected endpoints require a JWT bearer token. The Angular interceptor attaches the active session token, but Flask remains the authority for identity, role checks, merchant scoping, and mutation rules.
Authorization: Bearer <jwt-token>Authenticates a stored user and returns the session data Angular needs for guarded navigation and role-aware interface decisions.
JWT required: No
Request body:
email=parth@payments.com
password=admin123
Response example:
{
"status": 200,
"message": "Login successful",
"data": {
"email": "parth@payments.com",
"role": "admin",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}Frontend usage:
AuthService.login- login form
- session storage
- role-based landing route
Registers a user account. The Angular registration page submits merchant registration, keeping self-service signup aligned with merchant-scoped access rather than privileged roles.
JWT required: No
Request body:
email=newmerchant@example.com
password=pass123
role=merchant
Response example:
{
"status": 201,
"message": "User registered"
}Frontend usage:
AuthService.register- register form
Deletes the authenticated merchant account and removes payments created by that merchant account. This is account/profile deletion, not platform payment administration. Admin and finance users do not receive this control in the frontend and are rejected by the backend.
JWT required: Yes
Allowed backend role:
- merchant
Example request:
DELETE /api/me
Authorization: Bearer <jwt-token>Response example:
{
"status": 200,
"message": "Account deleted"
}Frontend usage:
- merchant-only app-shell account deletion
- confirmation dialog
- logout after successful deletion
Payments are lifecycle records. The backend creates them as pending, scopes retrieval by role, validates allowed mutation fields, and stores provider attempts as routing history.
Retrieves paginated payment records under the active user's role boundary. Admin and finance users receive platform-wide records. Merchants receive only records where created_by matches the authenticated email. Optional query parameters support backend filtering before pagination.
JWT required: Yes
Query parameters:
| Parameter | Example | Purpose |
|---|---|---|
page |
1 |
Page number |
limit |
5 |
Number of records per page |
status |
success |
Optional backend status filter |
from |
2026-01-01 |
Optional initiated date lower bound |
to |
2026-01-31 |
Optional initiated date upper bound |
Example request:
GET /api/payments?page=1&limit=5
Authorization: Bearer <jwt-token>Response example:
{
"status": 200,
"data": {
"payments": [
{
"_id": "65f1a7c4b2e8f4a91c0d2211",
"merchant": "Spotify",
"payment_type": "subscription",
"amount_minor": 1299,
"currency": "GBP",
"region": "UK",
"status": "success",
"created_by": "arjun@payments.com",
"initiated_at": "2026-01-03T10:00:00",
"customer_details": {
"name": "Ava Reed",
"email": "ava.reed@example.com",
"country": "UK"
},
"provider_attempts": [
{
"provider": "Stripe",
"result": "success",
"latency_ms": 142
}
]
}
],
"page": 1,
"limit": 5,
"total": 1
}
}Frontend usage:
PaymentsService.fetchPaymentsPaymentsService.fetchAllPayments- dashboard metrics
- payments table
- filters, sorting and pagination
Initiates a payment record. The backend sets status to pending, records the authenticated user's email as created_by, stores customer details, and accepts an initial provider_attempts array when supplied.
JWT required: Yes
Allowed frontend roles:
- admin
- merchant
Request body:
merchant=Spotify
payment_type=subscription
amount_minor=1299
currency=GBP
region=UK
customer_details={"name":"Ava Reed","email":"ava.reed@example.com","country":"UK"}
provider_attempts=[]
Response example:
{
"status": 201,
"message": "Payment created"
}Frontend usage:
PaymentFormModalComponentPaymentsService.createPayment- create payment flow
Applies controlled payment lifecycle mutations. Merchant users are blocked from updates. Finance users can update status and append provider attempts, but cannot alter core payment/customer fields. Admin users can update core fields as well as status/provider attempts.
Provider attempts are appended to the existing array, preserving routing history rather than replacing it.
JWT required: Yes
Allowed backend roles:
- admin
- finance
Request body for status update:
status=success
Request body for provider attempt:
provider_attempts=[{"provider":"PayPal","result":"failure","latency_ms":310}]
Response example:
{
"status": 200,
"message": "Updated"
}Frontend usage:
- approve/reject controls
- provider attempt modal
- analytics refresh after mutation
Deletes a payment record as a platform administration action. This is separate from merchant account/profile deletion.
JWT required: Yes
Allowed backend role:
- admin
Example request:
DELETE /api/payments/65f1a7c4b2e8f4a91c0d2211
Authorization: Bearer <jwt-token>Response example:
{
"status": 200,
"message": "Deleted"
}Frontend usage:
- admin payment delete action
- confirmation dialog
- payments refresh after mutation
Analytics endpoints are role-protected and use the same backend identity rules as payments. Merchant users receive analytics only from their own payment records. Admin and finance users receive platform-wide analytics. Metrics are derived from stored lifecycle records and provider attempts.
Returns payment volume grouped by currency, with optional filters applied before aggregation.
JWT required: Yes
Optional query parameters:
| Parameter | Example | Purpose |
|---|---|---|
status |
success |
Filter analytics by payment status |
from |
2026-01-01 |
Filter by initiated date lower bound |
to |
2026-01-31 |
Filter by initiated date upper bound |
Response example:
{
"status": 200,
"data": [
{
"currency": "GBP",
"total_volume": 124900
}
]
}Returns average latency grouped by provider using the provider_attempts routing history stored on payment records.
JWT required: Yes
Optional query parameters:
statusfromto
Response example:
{
"status": 200,
"data": [
{
"provider": "Stripe",
"average_latency_ms": 142
},
{
"provider": "PayPal",
"average_latency_ms": 184
}
]
}Returns payment counts grouped by lifecycle status.
JWT required: Yes
Optional query parameters:
statusfromto
Response example:
{
"status": 200,
"data": [
{
"status": "success",
"count": 8
},
{
"status": "pending",
"count": 3
},
{
"status": "failed",
"count": 2
}
]
}Frontend usage:
AnalyticsService.getPaymentVolumeAnalyticsService.getProviderLatencyAnalyticsService.getPaymentStatus- analytics charts
- refresh after payment mutation
- JWT authentication was added so API access is tied to a signed identity rather than anonymous requests.
- Role-Based Access Control was introduced for
admin,finance, andmerchant. - Merchant visibility is enforced server-side using the authenticated email, not only frontend filtering.
- Merchant account deletion is restricted to merchant users and removes records created by that account.
- Payments now follow a controlled lifecycle: backend-created
pendingrecords, restricted updates, provider attempt recording, and final status reporting. provider_attemptscaptures routing/fallback evidence with provider, result, and latency.- Finance users can perform review-style lifecycle changes without being able to rewrite core payment/customer fields.
GET /paymentsnow supports role scoping, pagination, status filtering, and initiated-date filtering.- Analytics endpoints now respect the same role visibility rules as payments.
- Provider latency and status distribution metrics were added so the system reports operational behaviour rather than only listing records.
The CW2 API is a more mature system boundary than CW1: authentication identifies the user, RBAC constrains what that user can see or mutate, provider attempts make routing history visible, and analytics are derived from the same scoped operational records used by the payments workflow.