Open Finance Malaysia - Data Consumer Documentation

Download OpenAPI specification:Download

Overview

Paynet OFP enables secure, consumer-consented access to financial data across Malaysian institutions — banks, fintechs, pension providers, insurers, and more. The platform connects Data Consumers (DCs) requesting user data with Data Providers (DPs) supplying it, mediated through Paynet's Authorization Server and Resource Server.

Authorization Server

Manages consent, authentication, OAuth 2.0 tokens, and enforces FAPI 2.0 security.

Resource Server

Serves financial data — accounts, balances, transactions — behind valid access tokens.

FAPI 2.0 Compliant

PAR, PKCE S256, sender-constrained tokens, asymmetric auth, RFC 9207 issuer ID.

Integration Flow

Authorization Code Grant Flow

The primary flow for obtaining user-consented access to financial data.

  1. End User initiates consent on the DC application.
  2. DC pushes authorization request POST /par with client_id and signed JAR containing authorization_details.
  3. Paynet OFP returns request_uri to DC
  4. DC redirects user to Paynet OFP GET /authorize with only client_id and request_uri.
  5. Paynet OFP redirects to DP, User is forwarded to the Data Provider's authorization endpoint.
  6. User authorizes logs in, selects accounts, and grants consent on DP.
  7. DP redirects user back to Paynet's redirect_uri.
  8. Paynet OFP redirects to DC with Authorization code returned as query parameter. Valid for 60 seconds.
  9. DC exchanges code for tokens via POST /token with authorization_code grant, code_verifier (PKCE), and client auth.
  10. Paynet OFP returns access_token, id_token, refresh_token, and authorization_details to the DC.

Refresh Token Flow

When an access token expires, the DC uses the refresh token to obtain a new one without re-authenticating the user. Per FAPI 2.0, the AS does not rotate refresh tokens — the same refresh token remains valid across multiple access token renewals.

Consent Revocation Flow

The DC obtains a client_credentials access token, then calls POST /consents/{consent_id}/revoke. OFP revokes the consent and notifies the DP via webhook.

Resource Server Flow

The DC sends a GET request with the access_token and an x-signature JWS header. OFP introspects the token, verifies the signature, forwards to the DP. The DP encrypts the response data with the DC's public encryption key (JWE inside JWS) and returns it through OFP to the DC.

Security

This specification conforms to the OpenID FAPI 2.0 Security Profile (Final, 19 Feb 2025). All authorization interactions between DCs and the Paynet OFP Authorization Server must follow these requirements.

Mutual TLS (mTLS)

All API connections require mutual TLS authentication. Both client and server present certificates, establishing bidirectional trust. TLS 1.2+ is mandatory with BCP 195 cipher suites.

Sender-Constrained Access Tokens

Access tokens are bound to the client's mTLS certificate. When the DC presents an access token to a Resource Server, the RS introspects the token to obtain the certificate thumbprint (cnf.x5t#S256) and validates it matches the mTLS connection. Tokens MUST NOT be transmitted in query strings.

Pushed Authorization Requests (PAR)

All authorization requests must go through the PAR endpoint (RFC 9126). The AS rejects any authorization request not initiated via PAR. The request_uri is valid for less than 600 seconds. Only client_id and request_uri may be sent to the /authorize endpoint.

PKCE (S256)

Every authorization request must include a fresh, cryptographically random code_challenge using the S256 method. The plain method is prohibited. The code_verifier is validated at the token endpoint.

Issuer Identification (RFC 9207)

The AS includes the iss parameter in every authorization response. DCs MUST compare this against the issuer value from the .well-known metadata and reject mismatches.

Client Authentication

Only asymmetric methods are permitted: private_key_jwt, tls_client_auth, or self_signed_tls_client_auth. Shared secret methods (client_secret_basic, client_secret_post, client_secret_jwt) are prohibited.

Refresh Token Policy

Refresh tokens MUST NOT be rotated. Per FAPI 2.0, rotation provides no security benefit with sender-constrained tokens and risks interoperability issues.

Cryptographic Requirements (FAPI 2.0 §5.4.1)

Requirement Detail
JWS Algorithms PS256, ES256, EdDSA (Ed25519) only. RS256, none, etc. are prohibited.
JWE Algorithms RSA-OAEP-256 (key encryption), A256GCM (content encryption).
RSA Key Size ≥ 2048 bits.
EC Key Size ≥ 160 bits effective security. P-256 and Ed25519 both qualify.
Credential Entropy Authorization codes, access tokens, and refresh tokens must have ≥ 128 bits of entropy.
JWT Best Practices RFC 8725 compliance: verify alg against allowlist, validate all claims, avoid x5u/jku headers.
TLS TLS 1.2+ with BCP 195 cipher suites. HSTS on browser-facing endpoints. No CORS on /authorize.

JWS Message Signing

All JWS headers must include alg (PS256/ES256/EdDSA) and kid (x5t#S256 certificate thumbprint). Timestamps (nbf, iat, exp) are used for replay protection. The AS accepts JWTs with iat/nbf up to 10 seconds in the future but rejects those more than 60 seconds ahead.

For resource API requests, the DC signs request parameters into an x-signature header JWS. Resource API responses are returned as a JWE (encrypted with DC's public key) nested inside a JWS (signed with DP's private key).

Error Codes

HTTP Status Codes

Code Description
200 OK
201 Created
204 No Content
303 Redirect
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
405 Method Not Allowed
429 Too Many Requests
500 Internal Server Error
503 Service Unavailable

OAuth 2.0 Error Codes

Returned in error responses from authorization and token endpoints.

Code Description
invalid_request Missing or invalid parameter.
invalid_client Client authentication failed.
invalid_grant Invalid, expired, or revoked grant/code.
unauthorized_client Client not authorized for this grant type.
unsupported_grant_type Grant type not supported.
access_denied Resource owner or AS denied the request.
invalid_scope Invalid or unknown scope.
server_error Unexpected server-side condition.
temporarily_unavailable Server overloaded or in maintenance.

Account & Application Error Codes

Code Description
Consent.AccountTemporarilyBlocked Account temporarily blocked by DP business rule.
Consent.PermanentAccountAccessFailure Account permanently unavailable.
Consent.TransientAccountAccessFailure Account unavailable due to transient failure.
AccessToken.InvalidScope Token does not have required scope.
Consent.Invalid Consent is in an invalid state.
Consent.BusinessRuleViolation DP business rule prevents the operation.
JWS.InvalidSignature JWS signature verification failed.
JWS.InvalidClaim One or more JWS claims failed validation.
JWE.DecryptionError JWE decryption failure.

Error Response Format

Error Response Body

{
  "error": "invalid_grant",
  "error_description": "The authorization code has expired."
}

Rate Limiting

When receiving HTTP 429 (Too Many Requests), implement retry with exponential backoff to avoid overwhelming the platform.

Attempt Wait Time
Initial Immediate
Retry 1 5 seconds
Retry 2 10 seconds
Retry 3 20 seconds
Retry 4 40 seconds

Authorization Server (AS)

The PayNet Open Finance Platform exposes a FAPI 2.0–compliant Authorization Server (AS) for OAuth 2.0 and OpenID Connect flows. Integrators should use discovery to obtain all AS endpoints and metadata instead of hardcoding URLs.

For this environment the AS issuer is https://api.as.openfinance.dev.inet.paynet.my.

Using the discovery (issuer) endpoint

  1. Start from the issuer URL
    You will receive the AS base URL (issuer) for your environment (e.g. from the Partner Dashboard or onboarding). The issuer is the logical identifier of the AS and must match the iss claim in tokens and authorization responses.

  2. Fetch the discovery document
    Request the OpenID Connect / OAuth 2.0 metadata at:

    • https://api.as.openfinance.dev.inet.paynet.my/.well-known/openid-configuration
      This document (see OpenID Connect Discovery 1.0 and RFC 8414) contains:
    • issuer — the AS issuer URL (validate that it matches the iss in responses and tokens).
    • authorization_endpoint, token_endpoint, jwks_uri, pushed_authorization_request_endpoint, userinfo_endpoint, and optionally introspection_endpoint, revocation_endpoint.
    • Supported algorithms, scopes, response types, and other capabilities.
  3. Use the URLs from the discovery response
    Use these values for all subsequent requests (authorization, token exchange, PAR, UserInfo, JWKS). Do not hardcode paths; environments may differ.

AS endpoints (discovered via metadata)

The following endpoint types are exposed by the AS. Exact URLs are provided in the discovery document; this list is for reference only.

Purpose Typical path (from discovery) Specification / RFC
Discovery / issuer metadata /.well-known/openid-configuration OpenID Connect Discovery 1.0, RFC 8414 (OAuth 2.0 AS Metadata)
Authorization (user consent) e.g. /authorize RFC 6749 §3.1 (OAuth 2.0)
Token exchange e.g. /token RFC 6749 §3.2 (OAuth 2.0)
Pushed Authorization Request (PAR) e.g. /par RFC 9126 (PAR)
UserInfo e.g. /userinfo OpenID Connect Core 1.0 (UserInfo)
JSON Web Key Set (JWKS) from jwks_uri in discovery RFC 7517 (JWK), used for token validation

The AS follows the FAPI 2.0 Security Profile (e.g. authorization code flow, PKCE S256, PAR where required). Behaviour and required parameters are defined by FAPI 2.0, OAuth 2.0, and OpenID Connect; use the discovery document and those specifications as the source of truth.

FAPI 2.0–compliant clients

To reduce integration effort and avoid common mistakes, use a client library or product that is FAPI 2.0–compliant (or certified). The OpenID Foundation provides conformance tests and certification for both Authorization Servers and OAuth/OIDC clients. For certified implementations and test tools, see:

Choosing a client that has passed FAPI 2.0 conformance tests (or is listed as certified) helps ensure correct use of PAR, PKCE, and other security requirements of the platform.

Resource Server

Account Balances

DC retrieves an account balances information from DP via PayNet.

Authorizations:
path Parameters
account_id
required
string

AccountID is the unique identifier for the account.

query Parameters
consent_id
string

ConsentID is the consent identifier for authorization.

Responses

Response samples

Content type
application/json
{
  • "data": "string"
}

Retrieve Consent

DC retrieves an existing consent using the consent ID. The DC may also use this endpoint to obtain the list of accounts associated with that consent.

Authorizations:
path Parameters
consent_id
required
string

ConsentID is the unique consent identifier (path parameter).

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}