Build Reporting

 

We require platforms using the Clear integration to perform reconciliation and other custom reporting. While reporting is only required for Clear integrations, platforms going through Link integrations may also find this guide useful.

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.canceled
  10. payouts.created
  11. payouts.completed
  12. payouts.failed
  13. recoveries.created
  14. recoveries.completed
  15. recoveries.failed
  16. refunds.created
  17. refunds.failed

We also recommend 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, we recommend 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 IDWePay Account IDWePay A Reference IDWePay Payment IDWePay P Reference ID
U123d3f61e56-5d99-4895-af2d-a07ab48476e9U123-9y8435y23421763483-12be-4d07-afe3-ab81a962f3e5U123-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

The Transaction Records API resource will be used heavily in reporting, in conjunction with Notifications. Note that transaction records can take time to build, so the value for the Transaction Record parameters in Notifications may be null when the Notification is received. Transaction records may be delayed up to 6 hours, so we recommend:
  1. Upon receipt of a Notification, check for Transaction Record IDs. If null, move to step 2.
  2. Send a GET request for the resource in question 3 hours after initial receipt of its Notification. If Transaction Record information is still not present, move to step 3:
  3. Send a GET request for the resource in question 6 hours after the initial receipt of its Notification.

A transaction record contains the following 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 (e.g. payment, refund, etc.).
  • owner -- A structure defining the associated 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:

ResourceTransaction Record Parameters
Paymentstxnr_app_fee
txnr_merchant
Refundstxnr_merchant_refund
txnr_app_fee_refund
Payoutstxnr_payout
txnr_failure
Recoveriestxnr_recovery
txnr_failure
Disputestxnr_chargeback_app_fees
txnr_chargeback_merchant
txnr_chargeback_reversal_app_fee
txnr_chargeback_reversal_merchant
txnr_merchant_chargeback_fee
Adjustmentstxnr_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:
Copy
Copied
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" \
Note
The create_time_start parameter will default to 7 days in the past and the create_time_end parameter will default to the current time if they are not otherwise specified. Additionally, the interval between create_time_start and create_time_end cannot exceed 35 calendar days.

Get a Single Payout from Transaction Records

Providing the payout_id parameter in a GET/ transactions_records request will make both the create_time_start parameter and the create_time_end not applicable, like mentioned in the above note, and will return the single payout matching the payout_id.
Copy
Copied
GET
curl -X GET \
/transaction_records?account_id=YOUR_MERCHANT'S_ACCOUNT&payout_id=PAYOUT_ID \
 -H "App-Id: 121212" \
 -H "App-Token: {YOUR-APP-TOKEN}" \
 -H "Api-Version: 3.0" \
 -H "Content-Type: application/json" \

Generate Reports

You have a few options to generate reports:

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:
Copy
Copied
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:
Copy
Copied
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 our 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 our transaction records should be used if your platform is serving reports based on your system data rather than based on our 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:

Copy
Copied
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.

We also recommend providing basic data tools for your merchants to use. For instance, once a basic report is generated via our 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:
Copy
Copied
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 - The total amount of the transaction
  • Fees - The total amount of the transaction associated with your app Account balance
  • Net - The total amount of the transaction associated with the merchant Account balance

Note that the credit / debit value of the amount fields will change depending on the resource. For instance, if a transaction record is examining a Payment, the gross indicates a debit from the payer, the net indicates a credit to the merchant, and the fee indicates a credit to your app account. For merchant reporting purposes, indicate credits and debits relative to the merchant Account balance. So, in the case of a Payment, the gross and net should be credits and the fee should be a debit.

Info

Validation for reconciliation reports is not necessary, as your platform will not have the ability to predict the resources included in a payout. Because we control payout limits, manual reviews, and other factors impacting the contents of payouts, we validate 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:
Copy
Copied
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.


Report on Multiple Merchant Locations

Some merchants, such as franchises, will have multiple locations. Per the guidance on supporting merchants with multiple locations, each location should have its own WePay Account ID, and they should all be tied to the same WePay Legal Entity ID.

Provide custom reporting for these merchants by covering the following use cases:

  • Report on each location
  • Report on all locations
To report on each location separately from other locations, follow the standard guidance above. To report on all locations collectively, first identify all locations by sending a GET /accounts request. Send the owner_id parameter with the Legal Entity ID as the value. The response will be an array of Accounts, and you should parse out the id parameter for each.

Next, decide whether you are generating a transaction history or a reconciliation report.

For transaction history reports, fetch all Transaction Records for each Account ID with a GET /transaction_records request. Be sure to send the account_id parameter. For reconciliation reports, fetch all Payouts for each Account ID with a GET /payouts request with the owner_id parameter having the Account ID as the value. Next, fetch all Transaction Records associated with each Payout by sending a GET /transaction_records request with the payout_id parameter.

Platform Reports

As a platform, use our Transaction Records for your own revenue reporting.To find all Transaction Records for Payments, Refunds, Disputes, app_fees that have impacted your platform WePay balance, send a GET /transaction_records?account_id=YOUR-PLATFORM-ACCOUNT-ID. Remember that you can find your app Account ID by logging in to partner center. Keep the defaults for create_time_start and create_time_end in mind as you construct requests like this.

When generating reports for your platform, use these definitions for Transaction Record parameters:

  • gross_amount -- The total amount of fees.
  • net_amount -- The total amount of fees minus WePay fees. For instance, this is the total amount credited to your platform Account balance for a Payment.
  • fee_amount -- The amount of WePay fees.
  • currency -- The currency of the associated transaction.
  • type -- The type of associated resource. For application fee Transaction Records, this value will be app_fee.
  • owner -- A structure defining the associated resource's ID and path.

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:
Copy
Copied
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 - The total amount of fees associated with the originating merchant transaction
  • fee_amount - The amount of WePay fees contributing to the gross
  • net_amount - The total amount of your platform fees contributing to the gross
  • owner.resource (this will be payments, refunds, disputes, etc.)
  • owner.id - This will be your platform's account ID

Note that the credit / debit value of the amounts will change depending on the owner resource. For instance, if a transaction record is examining a Payment, the gross and net will be credits to your platform account, and the fee will be a debit from your account and a credit to us.

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.

Handling 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:
Copy
Copied
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:
Copy
Copied
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:

Note
Make sure to consume the dispute amount. If the amount is different than the initial transaction, you have either a partial dispute or an exchange rate fluctuation.
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.


Partner Reports

As a Partner, use our Transaction Summaries and Transaction Metrics for real-time reporting information, similar to what is seen in Partner Center.

Transaction Summaries

Transaction Summaries are a representation of any money movement. These could be merchant-level money movements, but also Partner application-level movements such as withdrawals. It contains various information about an individual transaction including amounts, transaction times, basic fee information, payment method information, etc. The transaction summaries report can also be used to retrieve a list of transactions via various filter options or retrieve a specific transaction by making a request with the transaction_id and the transaction_type for the expected transaction.

This endpoint requires one of (create_time_start, create_time_end) or (finish_time_start, finish_time_end) to be set. Use the account_id value to make a GET /transaction_summaries request:
Copy
Copied
 curl -X GET \
 /transaction_summaries/ \
  -H 'App-Id: <your-app-id>' \
  -H 'App-Token: <your-app-token>' \
  -H 'Api-Version: 3.2' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "account_id": "<your-account-id>""
    "create_time_start": 1667300000,
    "create_time_start": 1667514437
}'

Transaction Metrics

The Transaction Metrics report returns a collection of pre-calculated metrics about transactions.

The GET /transaction_metrics endpoint requires one of (create_time_start, create_time_end) or (finish_time_start, finish_time_end) to be set. Use the account_id value to make a GET /transaction_metrics request:
Copy
Copied
 curl -X GET \
 /transaction_metrics/ \
  -H 'App-Id: <your-app-id>' \
  -H 'App-Token: <your-app-token>' \
  -H 'Api-Version: 3.2' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "account_id": "<your-account-id>""
    "create_time_start": 1667300000,
    "create_time_start": 1667514437
}'