API Basics
WePay’s API products are packed full of features and conveniences to help you handle different scenarios, like reducing PCI scope, preventing double charges in case of error, and adding in your own custom data to help maintain things like state. This page is a full list of features to use depending on your use case – keep it handy.
By the end of this doc, you’ll have the right information to build an API call.
Resource IDs
It is important to note that resource IDs returned by WePay are case-sensitive. For instance, if the following is returned by WePay as an Account ID:
d3f61e56-5d99-4895-af2d-a07ab48476e9
And you later send a GET request for that same account like so, even with just one letter in the wrong case:
curl -X GET \
--url 'https://stage-api.wepay.com/accounts/D3f61e56-5d99-4895-af2d-a07ab48476e9' \
-H 'Accept: application/json'\
-H 'App-Id: 12121'\
-H 'App-Token: '\
-H 'Api-Version: 3.0'
Then the account you are attempting to fetch will not be returned.
API Headers
As with all API calls, you need to pass required headers. First, let’s cover the required headers for all API calls to WePay, across products. As a reminder, you created your API credentials during account sign-up. Access them here.
Header Key | Header Value (example) |
---|---|
App-ID |
123456 |
API-Version |
3.0 |
App-Token |
stage_MzBfNzM2ZmEwYTItZmQ1My00MYg1LEEwYmMtYzE2MmMzNDIyZDIz |
Content-Type |
application/json |
Conditionally Required Headers
Beyond the globally required headers listed above, there are a few API headers which are only required in certain situations, or on certain endpoints:
Header Key | Header Value (example) | Condition(s) |
---|---|---|
Unique-Key |
TR-123 |
All requests to the POST /payments and POST /refunds endpoints. |
Client-IP |
100.166.99.123 |
Integrations which do not incorporate WePay's JS must include the Client-IP and WePay-Risk-Token headers on the following endpoints:
|
WePay-Risk-Token |
123e4567-e89b-12d3-a456-426655440000 |
Note
In order to safely retry POST /payments or POST /refunds requests, you need to use the Unique-Key
header, which is a uniquely defined value. Read the Idempotency section below for more information.
Find more information about Client-IP
and WePay-Risk-Token
here, and more information about a server to server integration here.
Finally, look to the table below to see the base URLs you will interface with. All resources found on the API reference are appended to the base URLs.
Base URL | Environment |
---|---|
https://stage-api.wepay.com | Stage |
https://api.wepay.com | Live |
API Versions
When interfacing with the WePay API, you can select which API version to pass. API versions are compatible with other versions, so you could make a call to certain endpoints using v3.1, and to others as v3.0.
If you do not need to use different versions, it’s completely fine to use a single version. The latest version is 3.0.
API Rate Limits
By default, the API rate limit is 30 requests endpoint per 10 seconds. The rate limit is calculated using the sliding window algorithm, meaning that API requests are measured on a rolling basis.
Throttling per endpoint ensures that if a single service (like creating payments) sees a spike, then other services will not be impacted (such as looking up accounts).
If your app attempts to send a total of 31 requests to a single endpoint in a sampling period of 10 seconds, then the last request in chronological order will receive the THROTTLE_EXCEEDED API error. If 31 requests were sent in the first second, you will be able to successfully send new requests at 11 seconds. On the other hand, if 15 requests were sent on second 9, and 16 requests were attempted on second 10 (1 would be throttled on second 10), you will then be able to send 15 un-throttled requests on second 19 (once second 9 is no longer included in the sliding window), and another 15 on second 20.
As another example, say your app hit the same endpoint with 3 requests per second for seconds 1-9, and then sent 4 requests on second 10. The last request to come in would receive an error, and you would be able to send another successful request on second 11.
If you have a business use case that requires a higher rate limit, please speak to your account manager or API Support, at api@wepay.com.
Upcoming Enhancements
Starting February 1, 2021, WePay will implement account-based and endpoint-based throttles in addition to the existing app-based. This will help ensure that:
- If a single merchant sees a spike in API requests, your other merchants won’t be impacted
- If your app sees a spike in reaching the POST /payments endpoint, your ability to reach other endpoints won’t be impacted
If a throttle limit is exceeded, then the error reason will identify which throttle is in play.
Summary of changes
Old throttle | Current throttle | February 1, 2021 throttle |
---|---|---|
|
|
|
Permissions Based Features
When road-mapping your integration with WePay, it’s important to remember that certain endpoints and parameters require permission for use. Sending calls to restricted endpoints or with restricted parameters will result in the following error:
{
"error_code": "NOT_AUTHORIZED",
"error_message": "FEATURE_NOT_ENABLED_FOR_APPLICATION"
...
}
During your planning, take note of each feature you’d like access to and submit a request to your account manager, technical account manager, or WePay’s developer support (api@wepay.com). Your request should include:
- Your platform's stage
app-id
- A high-level description of your business
- Your business use case for the specific feature(s) being requested
Restricted Features
Endpoint | Parameter | Notes |
---|---|---|
POST /payments | payment_method.credit_card |
Link platforms must tokenize payment methods, so cannot leverage the in-line raw credit card data feature. |
POST /payment_methods | credit_card.auto_update |
Link platforms cannot enroll in account updater for credit cards. |
POST /payment_methods | credit_card.cvv |
This parameter is always required for Link platforms. |
POST /payment_methods | credit_card.virtual_terminal_mode |
Link platforms do not have access to virtual terminal payments. |
Link Restrictions
WePay’s Link product is designed to tap into the JP Morgan Chase client-base, and certain endpoints are not enabled for Link platforms as a result. For instance, onboarding merchants with a Link integration will be initiated from the WePay end, so onboarding endpoints are automatically disabled for Link platforms.
Here is a list of all endpoint & HTTP method combinations which Link platforms do not have access to:
Endpoint | HTTP Method |
---|---|
/accounts |
POST |
/accounts/{id}/capabilities |
POST |
/legal_entities |
POST |
/legal_entities/{id} |
POST |
/legal_entities/{id}/set_controller_password |
POST |
/legal_entities/{id}/verifications |
POST |
/payout_methods |
POST |
/payout_methods/{id} |
POST |
/disputes/{id} |
POST |
/disputes/{id}/concede |
POST |
/payment_methods/{id}/verify_bank_deposits |
POST |
While Link integrations will not have access to the above API requests, Notifications related to those endpoints are still accessible. Subscribing to those Notifications will help keep data in sync between WePay and your platform, and WePay highly recommends subscribing (covered later).
Idempotency
Making GET calls will not modify resources, and sending a POST to an endpoint will update the fields provided in the POST body only. If you’d like to delete a field in an object, send a POST with the field set to NULL
. For complex objects, like beneficial owners– where you may not have all data at once–pass an empty object, like {}
. This lets you progressively update the Legal Entity object.
In error scenarios, retrying a payment and refund can lead to overcharging a payee or drawing too much from a merchant. In order to safeguard against these scenarios, you will use the “Unique-Key” key and unique value (generated by you) in the request header. You can use any value for the Unique Key, as long as it’s unique.
As an example, let’s say your platform handles rent between landlords and tenants. A good unique key could be the tenant’s payment date, so that double payments do not occur.
For all POST calls made to /payments and /refunds, you are required to send “Unique-Key” in the header. The Unique-Key requirement makes these POST requests idempotent and safe, nullifying duplicate successful requests. For all other POST calls, the Unique-Key is optional. In general, a Unique-Key is valid for 24 hours.
For more information on error handling and retry strategies, see the Design A Retry Strategy article.
Errors
WePay’s API follows standard API conventions with errors. You can view the API reference documentation for an exhaustive list of error codes. Throughout the integration guide, we will also highlight special errors and remediation strategies.
Avoid Hanging API Requests
Our API services will timeout after 30 seconds if no response is returned within that timeframe. It is recommended that you adjust your timeout settings to reflect this, in the case that your API request takes a little longer to process.
Handle 500s
In general, 500 HTTP errors indicate that an unknown error occurred and are safe to implement your retry logic for. See Design A Retry Strategy to create the best retry logic for your particular integration with WePay.
Note that 503 errors indicate that a known issue caused the error, but that the request can be retried at a later time.
In the case of a 500 returned on /payments or /refunds, you will need to implement proper retry logic, depending on a Card Present (CP) or Card Not Present (CNP) transaction flow.
Card Not Present transactions
In general, you should implement a back-off strategy upon receiving the first 5xx error code (like an exponential back-off). If a 5xx HTTP error returns for a request with a unique key the first time, resend the request with the same unique key, and carry on until you reach the threshold for your exponential back-off window (or the payment succeeds with a non 5xx error code).
If you use a different unique-key during your back-off, you run the risk of double-authenticating a payment. If you receive the API Error Code CONCURRENT_UNIQUE_KEY_REQUEST_IS_PROCESSING
, you can keep retrying safely.
If you reach the end of your retry window for back-off, grab the correlation-ID in the response header, and escalate the payment issue to WePay.
Card Present transactions
Like CNP transactions, in general, you should implement some type of back-off strategy when handling 5xxs. With CP transactions, however, a successful authentication at the terminal is sufficient to let a payer walk away from the terminal. Put another way, if you receive an encoded_payment_method
, an authentication has happened and you can attempt to execute a payment with the same error handling as the above Card Not Present section.
Handle 400s
If a 4xx HTTP error returns for a request with a unique key, that Payment cannot be processed. This means that new information must be submitted by the user, and a new unique key should be used on the new request. Refer to error code documentation here for further information on error responses.
Note
If you receive the API Error Code THROTTLE_EXCEEDED.APPLICATION_REQUEST_THROTTLE_EXCEEDED
or CONCURRENT_UNIQUE_KEY_REQUEST_IS_PROCESSING
, you can handle either of them as a 5xx HTTP error.
Custom Data
Custom data refers to a key-value object that can be passed in most API calls. The point of custom data is to add any additional metadata you need to store for resources, that you can’t store using predefined fields. There is a limit of 10kb for custom data objects.
As an example, let’s say you wanted to create a Payment resource, and wanted to store the payer’s user name on your platform in the WePay Payment API object. You could add a key value pair to custom data, like so:
"custom_data": {
"merchant_username": "merchant1"
}
And any time you retrieve or update this payment, the custom data will be stored and returned. Custom data is a JSON object, and allows for nesting. The API will not overwrite custom data, and will append new keys/values. If you’d like to remove keys and values, assign existing keys to null, or, to remove the keys, set custom_data
to null, and re-add data. Do not send personally identifiable information (PII) through custom data.
Custom Data is available on all API resources, except:
- rBits
- Orders
- Items
Next Up: Setup Platform
Align your app’s configurations with the type of integration you want.
- Use the Javascript library
- Send risk information programmatically
Questions? Need help? Visit our support page!