Reporting

 

WePay requires platforms to perform reconciliation and other custom reporting. Merchants rely on reconciliation reporting in order to match funds collected, failed, refunded, and disputed against funds paid out. Other custom reports that your platform can build out include transaction history reports for your merchants as well as revenue reports for your platform. Here’s a guide on how to build out reporting tools leveraging the WePay APIs.

Setup and Reporting Basics

 

Reporting Notifications

 

Subscribe to the following notification event topics with a reporting-specific callback URI:

  1. accounts.negative_balance
  2. adjustments.created
  3. disputes.created
  4. disputes.funds_withdrawn
  5. disputes.funds_reinstated
  6. disputes.resolved
  7. payments.created
  8. payments.completed
  9. payments.completed
  10. payments.canceled
  11. payouts.created
  12. payouts.completed
  13. payouts.completed
  14. payouts.failed
  15. recoveries.created
  16. recoveries.completed
  17. recoveries.failed
  18. refunds.created
  19. refunds.created
  20. refunds.failed

Note that transaction records can take time to build, so the value for transaction record parameters in notifications may be null. In these instances, delay a lookup of the resource by a few minutes in order to retrieve any needed transaction record IDs.

WePay recommends using a reporting-specific callback URI on top of normal notification subscriptions so that your platform can automate reporting activity independently of routine information updates and system notifications to your end users.

Reference IDs

WePay API resource IDs are not intended for public consumption. As such, WePay recommends displaying IDs relevant to your system and utilizing the reference_id in the WePay API in order to map your system objects to WePay API objects.

As an example, you may want to prefix reference IDs with the merchant user ID for your platform. Remember, you can create WePay API objects with a reference ID, or add it later. An entry in your database might look like this:

Platform User ID WePay Account ID WePay A Reference ID WePay Payment ID WePay P Reference ID
U123 d3f61e56-5d99-4895-af2d-a07ab48476e9 U123-9y8435y234 21763483-12be-4d07-afe3-ab81a962f3e5 U123-85981900

This being the case, you would then display U123-85981900 in your UI in place of the WePay payment ID, U123-9y8435y234 in place of the WePay account ID, and U123 in place of the WePay legal entity ID. Please keep in mind that the WePay legal entity resource is not a 1:1 translation into a user, and your platform may decide to allow your merchants to create multiple legal entities per platform account.

Transaction Records

Transaction Records are the WePay API resource primarily designed for reporting. A transaction record contains important reporting information:

  • gross_amount – The total amount of money moved.
  • net_amount – The total amount of money moved, less fees.
  • fee_amount – Depending on the owner resource, either platform or WePay fees.
  • currency – The currency of the associated transaction.
  • type – The type of associated resource (i.e. payment, refund, etc.)
  • owner – A structure defining the associate resource’s ID and path.

Each transactional resource (payment, refund, payout, etc.) has an associated transaction record which will be returned upon an API request to that resource. Additionally, the platform fee associated with the transaction will have its own transaction record. Here is a breakdown of the transaction record parameters that will appear on different resources:

Resource Transaction Record Parameters
Payments txnr_app_fee
txnr_merchant
Refunds txnr_merchant_refund
txnr_app_fee_refund
Payouts txnr_payout
txnr_failure
Recoveries txnr_recovery
txnr_failure
Disputes txnr_chargeback_app_fees
txnr_chargeback_merchant
txnr_chargeback_reversal_app_fee
txnr_chargeback_reversal_merchant
txnr_merchant_chargeback_fee
Adjustments txnr_adjustment

Looking up individual transaction records will help to answer questions about a specific transactional resource, like “Why is the fee on this payment $10.02 instead of $10.01?”

An array of transaction records can be retrieved based on an account or payout ID, as well, which is invaluable to reconciliation and historical reporting. For instance, this request will return an array of transaction records for all transactional resources associated with account ID d3f61e56-5d99-4895-af2d-a07ab48476e9:

GET
curl -X GET \
/transaction_records?account_id=d3f61e56-5d99-4895-af2d-a07ab48476e9 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Generate Reports

 

You have a few options to generate reports:

  • Generate reports directly from WePay transaction records
  • Generate reports from your payment logs

We’ll discuss more about each method later, and the options are not limited to those listed. As we walk through this guide, keep the options and possibilities in mind and decide which method works best for your architecture and system design.

As a platform, you’ll need to provide a minimum of three different reports, and other sections of this guide will walk through how to build:

  1. Merchant transaction history reports
  2. Merchant reconciliation reports
  3. Platform revenue reporting

Before going over those specifics, it’s important to think through and design your entire reporting system.

Pagination

If your UI provides a time-range filter for merchants to only view transactions from a given time period, include the create_time_start and/or the create_time_end parameters. For instance, if a merchant elects to view their transaction history from 7/1/2019-7/7/2019 PST, your request body should look like this:

GET
curl -X GET \
/transaction_records?account_id=YOUR_MERCHANT’S_ACCOUNT&create_time_start=1561964400&create_time_end=1562482800 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

The API response will include previous and next parameters which must be used either to paginate the transaction history report, or to fabricate a single continuous report.

After the first set of results are returned via the API, send subsequent GET /transaction_records requests. The only difference from the initial request will be the inclusion of the page parameter. Here, you will use the value from the next response parameter that you just received as the value for the page request parameter you’re about to send. For instance, if the response to the initial GET request included ”next”: “/transaction_records?page=cccde123fgh456”, then your subsequent GET request would look like this:

curl -X GET \
/transaction_records?account_id=YOUR_MERCHANT’S_ACCOUNT&create_time_start=1561964400&create_time_end=1562482800&page=cccde123fgh456 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Note that using the pagination feature (i.e. page parameter) precludes customization of the number of results per page; ten results will be returned per page after the initial GET request.


Validate Reports

 

Before and after generating a report, it’s best practice to validate your data to ensure reporting accuracy. Using reporting-specific callback URIs enhances your options for sanity checks before sending data to your separate reporting server:

  • Validate reporting notifications against your system data
  • Validate reporting notifications against WePay transaction records

Validation against your system data involves building payment data sets based on API logs which get updated upon changes in data. Changes in data can be identified through notifications and GET requests. To validate:

  1. Compare reporting notifications with your system data before submitting data to your payments database
  2. Compare a report with your system after generating it

Note

Payment data sets should also be validated against your platform information to ensure consistency and accuracy. For instance, if you platform has an invoice object correlated to a WePay payment ID, you can update your invoice object as paid once the WePay payment has an API status of complete.

Similarly, an invoice object should become refunded if:

  • Your platform receives a refunds.created notification with the relevant payment.id,
  • Or if your platform sends a GET /payments/{id} request where the amount_refunded parameter has a value greater than 0.

Validation against WePay transaction records should be used if your platform is serving reports based on your system data rather than based on the WePay transaction record API resource. Compare data points present in the report you generate with parallel data points from the associated transaction record to validate.


Merchant Reports

 

Merchants need access to a transaction history for their account(s). Using the GET /transaction_records request, your platform can automatically pull a collection of this information via the WePay API based on:

  • account_id
  • payout_id

A request based on your merchant’s account ID will look like this:

curl -X GET \
/transaction_records?account_id=YOUR_MERCHANT’S_ACCOUNT \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Alternatively, you can generate merchant reports based on your own payments data.

Transaction History Reports

 

1. Generate

As reporting notifications are received, log the details in order of their create_time and look up the transaction records to provide further details to your merchants. This method allows your platform to compile accurate transaction history reports as updates occur, as opposed to polling the WePay API blindly. Suggested transaction history fields to provide in a report include:

  • Resource type (payment, payout, refund, etc)
  • Resource ID
  • Time created
  • Time updated
  • Current status
  • Gross
  • Net
  • Currency
  • To/From (e.g. in cases of refunds, a refund will be TO a payer; in cases of payments, a payment will be FROM a payer)

These are basic suggested fields, so keep in mind that your client base may find other fields useful. Consider the available parameters on all transaction-related resources in order to identify the account transaction history information necessary for your platform.

2. Serve and Export

You should give merchants the option of exporting their account transaction history. For instance, most merchants would like to download reports as a .csv file. There are plenty of third party json/.csv converters, or you can build a solution in-house using resources and guides on Stack Overflow.

WePay also recommends providing basic data tools for your merchants to use. For instance, once a basic report is generated via WePay transaction records, provide data visualization tools to allow merchants to see their growth, best selling products, chargeback rates, etc. UIs to reorganize and/or pick and choose report columns are also valuable tools.


Reconciliation Reports

 

Reconciliation reports are required to help merchants understand the contents of their payouts as related to the contents of their accounts.

1. Generate

When a payouts.created notification is received and followed by a payouts.completed notification, begin compiling a reconciliation report for that payout by making a GET /transaction_records request with the payout_id:

curl -X GET \
/transaction_records?payout_id=9c19298b-319e-49f9-aa38-0de8469e7dc1 \ // ID from notification
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

The API response will provide an array of all transaction records related to that payout, which you will then parse into consumable reports. Suggested reconciliation report fields to include:

  • Payout ID
  • Payout date
  • Resource type (payment, refund, etc)
  • Resource ID
  • Gross - Indicate if this is a credit or debit to the account
  • Fees - Indicate if this is a credit or debit to the account
  • Net - Indicate if this is a credit or debit to the account

Note

Validation for reconciliation reports is not necessary, as your platform will not have the ability to predict the resources included in a payout. Because WePay controls payout limits, manual reviews, and other factors impacting the contents of payouts, WePay validates payout-based transaction records for you.

2. Serve and Export

In a UI reconciliation report, merchants should be able to click through a resource ID in order to view details about that specific object. In a system which relies on live API calls for data, simply make the GET /resource/{id} request when an item is clicked-through. For instance, if a merchant wants to see details of a payment, call GET /payments/{id} upon click:

curl -X GET \
 /payments/9c19298b-319e-49f9-aa38-0de8469e7dc1 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

For example, a merchant looking through their latest reconciliation report wants to view specific details regarding a payment included in that report. The reconciliation report itself might provide amount information (gross, fees, net, etc), but the merchant wants additional information about that payment. When they click on the resource ID (which in this case is the payment ID) in the UI report, a payment details page loads.


Platform Reports

 

As a platform, you’ll use WePay transaction records for your own revenue reporting.

Platform Revenue

 

As a platform, you’ll want to build out a reporting system to collect data related to your own revenue from WePay transactions. Here, we’ll go over the basics on building out that system, which will rely on the txnr_app_fee.id parameter of the payments resource.

1. Generate

When you receive a payments.created notification followed by a payments.completed notification, use the txnr_app_fee.id value to make a GET /transaction_records/{id} request:

curl -X GET \
/transaction_records/9c19298b-319e-49f9-aa38-0de8469e7dc1 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Data points from the transaction records resource which are vital to platform revenue reporting include:

  • create_time
  • gross_amount - Indicate if this is a debit or credit
  • fee_amount - Indicate if this is a debit or credit
  • net_amount - Indicate if this is a debit or credit
  • owner.resource (this will be payments, refunds, disputes, etc.)
  • owner.id - This will be your platform’s account ID

Store your platform revenue data in a separate data set.

In designing your platform revenue data set, plan for the following columns, as well:

  • reference_id from the payments resource
  • payment.id from the refunds and disputes resource

These will need to be retrieved from your general payments data set during parsing, or retrieved live from API responses. This is because those parameters are not present on transaction records resources.

Handline Refunds If you receive a refunds.created notification followed by a refunds.completed notification, store the payload.id, txnr_app_fee_refund.id, and payload.payment.id (which will identify the original impacted payment).

Use the txnr_app_fee_refund.id value to make a GET /transaction_records/{id} request:

curl -X GET \
 /transaction_records/9c19298b-319e-49f9-aa38-0de8469e7dc1 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Make a new entry in your platform revenue data set which includes the following:

Handling Disputes If you receive a disputes.created notification followed by a disputes.funds_withdrawn notification, then store the payload.id, txnr_chargeback_app_fees.id, and payment.id.

Use the txnr_chargeback_app_fees.id value to make a GET /transaction_records/{id} request:

curl -X GET \
 /transaction_records/9c19298b-319e-49f9-aa38-0de8469e7dc1 \
 -H "App-Id: 121212" \
 -H "App-Token: prod_MTAwXzk5OWIwZT666LWYwNWItNDU4MS1iZjBiL" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Make a new entry in your platform revenue data set which includes the following:

It is possible that a dispute can be reversed, depending on what the card issuer or card networks determine. If this happens, your platform will receive a disputes.resolved notification and a disputes.funds_reinstated notification. At this point, use the txnr_chargeback_reversal_app_fee.id value.

2. Serve and Export

You’ll want to serve your revenue reports to your internal finance teams. This involves parsing reports from raw data into a .csv file, or any other format needed.