Open Finance Malaysia - Data Provider 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.

Financial-Grade Security

mTLS, JWS signing, JWE encryption, FAPI compliance

OIDC Compliant

Authorization Code flow with id_token via Token Endpoint

RESTful JSON APIs

UTF-8 encoded, 5-second sync timeout, cursor-based pagination

Integration Flow

Security

Mutual TLS (mTLS)

JWS Detached Object Signing with algorithms: PS256, ES384, ES512. Protected headers include: alg, kid, iss, jti, iat, crit. The iat is validated within a 5-minute window.

JWS Message Signing

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.

JWE Data Encryption

Resource data (Account, Balances, Transactions) is encrypted with DC public cert using RSA-OAEP-256 / A256GCM. Responses are JWE inside JWS.

Certificates

PN Signature Cert — PN signs request payloads. JWK use = sig.

DC Signature Cert — DC signs request payloads. JWK use = sig.

DP Signature Cert — DP signs request payloads. JWK use = sig.

DC Encryption Cert — DP encrypts data with DC cert. JWK use = enc.

JWKS responses should be cached for a maximum of 15 minutes. During key rotation, old and new keys coexist with different kid values.

private_key_jwt Authentication

Used by PN when calling the DP Token Endpoint. The client_assertion JWS body includes:

Parameter Req Type Description
iss R String(36) Client ID (PayNet OFP).
sub R String(36) Client ID (PayNet OFP).
aud R String(300) DP Token Endpoint URL or issuer value.
nbf O Integer Not-before Unix timestamp.
exp R Integer Expiry Unix timestamp (max 10 min).
iat R Integer Issued-at Unix timestamp.
jti R String(36) Unique JWT ID for replay detection.

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."
}

Authorization Server (AS)

The Data Provider exposes an OAuth 2.0 / OpenID Connect Authorization Server (AS) for consent and token flows. Only the endpoints listed below are exposed on the public ingress.

For the mock DP environment the AS issuer is https://api.dp-as.openfinance.dev.inet.paynet.my/.

Using the discovery (issuer) endpoint

  1. Start from the issuer URL
    The AS base URL (issuer) for this environment is https://api.dp-as.openfinance.dev.inet.paynet.my/. The issuer 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.dp-as.openfinance.dev.inet.paynet.my/.well-known/openid-configuration
      This document contains issuer, authorization_endpoint, token_endpoint, jwks_uri, userinfo_endpoint, and other metadata. Use these URLs for all subsequent requests; do not hardcode paths.
  3. Use the URLs from the discovery response
    Use the values from the discovery response for authorization, token exchange, UserInfo, and JWKS. Exact paths may differ by deployment; discovery is the source of truth.

AS endpoints

Each of the following endpoints is exposed on the public ingress. Exact URLs are also provided in the discovery document.

Method Endpoint Purpose Specification / RFC
GET /.well-known/openid-configuration Discovery / issuer metadata OpenID Connect Discovery 1.0, RFC 8414 (OAuth 2.0 AS Metadata)
GET /.well-known/jwks.json JSON Web Key Set (token validation) RFC 7517 (JWK)
GET /oauth2/auth Authorization (user consent) RFC 6749 §3.1 (OAuth 2.0)
POST /oauth2/token Token exchange RFC 6749 §3.2 (OAuth 2.0)
POST /oauth2/revoke Revoke access or refresh token RFC 7009 (Token Revocation)
GET /oauth2/sessions/logout OpenID Connect logout (front- and back-channel) OpenID Connect Session Management, Back-channel
GET /userinfo OpenID Connect UserInfo OpenID Connect Core 1.0 (UserInfo)

Resource Server

Account Balances

PayNet retrieves an account balances information from DP.

path Parameters
account_id
required
string

AccountID is the account identifier (path).

query Parameters
consent_id
string

ConsentID is the consent identifier (required, query or header).

Responses

Response samples

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

Consent Event

Description: PayNet notifies DP when consent is created or updated.

Request Body schema: application/json
event_type
string
Default: "consent_event_type_unspecified"
Enum: "consent_event_type_unspecified" "consent_created" "consent_updated" "consent_status_updated"

EventType is the consent event type (PayNet section 13).

object

Data is the consent object.

Responses

Request samples

Content type
application/json
{
  • "event_type": "consent_event_type_unspecified",
  • "data": {
    }
}

Response samples

Content type
application/json
{ }

Update Consent

DP updates consent status and user info after the user authorizes the consent.

path Parameters
consent_id
required
string

ConsentID is the consent identifier (from path parameter).

Request Body schema: application/json
consent_id
string

ConsentID is the consent identifier (from path parameter).

status
string

Status is the consent status (32 chars, required).

id_token
string

IDToken is the JWT issued by the Data Provider (3000 chars, required if status = Authorized).

object

UserIdentity is the user identity object (required if status = Authorized).

Array of objects

Accounts is the list of consent account objects (required if status = Authorized).

Responses

Request samples

Content type
application/json
{
  • "consent_id": "string",
  • "status": "string",
  • "id_token": "string",
  • "user_identity": {
    },
  • "accounts": [
    ]
}

Response samples

Content type
application/json
{ }