Partner V1 API Proposal
This document is a proposal for a cleaner API design for external partnerships, separate from the mobile/dashboard internal endpoints that already exist today.
Background
The endpoints currently in production were born for:
- the merchant mobile app
- the web dashboard
- internal operational needs
The problem is that external partner needs are different:
- they need a stable contract
- they need partner-specific authentication
- they need narrower scopes
- they need audit and rate-limit
For that reason, a new namespace is recommended:
/api/partner/v1/...
Design Principles
The partner API must be:
- stable and versioned
- separated from internal mobile/dashboard
- minimum privilege
- observable and auditable
- easy to use for partners without exposing internal system details
Namespace
All partner endpoints should sit under:
/api/partner/v1
Examples:
/api/partner/v1/auth/token/api/partner/v1/merchants/{merchant_id}/api/partner/v1/merchants/{merchant_id}/dashboard/api/partner/v1/merchants/{merchant_id}/transactions/api/partner/v1/references/business-types
Authentication Model
Suggested model:
Partner Credential
partner_idpartner_secret
To obtain an access token:
POST /api/partner/v1/auth/token
Request:
{
"partner_id": "partner-abc",
"partner_secret": "secret-value"
}
Response:
{
"token_type": "Bearer",
"access_token": "jwt-or-opaque-token",
"expires_in_secs": 3600,
"scope": [
"merchant.read",
"dashboard.read",
"transaction.read"
]
}
Scopes
Example scopes:
merchant.readdashboard.readtransaction.readreference.readmerchant.registration.write
A partner is granted only the scopes it needs.
External partners must not be granted scopes for:
- terminal device control
- terminal pairing
- reading detailed merchant terminal data
Merchant Access Model
There are two possible access models:
Model A. Direct Partner Scope
The partner is given access to specific merchants based on a mapping:
partner_idmerchant_id
For sales partners, this mapping should also carry:
referral_codepartner_type = sales_referralassigned_atrevoked_at
Used when the partner has a list of officially linked merchants.
Model B. Delegated Consent
The merchant grants permission for the partner to access its data.
Needs:
- consent record
- consent scope
- consent status
- revoked_at
If the long-term target is a partner ecosystem, model B is healthier.
Model C. Scoring Dataset Access
For banking/finance partners, the recommended access model is not "see all merchant transactions", but:
- the partner gets access to merchants who have already consented
- the endpoint returns a constrained scoring dataset
- the partner does not directly receive every raw transaction field
Example scopes:
scoring.readrisk-summary.readmerchant-consent.read
Suggested Database Tables
To make /api/partner/v1 truly operational, the minimum tables that should exist:
1. partner.api_credentials
Goal:
- store the partner's credential for machine-to-machine auth
- store the allowed scopes per credential
- support secret rotation and credential deactivation without deleting the partner
Important fields:
partner_idcredential_keycredential_secret_hashauth_methodallowed_scopesstatusexpires_atlast_used_atlast_rotated_at
2. partner.merchant_access
Goal:
- be the source of truth for which merchants a partner may read
- distinguish referral, delegated consent, and finance scoring access
Important fields:
partner_idmerchant_idaccess_typeaccess_statusreferral_codegranted_atexpires_atrevoked_at
3. partner.merchant_consents
Goal:
- store a merchant's consent to data access by a partner
- be the legal basis for finance/scoring partners
Important fields:
partner_idmerchant_idconsent_typeconsent_scopeconsent_statusconsent_sourceconsent_text_versiongranted_atexpires_atrevoked_at
4. partner.api_audit_logs
Goal:
- record every partner request that goes through the partner API
- be the basis for audit, incident review, and rate-limit analysis
Important fields:
partner_idcredential_idmerchant_idrequest_idhttp_methodrequest_pathresponse_statusscope_usedrequest_queryresponse_summaryip_addresslatency_ms
The initial implementation of these tables started in the migration:
merchant_database/db_kesles_merchant/migrations/legacy/031_create_partner_api_tables.sql
Status (2026-06-23): shipped. The
partner.*domain has been extracted into its own databasedb_kesles_merchant_partner(final-state snapshot atmerchant_database/db_kesles_merchant_partner/migrations/v1/002_partner_base.sql); the oldpartnerschema indb_kesles_merchantwas dropped. The partner API is served bypartner_service(port 8086) at/api/partner/v1.
Proposed Endpoints
1. Auth
POST /api/partner/v1/auth/token
Goal:
- partner authentication
- issue a scoped access token
2. Merchant Profile
GET /api/partner/v1/merchants/{merchant_id}
Concise response:
- merchant id
- merchant code
- merchant name
- merchant status
- business type
- business scale
- contact info
- address summary
3. Dashboard Summary
GET /api/partner/v1/merchants/{merchant_id}/dashboard
Response:
- today summary
- balance total
- weekly gross points
- recent transactions summary
4. Transactions
GET /api/partner/v1/merchants/{merchant_id}/transactions
Parameters:
periodanchor_datepagepage_sizestatuspayment_channel
Response:
- pagination
- summary
- items
Notes:
- this endpoint is more suitable for operational partners or partners who do need transaction detail
- for finance partners, this should not be the main endpoint
GET /api/partner/v1/partners/{partner_id}/referral-merchants
A dedicated endpoint for sales partners.
Goal:
- show the list of merchants linked to the referring partner
- be the basis for filtering on the sales partner dashboard
Minimum response:
- merchant id
- merchant name
- referral code
- merchant status
- onboarding status
- activation date
GET /api/partner/v1/partners/{partner_id}/referral-merchants/summary
An aggregate endpoint for sales partners.
Goal:
- view total referral merchants
- active merchants
- aggregate revenue
- aggregate transactions
GET /api/partner/v1/merchants/{merchant_id}/scoring-summary
A dedicated endpoint for banking/finance partners.
Goal:
- give business scoring data in a safer form
Example fields:
- merchant_id
- merchant_status
- average_monthly_gross_amount
- average_monthly_transaction_count
- avg_ticket_size
- growth_30d
- growth_90d
- settlement_consistency_score
- transaction_stability_score
GET /api/partner/v1/merchants/{merchant_id}/scoring-transactions
If a finance partner still needs transaction data, this endpoint must:
- be limited per merchant consent
- only return relevant transaction fields
- not show personal fields that are not needed
5. Merchant Registration
POST /api/partner/v1/merchant-registrations
For partners onboarding new merchants.
GET /api/partner/v1/merchant-registrations/device-offer
Fetch the active device offer.
6. Reference Data
GET /api/partner/v1/references/provinces
GET /api/partner/v1/references/cities
GET /api/partner/v1/references/districts
GET /api/partner/v1/references/subdistricts
GET /api/partner/v1/references/postal-codes
GET /api/partner/v1/references/business-scales
GET /api/partner/v1/references/business-types
7. Webhooks
If a partner needs near-real-time integration, webhooks are recommended:
partner.transaction.created
partner.transaction.updated
partner.merchant.status.changed
Minimum webhook payload:
- event id
- event type
- occurred at
- merchant id
- resource id
- payload
- signature
Recommended Response Format
Success
{
"data": {},
"meta": {
"request_id": "uuid"
}
}
List
{
"data": [],
"meta": {
"page": 1,
"page_size": 50,
"total_items": 245,
"total_pages": 5,
"request_id": "uuid"
}
}
Error
{
"error": {
"code": "merchant_not_found",
"message": "Merchant not found",
"details": {}
},
"meta": {
"request_id": "uuid"
}
}
Security
The minimum that must be in place:
- scoped partner token
- partner audit log
- request id per request
- per-partner rate limit
- optional IP allowlist
- webhook signature verification
- secret rotation
- per-partner-type field-level data minimization
- consent validation before opening scoring data
Data Governance
New tables/concepts that may be needed:
partner_clientspartner_client_secretspartner_client_scopespartner_merchant_accesspartner_consentspartner_api_logspartner_webhook_subscriptionspartner_webhook_deliveriespartner_referral_codespartner_scoring_access_policiesmerchant_partner_consents
Migration Strategy From The Current API
Phase 1
Continue using existing endpoints for a limited set of partners.
Phase 2
Build a /api/partner/v1 facade reading the same store/service.
Phase 3
Add partner credentials and scopes.
Phase 4
Add webhooks and partner audit log.
Phase 5
Deprecate partner access to the legacy internal/mobile-facing endpoints.
Recommended Design Decisions
If a choice has to be made now, the recommendation is:
- do not expose internal endpoints directly to partners
- start with read-only
/api/partner/v1 - partner auth uses
partner_id + partner_secret - limit the initial endpoints to:
- merchant profile
- dashboard summary
- transactions
- reference data
- the merchant onboarding write flow comes later, after consent and audit are mature
- sales partners may only see merchants based on referral scope
- finance partners are routed to the scoring-summary endpoint, not full raw transactions by default