Data Models - Payments & Charges
Public/conceptual fields of Payment and Charge objects, normalized model, and separation from provider raw data.
This page explains the public/conceptual model of Payment and Charge objects. The goal is not to expose the private database schema one-to-one, but to help merchants and developers understand which field carries which responsibility.
In HSRC Pay the public integration model should rely on normalized fields. Raw provider response may be stored for debug, trace, or internal ops; merchant applications should decide from normalized fields.
Model design principles
- Payment is business-level payment intent.
- Charge is provider-level attempt or financial transaction attempt.
- Provider raw data does not replace the public model.
- Metadata carries merchant context; do not use it for secrets, card data, or provider credentials.
- Security/3DS fields are sensitive and should be masked.
- Public fields should stay stable and explainable for backward compatibility.
Payment object
| Field | Type | Description | When populated | Importance for merchant |
|---|---|---|---|---|
id | string | Payment identifier | At create | Order/payment matching |
amount | integer | Amount in minor unit | At create | Financial intent |
currency | string | Currency | At create | Provider capability and settlement context |
status | string | Payment lifecycle state | Throughout lifecycle | Merchant order state |
customer_id | string/null | Customer relationship | At create if present | Customer tracking |
checkout_session_id | string/null | Hosted checkout relationship | In checkout flow | Links session to payment |
routing_origin | string/null | Last confirm routing origin | After confirm | merchant_direct, autopilot, etc. |
installments | number/null | Installment count | At create | null or 1 for single charge |
metadata | object | Merchant-defined context | Create/update | Order, tenant, or internal reference |
created_at / updated_at | timestamp | Timestamps | System | Audit and operations |
secure_mode, auto_capture, and next_action are used during create/confirm; confirm response carries platform redirect in confirmResult.paymentNextAction (redirect_user_to_url). List/detail DTO may not show all internal fields always; see include_* query flags for expansion.
Charge object
| Field | Type | Description | Provider relationship | Notes |
|---|---|---|---|---|
id | string | Charge attempt identifier | Linked to provider attempt | Multiple per Payment possible |
payment_id | string | Parent Payment relationship | Groups attempts under same Payment | Critical for reporting |
attempt_no | integer/null | Attempt sequence | Routing plan index | Used for trace |
status | string | Charge lifecycle state | Updated from provider result | Authorized/captured/declined distinction |
amount | integer | Attempted amount | Provider request amount | Should align with payment amount |
authorized_amount | number | Authorized amount | After auth | Important before capture |
captured_amount | number | Captured amount | After capture | Financial closure |
refunded_amount | number | Total refunded | After refund | Refund reporting |
payment_provider_id | string/null | Provider identifier | Selected provider | Operational monitoring |
routing_plan_id | string/null | Routing plan relationship | Candidate selection | Fallback analysis |
routing_origin | string/null | Routing origin | Routing engine | Operational visibility |
security | object/null | 3DS/security subset | Orchestrator/adapter merge | Sensitive fields should be masked |
transaction | object/null | Normalized transaction subset | Orchestrator/adapter merge | Not raw provider response |
Payment vs Charge comparison
| Topic | Payment | Charge |
|---|---|---|
| Level | Merchant/business | Provider/rail |
| Count | Usually one per order | Multiple possible per Payment |
| Purpose | Holds payment intent and final state | Holds attempt, authorization, capture, and provider trace |
| Webhook effect | Main source for merchant order state | Operational detail and reconciliation |
| Routing effect | Payment stays the same | Fallback may create new charge attempt |
State fields
Payment state affects merchant order lifecycle. Charge state describes provider attempt status.
Example conceptual state families:
- Payment:
CREATED,REQUIRES_PAYMENT_METHOD,REQUIRES_ACTION,PROCESSING,AUTHORIZED,SUCCEEDED,CANCELED,REFUNDED,EXPIRED - Charge:
CREATED,REQUIRES_ACTION,AUTHORIZED,REQUIRES_CAPTURE,PARTIALLY_CAPTURED,CAPTURED,CANCELED,FAILED,REFUNDED,EXPIRED,DECLINED
Payment has no DECLINED; read decline as Charge DECLINED + Payment REQUIRES_PAYMENT_METHOD.
Use API Reference as source of truth for current enums and response contract.
Amount/currency fields
Amount fields should be designed in minor units. Payment amount is business target; Charge amount is provider attempt amount.
For partial capture or partial refund, interpret Charge capturedAmount and refundedAmount together with Payment top-level state.
Provider references
Provider reference fields are useful for reconciliation and support. However, the full provider raw response should not be treated as the merchant API contract.
Provider-specific fields may change; merchant applications should rely on normalized status, kind, errCode, providerRef, and traceId style public fields.
Metadata
Metadata carries merchant context:
- Order ID
- Tenant/workspace reference
- Campaign or invoice reference
- Internal reporting key
Do not put card data, CVV, provider credentials, secrets, signature material, or sensitive PII in metadata.
Security/3DS fields
3DS, secure mode, and security fields after challenge may vary by provider. In the public model these fields should be limited, masked, and normalized.
Example:
{
"security": {
"secureModeUsed": true,
"threeDSResult": "authenticated",
"liabilityShift": "unknown_or_provider_specific"
}
}This example is conceptual; do not expose real provider security payloads or sensitive fields in public docs.
Event payload relationship
Webhook/event payloads carry Payment state changes to merchant backend. Charge details may be summarized in events or queried via API.
Trust Payment events for merchant order state; use Charge and Routing trace fields for provider attempt analysis.
Example JSON
{
"object": "payment",
"id": "pay_123",
"amount": 100000,
"currency": "TRY",
"status": "SUCCEEDED",
"metadata": { "order_id": "ord_987" },
"charges": [
{
"object": "charge",
"id": "ch_1",
"payment_id": "pay_123",
"attempt_no": 1,
"status": "DECLINED",
"amount": 100000,
"routing_origin": "merchant_direct"
},
{
"object": "charge",
"id": "ch_2",
"payment_id": "pay_123",
"attempt_no": 2,
"status": "CAPTURED",
"amount": 100000,
"routing_origin": "fallback"
}
]
}Backward compatibility notes
- Public response fields should evolve with backward compatibility during migration.
- Private database column names are not the public API contract.
- Merchant integration should be built on the normalized model, not raw provider response.
- When new provider capability or result family is added, docs and SDK behavior should be updated together.