Transaction Parameters

When receiving payments on a website, the visitor would usually get to a page at which to make payment. At this time, we would already know:

  1. The visitor's unique identifier (This is usually an email on most websites)
  2. The amount they should be charged
  3. Whether the payment will be recurring.
  4. The item(s) for which they will be making payment.

At this point, Paystack can be called upon. It is from this point that the posts in this series will guide you to concluding integration.

1. Email

As mentioned in the introduction, we expect that your site already has a unique identifier for the visitor. This is important as it makes it possible for us to help when a customer's history is required to resolve an issue. It also makes it possible to isolate customers' transactions in order to avoid known patterns of fraudulent payments. If your customers provide unique email addresses, then purrfecttt! This step is done.

For sites which do not use email addresses to identify their customers or whose customers' emails need to be kept secret for policy reasons, we would encourage the following course:

  1. Use <unique identifier>@a-subdomain.your-site.tld as each customer's email. Some common patterns include
    • <phone_number>@payments.the-site.tld
    • <random hash which is unique to user>@users.the-site.tld
    • user<id_in_db>@the-site.tld
    • <username_on_site>@the-site.tld


Use a domain or subdomain that exists

Ensure that even while testing, you use an email you have access to and which can receive emails.

  1. Implement a catchall script on the subdomain that forwards the emails to the respective customers as an in-app message.


E-mail address obtained

"email": "[email protected]"

2. Amount (required if not recurring)

How much should we charge the visitor? It is important to note that we will deduct our fees from the transaction amount before adding to your payout. If you intend to pass our fees onto the visitor, you will need to do some maths :1234:. There is a github class here that can help a PHP developer with this. Translations are very much welcome and will be added to a list that can help others :+1:

All amounts on Paystack should be sent in the lowest denomination for the currency. For NGN payments, this means you should send the kobo equivalent.


Always send a kobo value for amount

e.g. to accept 120 Naira 50 Kobo, send 12050 as the amount


Amount obtained

"amount": 12050

3. Plan (required if recurring)

If you want the payment to be recurring, the visitor will have to be subscribed to a Paystack Plan. If this will not be recurring, don't send a plan.


Plan amount overrides amount sent

When we receive both amount and plan, the amount sent is ignored.

Plans can be managed on your Paystack dashboard at When a plan is created, you get a "Plan Code". Specify that when creating the transaction so that a successful payment subscribes the visitor to your plan.


Recurring payment? Add a plan!

"plan": "PLN_code"

4. Metadata (optional)

You should add metadata to your transactions so that information stored can be very complete. As a plus, if you add them as custom fields, we will display on your dashboard along with other transaction details. Crafting metadata will depend on your language's handling of JSON. Common metadata are:

  • Invoice ID
  • Cart ID
  • Cart Items
  • Payment medium (site/app)

Rather than crafting an almost human readable reference, we encourage you to add metadata to your transaction.

The custom_fields key is reserved for an array of custom fields that should show in the email alert you get and on the dashboard when you click the transaction. Custom fields have 3 keys: display_name, variable_name and value. The display name will be the title for the value when displaying.

As a sample sending the metadata below:

      "display_name":"Invoice ID",
      "variable_name":"Invoice ID",
      "display_name":"Cart Items",
      "value":"3 bananas, 12 mangoes"

will ensure that the Cart Items and Invoice ID show on your alert and Dashboard while the cart_id is only available programmatically.


Metadata set

"metadata":{"cart_id":398,"custom_fields":[{"display_name":"Invoice ID","variable_name":"Invoice ID","value":209},{"display_name":"Cart Items","variable_name":"cart_items","value":"3 bananas, 12 mangoes"}]}

5. Reference (optional)

We recommend that you provide a reference for your transactions. Each reference being non-random, but rather tied to each transaction.

For instance, a good reference for an automatic charge done daily would be charging-cus10-day5. We have experienced scenarios that could have easily been avoided if the reference had been non-random, non-timestamp. Because network issues sometimes cause a delay in processing, some transactions may be created later than usual. If you use a crafted reference, you will 100% avoid creating a second transaction debiting the customer twice if this happens.


Craft your references

✘ Avoid the lure of "easily" generating random references or using timestamp-based references.
✔︎ Pick references from an auto-increment column
✔︎ Make your reference easy to read. e.g. customer10-cart4-checkout

All transactions can be resumed by loading them inline or on our mobile SDKs with same reference, email and amount. You will reduce abandonment statistics by resuming transactions with an existing reference if payment is still expected for same amount from same person for same value proposition. Do note that if you set a payment session timeout, transactions that are older than the timeout will not allow new attempts.

Do note that:

  1. Only send Alphanumeric characters and -, . and =. Other characters are invalid (no spaces, newlines etc).
  2. Our references are case sensitive

What’s Next

All set? One last thing...