Skip to main content

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:

  1. stable and versioned
  2. separated from internal mobile/dashboard
  3. minimum privilege
  4. observable and auditable
  5. 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_id
  • partner_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.read
  • dashboard.read
  • transaction.read
  • reference.read
  • merchant.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_id
  • merchant_id

For sales partners, this mapping should also carry:

  • referral_code
  • partner_type = sales_referral
  • assigned_at
  • revoked_at

Used when the partner has a list of officially linked merchants.

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.read
  • risk-summary.read
  • merchant-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_id
  • credential_key
  • credential_secret_hash
  • auth_method
  • allowed_scopes
  • status
  • expires_at
  • last_used_at
  • last_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_id
  • merchant_id
  • access_type
  • access_status
  • referral_code
  • granted_at
  • expires_at
  • revoked_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_id
  • merchant_id
  • consent_type
  • consent_scope
  • consent_status
  • consent_source
  • consent_text_version
  • granted_at
  • expires_at
  • revoked_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_id
  • credential_id
  • merchant_id
  • request_id
  • http_method
  • request_path
  • response_status
  • scope_used
  • request_query
  • response_summary
  • ip_address
  • latency_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 database db_kesles_merchant_partner (final-state snapshot at merchant_database/db_kesles_merchant_partner/migrations/v1/002_partner_base.sql); the old partner schema in db_kesles_merchant was dropped. The partner API is served by partner_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:

  • period
  • anchor_date
  • page
  • page_size
  • status
  • payment_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

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_clients
  • partner_client_secrets
  • partner_client_scopes
  • partner_merchant_access
  • partner_consents
  • partner_api_logs
  • partner_webhook_subscriptions
  • partner_webhook_deliveries
  • partner_referral_codes
  • partner_scoring_access_policies
  • merchant_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.

If a choice has to be made now, the recommendation is:

  1. do not expose internal endpoints directly to partners
  2. start with read-only /api/partner/v1
  3. partner auth uses partner_id + partner_secret
  4. limit the initial endpoints to:
    • merchant profile
    • dashboard summary
    • transactions
    • reference data
  5. the merchant onboarding write flow comes later, after consent and audit are mature
  6. sales partners may only see merchants based on referral scope
  7. finance partners are routed to the scoring-summary endpoint, not full raw transactions by default