How To Write Your Policies

Policy Language: Rego (Open Policy Agent)

PayMongo policies are written using Rego, the policy language from Open Policy Agent (OPA).

Rego is a purpose-built language for defining authorization and decision rules. It is widely used to express who can do what, under which conditions, in a clear and auditable way.

By using Rego, PayMongo enables you to:

  • Write expressive and flexible policy rules
  • Evaluate policies consistently at runtime
  • Update business rules without changing application code

How PayMongo Uses Rego

When an operation is performed (for example, a wallet transfer), PayMongo:

  • Identifies all active policies that match the resource and operation
  • Evaluates each policy using Rego
  • Collects the decision (allow or deny) from each policy
  • Allows the operation only if all policies allow it

Your Rego policy does not execute the action itself. It only decides whether the action should be allowed.


Resources and Operations

Policies are always evaluated against:

  • A resource (what the policy applies to)
  • An operation (the action being performed)

PayMongo provides a predefined set of supported resources and operations. Examples include:

  • Resource: wallet
  • Operation: CreateTransfer

Only these predefined combinations are evaluated by the system.

📘

Important

The full and up-to-date list of supported resources and operations is available on the Parameters page.


Violations

When a policy blocks an operation, PayMongo returns not only a deny decision, but also a list of violations explaining why the action was rejected. Violations allow you to display clear, user-friendly error messages in your application.

A violation is a structured reason returned by a policy when a rule is not satisfied.

For example, a policy might determine:

  • The user is not authorized
  • The amount exceeds a limit
  • The destination account is not approved

Instead of only returning “denied”, the policy includes violation codes that describe the exact issue.

PayMongo maintains a predefined list of supported violation codes and their corresponding error messages. These are documented on the Parameters page. Each violation code maps to a specific message that your system should display.

Example (conceptual):

ViolationError Message
identity:requiredAuthentication required
destination_account:not foundDestination account not found
transfer:exceededTransfer amount exceeded the allowed limit
📘

Always refer to the Parameters page for the official list.

When writing your policy:

  • Use only violation codes listed on the Parameters page
  • Return violations only when a rule fails
  • Ensure violations accurately describe the failed condition

This ensures your application can reliably map violations to the correct user message. If your policy returns a violation code that is not listed on the Parameters page:

  • PayMongo cannot map it to a specific message
  • A generic error message will be used instead

Example of generic message:

“This action is not allowed due to policy restrictions.”

To avoid this, always use the official violation codes.


Policy Input Data

When your policy is evaluated, PayMongo passes structured input data into the Rego engine. This input contains contextual data relevant to the operation. You can use this input data to define your policy rules.

Rego policies evaluate the input provided by PayMongo.

Conceptually, a policy answers questions like:

  • Is the user’s role allowed?
  • Is the transfer amount within limits?
  • Is the destination account approved?
  • Is the operation happening at an allowed time?

Example (Conceptual)

“Allow wallet transfers only if the user role is finance_admin and the amount is below the maximum limit.”

Your policy would:

  • Read the user role from the input
  • Read the transfer amount from the input
  • Return allow = true only if both conditions are met

All of these checks are done using the input data where the exact field names and structure are defined in the Parameters page


Policy Structure and Conventions

When writing Rego policies for PayMongo:

  • Policies must return a clear allow or deny decision
  • Use only documented input fields
  • Avoid assumptions about missing data
  • Keep policies focused and readable

PayMongo evaluates policies in a standardized way to ensure consistent behavior across all merchants. This is achieved by defining the output of the policies that merchants must follow and achieve when writing their policies.

Output example:

{
  "allow": false,
  "violations": [
    "source_account_daily_limit_exceeded"
	]
}

You can use this Rego template to achieve that desired output.

package <resource>.<operation>

default allow := false

allow if {
  count(violations) == 0
}

Example

PayMongo evaluates wallet resource and CreateTransfer operation upon creating a transfer with input data sent into the evaluation as follows:

{
    "account_limits" : {
        "daily": {
            "in" : 99999999999,
            "out": 250000
        },
        "monthly": {
            "in" : 15000000,
            "out": 99999999999
        }
    },
    "current_usage" : {
        "daily": {
            "in" : 0,
            "out": 200000
        },
        "monthly": {
            "in" : 0,
            "out": 0
        }
    },
    "type": "out",
    "current_transaction_amount": 100000
}

With this input, you can create a policy to check whether the transfer will exceed the daily cash out limit of the account as follows:

package wallet.CreateTransfer

default allow := false

allow if {
  count(violations) == 0
}

violations contains "source_account_daily_limit_exceeded" if {
	input.current_usage.daily.out + input.current_transaction_amount > input.account_limits.daily.out
}

This policy will deny the transaction as the current transaction will violates the account daily limit if carried. The response of the policy evaluation will be :

{
  "allow": false,
  "violations": [
    "source_account_daily_limit_exceeded"
	]
}