Welcome to the PayWhirl API Reference. Here you will find details about our API and the methods it supports. We are consistently trying to make our web services better, so if you run into any issues or need help getting set up, please reach out to our support team.
Here's a high-level overview of how the PayWhirl services work:
plans
customers
cards
plans
to customers
using subscribe
The details for the rest of the options you see to the left will be explained in their individual sections.
Next will be a slightly more technical explanation of the usage details. The target audience is assumed to have general knowledge of software development and that our RESTful API uses POST and GET methods to send and receive data behind the scenes, so an active internet connection is required.
In order to access the API, you will need an API key and secret. You can obtain one in the API key section of the main site. You can also find this page in your dashboard in the following section:
Settings & Account > Developer > API Keys
Note: please make sure to store this token securely, and never expose it in your front-end code, because it gives full access to your subscriptions to anyone who gets ahold of it. If you suspect your API key or secret may have been leaked, please revoke it it as soon as possible and create a new one.
After obtaining your token, you can call the /test
endpoint to verify that your credentials are working.
All calls made to the API will use the following endpoint: https://api.paywhirl.com.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/test');
Sample response:var_export(json_decode($response->getBody())); array ( 'message' => 'Connection successful', )
Note: since every mainstream web framework includes high quality tools for accessing APIs and processing webhooks, we decided to deprecate our dedicated libraries. This leaves you with the maximum flexibility in choosing your preferred tech stack. The following section is left for reference only.
The PayWhirl libraries follow a typical object-oriented or object-based software pattern, where you simply instantiate a PayWhirl object using your API credentials and call a variety of methods to manipulate your account while the PayWhirl object abstracts away network authentication and requests.
The vast majority of methods recieve a JSON object from our servers that is translated by the library into that language's native dictionary-like data structure. The returned object is either something that you've directly requested, or is an object that can be seen as a sort of receipt, verifying that your changes have been acknowledged and stored. Anything that doesn't operate this way will explicitly say so in its section of this documentation.
Place the library file in your project and import the class so that you can instantiate a PayWhirl object. When you create a new PayWhirl object you need to pass in your API key and secret, which can be found in the API key section of the main site.
PayWhirl enforces API rate limiting for any given interval. This means you cannot exceed the allowed number of requests to the API in a predefined interval. Current values are:
Number of requests: 360
Interval: 1 minute(s)
If you excceed the number of allowed requests for the given interval, HTTP response code of 429 will be returned. To help mitigate this problem, 3 HTTP response headers are available for you to check with each request you make:
Customer objects are the primary abstraction mechanism for storing information about
a specific real person. You can later attach customers
to plans
using a subscription
,
or you can charge
them directly for single-instance payments.
The customer section of the API allows you to create, update, and retrieve information about your customers.
You might find it useful to keep track of your customer id
numbers as you create them so that you have an easy way to
select customers you want to find information about or to manipulate.
The primary purpose of this method is to retrieve a selection of your customers (that can be ordered via the parameters below).
This is useful for keeping track of your customers in a local database for bookkeeping purposes and for having a local copy that you
can edit before submitting changes via the update customer
method.
An important distinction to keep in mind is that the customer's id
is distinct from your (the PayWhirl account
holder's) user_id
.
This method returns an indexed
array
containing Customers of type
object
.
For parameters, the method will accept one of the key-value pairs listed below.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/customers/?limit=10&order_key=id&order_direction=asc');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 54398, 'user_id' => 1234, 'first_name' => 'Awesome', 'last_name' => 'Person', 'email' => 'awesome+person@paywhirl.com', 'phone' => '4564564566', 'address' => '123, Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'gateway_reference' => '783789y6r890', 'default_card' => 34, 'gateway_type' => 'PaywhirlTest', 'gateway_id' => 18, 'currency' => 'USD', 'utm_source' => '', 'utm_medium' => '', 'utm_term' => '', 'utm_content' => '', 'utm_campaign' => '', 'utm_group' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, ), 1 => array ( 'id' => 54403, 'user_id' => 1234, 'first_name' => 'Joe', 'last_name' => 'Cool', 'email' => 'joe@paywhirl.com', 'phone' => '8978768768', 'address' => '123 Easy Street', 'city' => 'Dallas', 'state' => 'Texas', 'zip' => '93003', 'country' => 'US', 'gateway_reference' => 'cus_56549881e6e03', 'default_card' => 45, 'gateway_type' => 'Stripe', 'gateway_id' => 20, 'currency' => 'USD', 'utm_source' => '', 'utm_medium' => '', 'utm_term' => '', 'utm_content' => '', 'utm_campaign' => '', 'utm_group' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, ), )
The primary purpose of this method is to retrieve information about an individual customer from the PayWhirl database for your personal use.
This will most likely be useful to you as a tool for displaying customer information in your app, or as a way to grab a current version of a
specific customer's data in order to modify it before submitting an update customer
request.
This method returns a Customer object of type
object
.
For parameters, you can select the customer you desire by passing in the customer's database assigned (integer)
["id"]
or the user-supplied (string)
["email"]
.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/customer/54398');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 54398, 'user_id' => 1234, 'first_name' => 'Awesome', 'last_name' => 'Person', 'email' => 'awesome+person1@example.com', 'phone' => '4564564566', 'address' => '123, Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'gateway_reference' => '783789y6r890', 'default_card' => 34, 'gateway_type' => 'PaywhirlTest', 'gateway_id' => 18, 'currency' => 'USD', 'utm_source' => '', 'utm_medium' => '', 'utm_term' => '', 'utm_content' => '', 'utm_campaign' => '', 'utm_group' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, )
Authenticate a Customer by passing in an email address and password.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/auth/customer', [ 'json' => [ 'email' => 'awesome+person@paywhirl.com', 'password' => 'secret', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Create a new Customer by passing in an
array
of key-value pairs. The parameters below tagged "(required)" can be used to create a minimal
Customer. The
["email"]
field in particular is used as one of two candidate keys for the database. The second candidate
key is a database-supplied
["id"]
field.
This method is the third step after setting up your account and creating some plans.
Later, when you're binding a customer
and plan
via a subscription
, you will need to supply the customer's
id
.
For security reasons, we strongly advise leaving the password
field blank, and letting the customer
assign the password themselves, using a secure link in the Welcome email.
If you decide to provide your password anyway, note that the minimum viable one needs to be between 6 and 20 characters, and uses the following
perl-compatible regex that might be useful to include in your own code:
/^[A-Za-z0-9~!@#$%^&*()_\-+=<>,.?\/;:{}\\\\[\]|]{6,}$/
Although the technical minimum password length is 6 characters, we do recommend that you stress the importance of a password that is around 14-ish characters long to harness the power of combinatoric explosions. It's also a good idea to remind people that they shouldn't use the same password for multiple websites or services.
It is also important to never locally store the password string, especially in plaintext. The plaintext password should be secured by the HTTPS request, and is hashed on our servers before it ever touches the database.
Email Settings: this method will trigger the Welcome Email event if you've elected to create and use a welcome template email.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/create/customer', [ 'json' => [ 'first_name' => 'Sleve', 'last_name' => 'McDichael', 'email' => 'slevem@dandleton.com', 'currency' => 'USD', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => '1234546', 'user_id' => 1234, 'first_name' => 'Sleve', 'last_name' => 'McDichael', 'email' => 'slevem@dandleton.com', 'phone' => '', 'address' => '', 'city' => '', 'state' => '', 'zip' => '', 'country' => '', 'gateway_reference' => '66b3418b2e496', 'default_card' => 0, 'gateway_type' => 'PaywhirlTest', 'gateway_id' => 18, 'currency' => 'USD', 'utm_source' => '', 'utm_medium' => '', 'utm_term' => '', 'utm_content' => '', 'utm_campaign' => '', 'utm_group' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
The update customer method requires that you return ALL of the customer information to be updated, so the standard workflow should be get
customer
,
then change any data you want, then return all of the customer data. Any empty fields will be removed from the customer object.
The update method is mostly useful for things like changing the default card on file for a customer, or for fixing an error in a name.
You cannot use this method unless you've already used the create customer
method to register a customer object with our service.
The update method will read in an
array
of key-value pairs that you wish to alter, and will update the customer associated with the
["id"]
contained in the collection passed in. If you don't know the
["id"]
of the customer you wish to modify, you can utilize the
/GET/customer/
method for your language and search by email address. If you don't know the email address, you can use the
/GET/customers/
method to retrieve an array of all customers and their ids.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/update/customer', [ 'json' => [ 'id' => 54398, 'first_name' => 'Stove', 'last_name' => 'Dandleton', 'email' => 'slevem@dandleton.com', 'currency' => 'USD', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 54398, 'user_id' => 1234, 'first_name' => 'Stove', 'last_name' => 'Dandleton', 'email' => 'slevem@dandleton.com', 'phone' => '4564564566', 'address' => '123, Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'gateway_reference' => '783789y6r890', 'default_card' => 34, 'gateway_type' => 'PaywhirlTest', 'gateway_id' => 18, 'currency' => 'USD', 'utm_source' => '', 'utm_medium' => '', 'utm_term' => '', 'utm_content' => '', 'utm_campaign' => '', 'utm_group' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Delete a customer by its ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/delete/customer', [ 'json' => [ 'id' => 54398, 'forget' => true, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
This method returns a list of all questions associated with your account that can be displayed on your checkout or sign up forms. For more information about the data fields, there is a graphical implementation in the PayWhirl dashboard that clearly elucidates the options.
The general purpose of any form question is for you to gather information from your customers without needing to use a secondary polling service. By utilizing the checkout questions, you can get small snippets of information that might be useful for your company to analyze. This method will most likely be useful for finding values needed to store in your database for easier parsing later.
Note that this does not grab questions associated with individual subscribers
, but retrieves all of the questions associated with
your PayWhirl account.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/questions?limit=10');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'type' => 'select', 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'className' => 'form-control', 'subtype' => NULL, 'toggle' => NULL, 'value' => NULL, 'description' => NULL, 'required' => true, 'values' => array ( 0 => array ( 'label' => 'Whole Bean', 'value' => 'Whole Bean', 'selected' => true, ), 1 => array ( 'label' => 'Ground', 'value' => 'Ground', ), ), 'rows' => NULL, 'placeholder' => '', 'multiple' => NULL, 'other' => NULL, 'min' => NULL, 'max' => NULL, 'step' => NULL, ), )
This method allows you to create or modify an answer provided by a given user, selected by
["customer_id"]
,
["question_name"]
, and
["answer"]
.
The general idea is that any given customer will answer questions during checkout (or with this method, whenever you choose).
This method provides a way for you to associate a given answer with a customer and a question name. Later, you can use the get
answers
method to retrieve and parse the data you've acquired from your customers.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/update/answer', [ 'json' => [ 'question_name' => 'select-1454375030381', 'customer_id' => 54398, 'answer' => 'Ground', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Ground', ), )
Get a complete lists of a customer's answers to profile questions by passing in an
integer
representing the customer ID.
The general idea of the get answers
method is that it allows you to retrieve all of the answered questions associated with a given
customer.
The most common use-case for this is to download all of the information stored about your customers and store it in a local database, or convert
it
to a spreadsheet-readable format so that you can parse the feedback you've acquired.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/answers?customer_id=54398');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), )
Get a complete lists of a customer's addresses by passing in an
integer
representing the customer ID.
The general idea of the get addresses
method is that it allows you to retrieve all of the additional addresses that a customer has
added to their account.
The most common use-case for this is if you want to allow your customers to ship to multiple locations, and want to keep a reference for
additional shipping options.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/customer/addresses/54398');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'user_id' => 1234, 'customer_id' => 54398, 'first_name' => 'Awesome', 'last_name' => 'Person', 'address' => '123, Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'phone' => '4564564566', 'id' => 0, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, ), 1 => array ( 'id' => 12, 'user_id' => 1234, 'customer_id' => 54398, 'first_name' => 'Joe', 'last_name' => 'Cool', 'phone' => '8978768768', 'address' => '123 Easy Street', 'city' => 'Dallas', 'state' => 'Texas', 'zip' => '93003', 'country' => 'US', 'metadata' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, ), )
Get a single address by passing in an
integer
representing the address ID.
The general idea of the get address
method is that it allows you to get a specific extra address a customer has added to their
account.
The most common use-case for this is if you want to allow your customers to ship to multiple locations, and want to keep a reference for
additional shipping options.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/customer/address/12');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 12, 'user_id' => 1234, 'customer_id' => 54398, 'first_name' => 'Joe', 'last_name' => 'Cool', 'phone' => '8978768768', 'address' => '123 Easy Street', 'city' => 'Dallas', 'state' => 'Texas', 'zip' => '93003', 'country' => 'US', 'metadata' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Create an extra address for a customer.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/customer/address', [ 'json' => [ 'customer_id' => 54398, 'first_name' => 'Awesome', 'last_name' => 'Person', 'address' => '123 Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'phone' => '4564564566', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => '1234546', 'user_id' => 1234, 'customer_id' => 54398, 'first_name' => 'Awesome', 'last_name' => 'Person', 'phone' => '4564564566', 'address' => '123 Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'metadata' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Update an extra customer address.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('PATCH', '/customer/address/12', [ 'json' => [ 'first_name' => 'Awesome', 'last_name' => 'Person', 'address' => '123 Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'phone' => '4564564566', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 12, 'user_id' => 1234, 'customer_id' => 54398, 'first_name' => 'Awesome', 'last_name' => 'Person', 'phone' => '4564564566', 'address' => '123 Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'metadata' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Delete an extra customer address
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('DELETE', '/customer/address/12');
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Get a complete customer profile (customer info, addresses, and profile answers) by using an
integer
representing the customer ID.
The general idea of the get profile
method is that it allows you to retrieve all of the information associated with a given
customer.
The most common use-case for this is if you want to keep a copy of your customer's records, or if you want a more detailed overview of a
customer than the get customers
methods provides.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/customer/profile/54398');
Sample response:var_export(json_decode($response->getBody())); array ( 'customer' => array ( 'id' => 54398, 'user_id' => 1234, 'first_name' => 'Awesome', 'last_name' => 'Person', 'email' => 'awesome+person1@example.com', 'phone' => '4564564566', 'address' => '123, Easy Street', 'city' => 'Los Angeles', 'state' => 'California', 'zip' => '93003', 'country' => 'US', 'gateway_reference' => '783789y6r890', 'default_card' => 34, 'gateway_type' => 'PaywhirlTest', 'gateway_id' => 18, 'currency' => 'USD', 'utm_source' => '', 'utm_medium' => '', 'utm_term' => '', 'utm_content' => '', 'utm_campaign' => '', 'utm_group' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, ), 'addresses' => array ( 0 => array ( 'id' => 12, 'user_id' => 1234, 'customer_id' => 54398, 'first_name' => 'Joe', 'last_name' => 'Cool', 'phone' => '8978768768', 'address' => '123 Easy Street', 'city' => 'Dallas', 'state' => 'Texas', 'zip' => '93003', 'country' => 'US', 'metadata' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, ), ), 'answers' => array ( 0 => array ( 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), ), )
Plans can be considered one of the core products that PayWhirl manages for you. The general idea of a plan is that it establishes the "how much" and "when" to bill for the system, while also containing the "what" for the customer.
The PayWhirl plan page is the usual method for generating plans outside of this API,
and can be a good resource for understanding each aspect of the plan
object.
Get a list of plans created by your account.
The get plans
method will return a list of up to
100 plans associated with your account. You can choose which slice of plans you want returned by using the before_id
and
after_id
parameters. Each plan has a set of questions
associated with it so that you can gather information on a
per-plan basis.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/plans/?limit=10&order_key=id&order_direction=desc');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 64525, 'user_id' => 1234, 'active' => 0, 'enabled' => 0, 'description' => '', 'image' => '', 'name' => 'Super Order Plan', 'billing_amount' => 10, 'sku' => 'DEMO-SKU-2', 'currency' => 'USD', 'setup_fee' => 0, 'setup_fee_type' => NULL, 'setup_fee_sku' => NULL, 'require_tax' => 1, 'billing_interval' => 2, 'billing_frequency' => 'week', 'billing_dates' => '', 'billing_cycle_anchor' => 0, 'billing_cycle_anchor_time' => '', 'starting_day' => 0, 'trial_days' => 7, 'installments' => 0, 'require_shipping' => 1, 'cancellation_type' => NULL, 'autorenew_setup_fee' => 0, 'autorenew_plan' => 0, 'email_settings' => NULL, 'send_reminders' => NULL, 'questions' => '', 'display_download' => '', 'file' => '', 'tags' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, ), 1 => array ( 'id' => 64524, 'user_id' => 1234, 'active' => 0, 'enabled' => 0, 'description' => '', 'image' => '', 'name' => 'Monthly Order Plan', 'billing_amount' => 10, 'sku' => 'DEMO-SKU-3', 'currency' => 'USD', 'setup_fee' => 0, 'setup_fee_type' => NULL, 'setup_fee_sku' => NULL, 'require_tax' => 1, 'billing_interval' => 1, 'billing_frequency' => 'month', 'billing_dates' => '', 'billing_cycle_anchor' => 0, 'billing_cycle_anchor_time' => '', 'starting_day' => 0, 'trial_days' => 0, 'installments' => 0, 'require_shipping' => 1, 'cancellation_type' => NULL, 'autorenew_setup_fee' => 0, 'autorenew_plan' => 0, 'email_settings' => NULL, 'send_reminders' => NULL, 'questions' => '', 'display_download' => '', 'file' => '', 'tags' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, ), )
Get a single plan by plan ID.
As described above in the get plans
section, plans are the core object that PayWhirl manages for you.
This method is useful for inspecting the details of a specific plan so that you can either keep track of plans in your own local database,
or so that you can have a base object to modify before updating the data in a plan.
If you need to find the plan id
for retrieval of a specific plan, you can either check your plans page
or use get plans
to retrieve a larger list to select from.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/plan/64524');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 64524, 'user_id' => 1234, 'active' => 0, 'enabled' => 0, 'description' => '', 'image' => '', 'name' => 'Super Order Plan', 'billing_amount' => 10, 'sku' => 'DEMO-SKU-2', 'currency' => 'USD', 'setup_fee' => 0, 'setup_fee_type' => NULL, 'setup_fee_sku' => NULL, 'require_tax' => 1, 'billing_interval' => 2, 'billing_frequency' => 'week', 'billing_dates' => '', 'billing_cycle_anchor' => 0, 'billing_cycle_anchor_time' => '', 'starting_day' => 0, 'trial_days' => 7, 'installments' => 0, 'require_shipping' => 1, 'cancellation_type' => NULL, 'autorenew_setup_fee' => 0, 'autorenew_plan' => 0, 'email_settings' => NULL, 'send_reminders' => NULL, 'questions' => '', 'display_download' => '', 'file' => '', 'tags' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, )
Create a plan that allows you to set rules for how your customers will be billed.
Each time a customer subscribes
to one of your plans, the rules of your plan
will be attached
to your subscription
. If you change the rules for the plan, they will be applied
to the customer's next invoice. Your plan will automatically be given an id
with which you can then store and use later to update the plan if necessary.
This is generally the second step in setting up your PayWhirl account. The high level overview is that you create customers
and
plans
,
then they are linked together via a subscription
.
The easiest way to get a feel for how to create a plan is to inspect the plan page
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/create/plan', [ 'json' => [ 'name' => 'Super Order Plan', 'description' => '', 'setup_fee' => 0, 'setup_fee_type' => 'fee', 'setup_fee_sku' => '', 'installments' => 3, 'image' => '', 'starting_day' => 0, 'billing_amount' => 10, 'billing_interval' => 1, 'billing_frequency' => 'day', 'trial_days' => 0, 'currency' => 'USD', 'sku' => 'DEMO-SKU-2', 'require_tax' => 0, 'require_shipping' => 1, 'billing_cycle_anchor' => 0, 'enabled' => 0, 'tags' => '', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 7467, 'user_id' => 1234, 'active' => 0, 'enabled' => 0, 'description' => '', 'image' => '', 'name' => 'Super Order Plan', 'billing_amount' => 10, 'sku' => 'DEMO-SKU-2', 'currency' => 'USD', 'setup_fee' => 0, 'setup_fee_type' => 'fee', 'setup_fee_sku' => '', 'require_tax' => 0, 'billing_interval' => 1, 'billing_frequency' => 'day', 'billing_dates' => '', 'billing_cycle_anchor' => 0, 'billing_cycle_anchor_time' => '', 'starting_day' => 0, 'trial_days' => 0, 'installments' => 3, 'require_shipping' => 1, 'cancellation_type' => NULL, 'autorenew_setup_fee' => 0, 'autorenew_plan' => 0, 'email_settings' => NULL, 'send_reminders' => NULL, 'questions' => '', 'display_download' => '', 'file' => '', 'tags' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
To update a plan you simply pass in a plan object that has the values
you wish to update, and ensure that the plan_id
field matches
the plan you wish to change.
The general use-case for updating a plan is that maybe the products you're offering now are higher quality, so the current customers' rates need
to go up,
or maybe you noticed an error in the original plan and need to modify it without creating a whole new plan and re-subscribing your customers.
Any changes made to an existing plan will automatically be applied to any subscribed customers, so you don't need to worry about any additional
modifications other
than changing your plan
.
The easiest way to update a plan is to use the get plan
method if you know the plan_id
, or the get plans
method to retrieve
a larger list to find your plan_id
that needs changing. Once you have your plan
object,
simply modify the fields you wish to change and re-submit via update plan
.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/update/plan', [ 'json' => [ 'id' => 64524, 'name' => 'New plan name', 'setup_fee' => 0, 'setup_fee_type' => 'fee', 'setup_fee_sku' => '', 'installments' => 6, 'billing_amount' => 120, 'billing_interval' => 1, 'billing_frequency' => 'day', 'trial_days' => 0, 'sku' => 'e456456', 'currency' => 'USD', 'require_tax' => 0, 'require_shipping' => 1, 'billing_cycle_anchor' => 0, 'active' => 0, 'image' => '', 'starting_day' => 0, 'description' => '', 'enabled' => 0, 'tags' => '', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 64524, 'user_id' => 1234, 'active' => 0, 'enabled' => 0, 'description' => '', 'image' => '', 'name' => 'New plan name', 'billing_amount' => 120, 'sku' => 'e456456', 'currency' => 'USD', 'setup_fee' => 0, 'setup_fee_type' => 'fee', 'setup_fee_sku' => '', 'require_tax' => 0, 'billing_interval' => 1, 'billing_frequency' => 'day', 'billing_dates' => '', 'billing_cycle_anchor' => 0, 'billing_cycle_anchor_time' => '', 'starting_day' => 0, 'trial_days' => 0, 'installments' => 6, 'require_shipping' => 1, 'cancellation_type' => NULL, 'autorenew_setup_fee' => 0, 'autorenew_plan' => 0, 'email_settings' => NULL, 'send_reminders' => NULL, 'questions' => '', 'display_download' => '', 'file' => '', 'tags' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Subscriptions are the core objects that handle the billing process when you're not doing individual charges.
You create a subscription using the subscribe customer
method, which requires that you have at least one customer with a payment
method on file,
as well as a plan you wish to subscribe the customer to. Once you've subscribed a customer, PayWhirl will generate invoices at regular
intervals, which will then
attempt to process payments at a time specified by your plans.
If you want up-to-date information about the status of your subscribers, see the webhooks section below to learn how to get feedback from our system.
Get a list of subscriptions associated with a given customer.
This method is useful for determining which services a customer is or isn't currently expecting, which you can determine
by checking value of current_period_end
, which will be a Unix Timestamp (UTC time zone).
To find a customerID
to look up, you'll want to check the get customers
method for your language,
which will return a list of all customers that you can inspect for the customer IDs. It may also be helpful to locally keep
your customer IDs stored when you create them, as a large number of methods require a customer ID as input.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/subscriptions/54398?status=all');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 29654, 'user_id' => 1234, 'customer_id' => 54398, 'plan_id' => 64524, 'widget_id' => 0, 'quantity' => 1, 'trial_start' => 1709551440, 'trial_end' => 1710156240, 'current_period_start' => 1710156240, 'current_period_end' => 1711365840, 'installment_plan' => 1, 'installments_left' => 6, 'cancellation_type' => NULL, 'cancellation_requested_at' => NULL, 'cancel_at_period_end' => 0, 'vendor_product_id' => 0, 'parent_subscription_id' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-04-13T11:24:00.000000Z', 'deleted_at' => NULL, 'plan' => array ( 'id' => 64524, 'user_id' => 1234, 'active' => 0, 'enabled' => 0, 'description' => '', 'image' => '', 'name' => 'Super Order Plan', 'billing_amount' => 10, 'sku' => 'DEMO-SKU-2', 'currency' => 'USD', 'setup_fee' => 0, 'setup_fee_type' => NULL, 'setup_fee_sku' => NULL, 'require_tax' => 1, 'billing_interval' => 2, 'billing_frequency' => 'week', 'billing_dates' => '', 'billing_cycle_anchor' => 0, 'billing_cycle_anchor_time' => '', 'starting_day' => 0, 'trial_days' => 7, 'installments' => 0, 'require_shipping' => 1, 'cancellation_type' => NULL, 'autorenew_setup_fee' => 0, 'autorenew_plan' => 0, 'email_settings' => NULL, 'send_reminders' => NULL, 'questions' => '', 'display_download' => '', 'file' => '', 'tags' => '', 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-06T11:24:00.000000Z', 'deleted_at' => NULL, ), ), )
Get a single subscription based on the subscription's ID.
This method returns information about a specific subscription without displaying information about the customer or the plan.
This can be useful if you're locally keeping track of subscription id
s and want to find out which customers are associated with
each
plan, or if you need to know how long a subscription has left before you prompt for renewal.
The easiest way to keep track of the subscription IDs to pass in as a parameter is to record the id
field whenever you subscribe a
customer.
If you choose not to do this, you can find subscription IDs by using the get subscriptions
method and passing in your customer IDs,
or by using the get subscribers
method.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/subscription/29654');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 29654, 'user_id' => 1234, 'customer_id' => 54398, 'plan_id' => 64524, 'widget_id' => 0, 'quantity' => 1, 'trial_start' => 1709551440, 'trial_end' => 1710156240, 'current_period_start' => 1710156240, 'current_period_end' => 1711365840, 'installment_plan' => 1, 'installments_left' => 6, 'cancellation_type' => NULL, 'cancellation_requested_at' => NULL, 'cancel_at_period_end' => 0, 'vendor_product_id' => 0, 'parent_subscription_id' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-04-13T11:24:00.000000Z', 'deleted_at' => NULL, )
Enroll a customer in an existing plan. The customer must have a valid payment method on file in order to be enrolled in a plan. Use the GET methods for customers and plans to retrieve your customer and plan IDs.
This is the fifth step described in the introduction, and is the method you'll use to begin charging your customers.
The only required fields are customer id
and plan id
to create a subscription, but free trials are
common for subscription services, and the code examples include a method for generating those.
The trial end
field
uses a Unix Timestamp in the UTC timezone, so you can also generate them using whatever the preferred method is for your system.
Email Settings: this method will trigger the New Subscription Email event if you've elected to create and use a new subscription template email.
The Payment Reminder and Payment Receipt emails are also tied to this method, as those emails are automatically sent when a transaction is about to process, or when a transaction actually processes (if you've chosen to use a template or to create your own emails.)
Unsuccessful Payment emails will also be sent if a customer with an active subscription's charge fails.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/subscribe/customer', [ 'json' => [ 'customer_id' => 54398, 'plan_id' => 64524, 'trial_end' => 1710156240, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 936537, 'user_id' => 1234, 'customer_id' => 54398, 'plan_id' => 64524, 'widget_id' => 0, 'quantity' => 1, 'trial_start' => 1709551440, 'trial_end' => 1710156240, 'current_period_start' => 1709551440, 'current_period_end' => 1710156240, 'installment_plan' => 0, 'installments_left' => 0, 'cancellation_type' => NULL, 'cancellation_requested_at' => NULL, 'cancel_at_period_end' => 0, 'vendor_product_id' => 0, 'parent_subscription_id' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Update various subscription parameters. A customer's subscription will stay the same, but the payment plan referenced by that subscription will be modified.
This method is useful as an error-correction mechanism if your customer accidentally selected the wrong plan, or if you want to provide a method for changing customer plans without needing to destroy the whole transaction to create a new one. It can also be used to modify the various attributes of a subscription (below).
For clarity, the subscription id
references the object that handles the timing and execution of the
transactions, while the plan id
references the object that determines the amount charged and the services provided.
All the parameters listed below are optional, aside from the subscription ID. You may choose to update one or many of the subscription params.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/update/subscription', [ 'json' => [ 'subscription_id' => 29654, 'plan_id' => 64525, 'quantity' => 5, 'address_id' => 12345, 'trial_end' => 1710761040, 'card_id' => 123, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 29654, 'user_id' => 1234, 'customer_id' => 54398, 'plan_id' => 64525, 'widget_id' => 0, 'quantity' => 5, 'trial_start' => 1709551440, 'trial_end' => 1710761040, 'current_period_start' => 1710156240, 'current_period_end' => 1710761040, 'installment_plan' => false, 'installments_left' => 0, 'cancellation_type' => NULL, 'cancellation_requested_at' => NULL, 'cancel_at_period_end' => 0, 'vendor_product_id' => 0, 'parent_subscription_id' => NULL, 'created_at' => '2024-01-24T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Cancel a customer's existing subscription.
This method will prevent the subscription from making any additional charges, and will unbind a customer from a plan.
It is important to note that this will cancel the subscription immediately, so if you plan to provide additional services during the time remaining on your customers' account, that will be the responsibility of your software. This method strictly prevents additional payments from being processed.
Email Settings: this method will trigger the Cancelled Subscription Email event if you've elected to create and use a cancelled subscription email.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/unsubscribe/customer', [ 'json' => [ 'subscription_id' => 29654, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Get a list of active subscribers.
This method simply returns a list of customers that currently have an active subscription. This can be useful for grabbing a list of all customers that you need to provide services for.
The returned list is limited to 100 customers at a time, so it is important to use the starting_after
and
starting_before
parameters to choose the slice you wish to work with.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/subscribers/?limit=10&order_key=current_period_end&order_direction=asc');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'subscription_id' => 29654, 'user_id' => 1234, 'customer_id' => 54398, 'plan_id' => 64524, 'first_name' => 'Awesome', 'last_name' => 'Person', 'email' => 'awesome+person1@example.com', 'quantity' => 1, 'current_period_start' => 1710156240, 'current_period_end' => 1711365840, 'installment_plan' => 1, 'installments_left' => 6, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-04-13T11:24:00.000000Z', 'profile' => array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), ), ), )
An invoice is an object that contains all the information needed to process a single transaction. You can think of a subscription as a sort of invoice factory, where each invoice produced will handle its own individual task.
While the subscription and charge methods handle the generation of invoices, the methods in this section allow you to view the contents of a single invoice, or to see all of the upcoming invoices for a single customer.
Get a single invoice by passing in an invoice ID.
This method returns a single invoice indicating things like whether or not a customer has paid yet, their currency type, or how many attempts were made to collect the payment. These are useful to query for record keeping, or for keeping track of which customers still have outstanding fees.
The main ways to find your invoice IDs programmatically are to either use the get invoices
method to get all invoices for a
specific customer,
or to record the data sent by the payment processing webhooks as described in the wehbooks section of this page.
For one-off cases, you can also find your invoice ids in your invoices page.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/invoice/39465');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 39465, 'user_id' => 1234, 'customer_id' => 54398, 'subscription_id' => 5047, 'charge_id' => 583, 'additional_charge_id' => NULL, 'card_id' => 365, 'address_id' => 0, 'amount_due' => 198, 'currency' => 'USD', 'discount_id' => 0, 'discount' => '0.00', 'shipping' => 0, 'shipping_total' => 0, 'tax' => 0, 'status' => 'Draft', 'paid' => 0, 'subtotal' => 198.98, 'attempted' => 0, 'attempt_count' => 0, 'due_date' => 0, 'next_payment_attempt' => 0, 'period_end' => 0, 'period_start' => 0, 'tax_total' => 0, 'tax_rule_name' => NULL, 'refunded_amount' => 0, 'webhooks_delivered_at' => 0, 'skipped_at' => NULL, 'paid_on' => 0, 'promo_id' => 0, 'promo_code' => '', 'promo_uses' => 0, 'integration_errors' => '', 'carrier' => '', 'service' => '', 'tracking_number' => '', 'is_order' => 1, 'shopify_created_at' => NULL, 'metadata' => NULL, 'tax_integration_id' => NULL, 'tax_calculated_at' => NULL, 'tax_status' => NULL, 'tax_date' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, 'profile' => array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), ), 'items' => array ( 0 => array ( 'id' => 2543, 'type' => 'plan', 'user_id' => 0, 'customer_id' => 0, 'invoice_id' => 39465, 'plan_id' => 64524, 'quantity' => 2, 'description' => 'Subscription to Coffee Daily 1', 'amount' => 99, 'currency' => 'USD', 'image' => NULL, 'tax_code' => NULL, 'sku' => '', 'vendor_product_id' => NULL, 'upsell_index' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, ), ), )
Get a list of upcoming (or all) invoices
This method can be useful for determining which invoices will be processed soon, and for determining what a given customer is expecting. This is also a good place to retrieve information from any survey questions that are asked in ongoing services. Adding the all parameter will return all customer's invoices, not only the upcoming ones.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/invoices/54398?all=1');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 12345, 'user_id' => 1234, 'customer_id' => 54398, 'subscription_id' => 0, 'charge_id' => 0, 'additional_charge_id' => NULL, 'card_id' => 0, 'address_id' => 12345, 'amount_due' => 198.98, 'currency' => 'USD', 'discount_id' => 0, 'discount' => '0.00', 'shipping' => 0, 'shipping_total' => 0, 'tax' => 0, 'status' => 'Draft', 'paid' => 0, 'subtotal' => 198.98, 'attempted' => 0, 'attempt_count' => 0, 'due_date' => 0, 'next_payment_attempt' => 0, 'period_end' => 0, 'period_start' => 0, 'tax_total' => 0, 'tax_rule_name' => NULL, 'refunded_amount' => 0, 'webhooks_delivered_at' => 0, 'skipped_at' => NULL, 'paid_on' => 0, 'promo_id' => 0, 'promo_code' => '', 'promo_uses' => 0, 'integration_errors' => '', 'carrier' => '', 'service' => '', 'tracking_number' => '', 'is_order' => 1, 'shopify_created_at' => NULL, 'metadata' => NULL, 'tax_integration_id' => NULL, 'tax_calculated_at' => NULL, 'tax_status' => NULL, 'tax_date' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, 'profile' => array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), ), 'items' => array ( 0 => array ( 'id' => 2543, 'type' => 'product', 'user_id' => 0, 'customer_id' => 0, 'invoice_id' => 12345, 'plan_id' => NULL, 'quantity' => 2, 'description' => 'Whole Bean', 'amount' => 9.99, 'currency' => 'USD', 'image' => NULL, 'tax_code' => NULL, 'sku' => '', 'vendor_product_id' => NULL, 'upsell_index' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, ), ), ), 1 => array ( 'id' => 12346, 'user_id' => 1234, 'customer_id' => 54398, 'subscription_id' => 0, 'charge_id' => 0, 'additional_charge_id' => NULL, 'card_id' => 0, 'address_id' => 12345, 'amount_due' => 198.98, 'currency' => 'USD', 'discount_id' => 0, 'discount' => '0.00', 'shipping' => 0, 'shipping_total' => 0, 'tax' => 0, 'status' => 'Draft', 'paid' => 0, 'subtotal' => 198.98, 'attempted' => 0, 'attempt_count' => 0, 'due_date' => 0, 'next_payment_attempt' => 0, 'period_end' => 0, 'period_start' => 0, 'tax_total' => 0, 'tax_rule_name' => NULL, 'refunded_amount' => 0, 'webhooks_delivered_at' => 0, 'skipped_at' => NULL, 'paid_on' => 0, 'promo_id' => 0, 'promo_code' => '', 'promo_uses' => 0, 'integration_errors' => '', 'carrier' => '', 'service' => '', 'tracking_number' => '', 'is_order' => 1, 'shopify_created_at' => NULL, 'metadata' => NULL, 'tax_integration_id' => NULL, 'tax_calculated_at' => NULL, 'tax_status' => NULL, 'tax_date' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, 'profile' => array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), ), 'items' => array ( 0 => array ( 'id' => 2544, 'type' => 'product', 'user_id' => 0, 'customer_id' => 0, 'invoice_id' => 12346, 'plan_id' => NULL, 'quantity' => 3, 'description' => 'Whole Bean', 'amount' => 99.99, 'currency' => 'USD', 'image' => NULL, 'tax_code' => NULL, 'sku' => '', 'vendor_product_id' => NULL, 'upsell_index' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, ), ), ), )
Process a pending invoice by passing in an integer
representing the invoice ID.
This method can be useful if you want to charge a customer before the automatic invoice processing time rolls around.
You can find invoice IDs with any of the methods illustrated in the get invoices
section.
Payment methods requiring Strong Customer Authentication
(SCA) need special handling when processing. This endpoint supports 2-step processing. Submit it normally without any additional
parameters to try normal processing. This will use off_session flag and try to process invoice as if PayWhirl processes it in the backend. If
your customer is present, submit customer_present = true
flag as part of the POST request. This will tell PW to try on_session
processing if off_session one requires authentication. If client-side auth is needed, this endpoint will return:
[
"requires_action" => true,
"payment_intent_client_secret" => "pi_XYZ_secret_..."
]
You should continue with the Stripe JS SDK here and
the returned intent client secret to authorize the payment. Upon successful authorization, call the same API endpoint with one additional
parameter intent_id
which comes as result.paymentIntent.id according to Stripe docs. This
will trigger second step of processing the invoice which will finish and do any post-payment activities.
invoice_id
you intend to process
true
to trigger on_session support for payments requiring Strong Customer Authentication
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoice/39465/process', [ 'json' => [ 'id' => 39465, 'customer_present' => true, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Mark a pending invoice as paid by passing in an integer
representing the invoice ID.
This method can be useful if you want to mark an invoice as paid without actually processing a charge transaction.
You can find invoice IDs with any of the methods illustrated in the get invoices
section.
invoice_id
you intend to process
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoice/39465/mark-as-paid');
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Add a Promo Code to an existing unpaid invoice.
You can find invoice IDs with any of the methods illustrated in the get invoices
section.
invoice_id
you intend to process
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoice/39465/add-promo', [ 'json' => [ 'promo_code' => 'PROMO-1234', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Remove existing Promo Code from an unpaid invoice.
You can find invoice IDs with any of the methods illustrated in the get invoices
section.
invoice_id
you intend to process
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoice/39465/remove-promo');
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Change invoice's payment method.
This method is useful for changing an upcoming invoice's payment method to another card that a customer has on file. The first parameter is an integer representing the ID of the invoice to modify, and the second parameter is the ID of the card you want to use for the invoice.
You can find invoice IDs with any of the methods illustrated in the get invoices
section.
invoice_id
you intend to modify
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoice/39465/card', [ 'json' => [ 'card_id' => 9534, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Modifies the quantities of line items in a specific invoice.
This method is useful when you want to change the number of line items in an existing invoice. For example, invoice '22' might have items '1111'
with a quantity of '2',
and '1112' with a quantity of '3', but the customer wants '4' and '5' respectively. Instead of creating a brand new invoice, you can simply
call this method and pass in (22, {'1111': 4, '1112': 5})
, which will set the line item quantities to the updated values.
You can find invoice IDs with any of the methods illustrated in the get invoices
section.
You can find the line item IDs by using the get invoices
method above, and
looking at the "items"
, where you will want the "id"
.
If you set any of the line_items
to '0', the item will be deleted from the invoice.
invoice_id
you intend to modify
{ <line_item_id>: <quantity>, ... }
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoice/39465/items', [ 'json' => [ '2543' => 1, '2545' => 2, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', 'items_updated' => 2, )
Create an upcoming or previously paid invoice for a customer.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoices', [ 'json' => [ 'customer_id' => 54398, 'next_payment_attempt' => 1709637840, 'shipping' => 1, 'tax' => 1, [ [ 'type' => 'product', 'description' => 'Sample item', 'amount' => 22.34, 'quantity' => 1, ] ] ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', 'invoice_id' => 1, )
Delete an invoice based on its ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/delete/invoice', [ 'json' => [ 'id' => 39465, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', 'invoice' => array ( 'id' => 39465, 'user_id' => 1234, 'customer_id' => 54398, 'subscription_id' => 5047, 'charge_id' => 583, 'additional_charge_id' => NULL, 'card_id' => 365, 'address_id' => 0, 'amount_due' => 198, 'currency' => 'USD', 'discount_id' => 0, 'discount' => '0.00', 'shipping' => 0, 'shipping_total' => 0, 'tax' => 0, 'status' => 'Draft', 'paid' => 0, 'subtotal' => 198.98, 'attempted' => 0, 'attempt_count' => 0, 'due_date' => 0, 'next_payment_attempt' => 0, 'period_end' => 0, 'period_start' => 0, 'tax_total' => 0, 'tax_rule_name' => NULL, 'refunded_amount' => 0, 'webhooks_delivered_at' => 0, 'skipped_at' => NULL, 'paid_on' => 0, 'promo_id' => 0, 'promo_code' => '', 'promo_uses' => 0, 'integration_errors' => '', 'carrier' => '', 'service' => '', 'tracking_number' => '', 'is_order' => 1, 'shopify_created_at' => NULL, 'metadata' => NULL, 'tax_integration_id' => NULL, 'tax_calculated_at' => NULL, 'tax_status' => NULL, 'tax_date' => NULL, 'created_at' => '2024-03-02T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => '2024-03-04T11:24:00.000000Z', ), )
Updating the next payment date of the upcoming invoice.
APPLY TO ALL FUTURE INVOICES
Setting this option to true
WILL change the customer's billing cycle and future payment dates based on the chosen date.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/invoices/39465/next-payment-date', [ 'json' => [ 'next_payment_attempt' => 1709551440, 'all' => true, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 39465, 'user_id' => 1234, 'customer_id' => 54398, 'subscription_id' => 0, 'charge_id' => 0, 'additional_charge_id' => NULL, 'card_id' => 0, 'address_id' => 0, 'amount_due' => 198, 'currency' => 'USD', 'discount_id' => 0, 'discount' => '0.00', 'shipping' => 0, 'shipping_total' => 0, 'tax' => 0, 'status' => 'Scheduled', 'paid' => 0, 'subtotal' => 198.98, 'attempted' => 0, 'attempt_count' => 0, 'due_date' => 0, 'next_payment_attempt' => 1709551440, 'period_end' => 1709551440, 'period_start' => 0, 'tax_total' => 0, 'tax_rule_name' => NULL, 'refunded_amount' => 0, 'webhooks_delivered_at' => 0, 'skipped_at' => NULL, 'paid_on' => 0, 'promo_id' => 0, 'promo_code' => '', 'promo_uses' => 0, 'integration_errors' => '', 'carrier' => '', 'service' => '', 'tracking_number' => '', 'is_order' => 1, 'shopify_created_at' => NULL, 'metadata' => NULL, 'tax_integration_id' => NULL, 'tax_calculated_at' => NULL, 'tax_status' => NULL, 'tax_date' => NULL, 'created_at' => '2024-03-03T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, 'profile' => array ( 0 => array ( 'name' => 'select-1454375030381', 'label' => 'Ground or Whole Bean?', 'answer' => 'Whole Bean', ), ), 'items' => array ( 0 => array ( 'id' => 2543, 'type' => 'plan', 'user_id' => 0, 'customer_id' => 0, 'invoice_id' => 39465, 'plan_id' => 64524, 'quantity' => 2, 'description' => 'Subscription to Coffee Daily 1', 'amount' => 99, 'currency' => 'USD', 'image' => NULL, 'tax_code' => NULL, 'sku' => '', 'vendor_product_id' => NULL, 'upsell_index' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-05T11:24:00.000000Z', 'deleted_at' => NULL, ), ), )
Payment gateways are where you'll set up your business and bank account information so that PayWhirl's automatic transactions can deposit funds into your bank account.
During the development and testing phase, the PayWhirl Test Gateway will allow you to use your plans and create charges without any actual transaction taking place, so you can verify the integrity of your system and experiment with the available methods.
The methods in this section allow you to view the status of all gateways associated with your account, or to check the information about a single gateway.
Get a list of payment gateways associated with your account.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/gateways/');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 836, 'user_id' => 1234, 'name' => 'PayWhirl Test Gateway', 'type' => 'PaywhirlTest', 'error_message' => '', 'expires' => 0, 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), 1 => array ( 'id' => 837, 'user_id' => 1234, 'name' => 'Stripe Connect', 'type' => 'StripeConnect', 'error_message' => '', 'expires' => 0, 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), )
Get a single payment gateway by ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/gateway/836');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 836, 'user_id' => 1234, 'name' => 'PayWhirl Test Gateway', 'type' => 'PaywhirlTest', 'error_message' => '', 'expires' => 0, 'metadata' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
Sometimes it's useful to do a one-time charge, often as a signup fee, or so that you don't need to deal with multiple payment services for non-recurring transactions.
The charge methods offer a simple way to create an invoice with just a charge amount and a customer ID, and to review the contents of a single charge without looking at the entire invoice.
If you want to keep track of the individual charge id
, it's returned after a create charge
in
items[index]->id
.
You can also refund a charge by its id
.
Create an invoice with a single charge.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/create/charge', [ 'json' => [ 'customer_id' => 54398, 'amount' => 100.99, 'quantity' => 2, 'description' => 'Whole Bean', 'sku' => 'sku-123', 'schedule' => 1709555040, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 72464, 'user_id' => 1234, 'customer_id' => 54398, 'subscription_id' => 0, 'charge_id' => 0, 'additional_charge_id' => NULL, 'card_id' => 9534, 'address_id' => 0, 'amount_due' => 201.98, 'currency' => 'USD', 'discount_id' => 0, 'discount' => '0.00', 'shipping' => 0, 'shipping_total' => 0, 'tax' => 0, 'status' => 'Scheduled', 'paid' => 0, 'subtotal' => 201.98, 'attempted' => 0, 'attempt_count' => 0, 'due_date' => 0, 'next_payment_attempt' => 1709555040, 'period_end' => 1709555040, 'period_start' => 0, 'tax_total' => 0, 'tax_rule_name' => '', 'refunded_amount' => 0, 'webhooks_delivered_at' => 0, 'skipped_at' => NULL, 'paid_on' => 0, 'promo_id' => 0, 'promo_code' => '', 'promo_uses' => 0, 'integration_errors' => '', 'carrier' => '', 'service' => '', 'tracking_number' => '', 'is_order' => 1, 'shopify_created_at' => NULL, 'metadata' => NULL, 'tax_integration_id' => NULL, 'tax_calculated_at' => '2024-03-04 11:24:00', 'tax_status' => 'success', 'tax_date' => '2024-03-04 12:24:00', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, 'items' => array ( 0 => array ( 'id' => 365, 'type' => 'fee', 'user_id' => 1234, 'customer_id' => 54398, 'invoice_id' => 72464, 'plan_id' => NULL, 'quantity' => 2, 'description' => 'Whole Bean', 'amount' => 100.99, 'currency' => 'USD', 'image' => NULL, 'tax_code' => '', 'sku' => 'sku-123', 'vendor_product_id' => NULL, 'upsell_index' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, ), ), )
Get a single charge using the charge ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/charge/342');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 342, 'user_id' => 1234, 'customer_id' => 54398, 'gateway_id' => 18, 'gateway_reference' => 'ch_171eGCKsdBiM5uJj5rY', 'amount' => 20.3, 'currency' => 'USD', 'usd' => '19.99', 'description' => 'Payment for Invoice #52', 'fee' => 0, 'bill_fee' => 0, 'fee_item_id' => '0', 'fee_refund_item_id' => '0', 'refunded' => 0, 'refunded_on' => NULL, 'refunded_amount' => 0, 'refund_reference' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Refund a single charge with the whole or partial amount.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/refund/charge/342', [ 'json' => [ 'refund_amount' => '1.99', 'mark_only' => true, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 342, 'user_id' => 1234, 'customer_id' => 54398, 'gateway_id' => 18, 'gateway_reference' => 'ch_171eGCKsdBiM5uJj5rY', 'amount' => 20.3, 'currency' => 'USD', 'usd' => '19.99', 'description' => 'Payment for Invoice #52', 'fee' => 0, 'bill_fee' => 0, 'fee_item_id' => '0', 'fee_refund_item_id' => '0', 'refunded' => 1, 'refunded_on' => 1709551440, 'refunded_amount' => 1.99, 'refund_reference' => 'Manually marked as refunded.', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
The card object handles the storage and creation of credit card information, along with a reference to the payment gateway you want to use to process charges.
Because it's important never to store unencrypted card information, we only accept Stripe, Braintree, Authorize.net, or Square card tokens.
However, if you're using the PayWhirl Test Gateway when building a service, we do allow test cards to be entered manually.
Get a list of cards associated with a given customer ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/cards/54398');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 34, 'user_id' => 1234, 'customer_id' => 54398, 'gateway_id' => 18, 'gateway_reference' => '783789y6r890', 'brand' => 'Visa', 'funding' => 'Credit', 'country' => 'US', 'last4' => '4242', 'exp_date' => '12/2032', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), 1 => array ( 'id' => 35, 'user_id' => 1234, 'customer_id' => 54398, 'gateway_id' => 18, 'gateway_reference' => '783789y6r891', 'brand' => 'Mastercard', 'funding' => 'debit', 'country' => 'US', 'last4' => '4242', 'exp_date' => '12/2032', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), )
Get a single card by passing in the card's ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/card/34');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 34, 'user_id' => 1234, 'customer_id' => 54398, 'gateway_id' => 18, 'gateway_reference' => '783789y6r890', 'brand' => 'Credit', 'funding' => 'Credit', 'country' => 'Ecuador', 'last4' => '4242', 'exp_date' => '12/2032', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
Create card information to store with a customer.
To create a card, you need to supply an object containing customer information along with a Stripe, Braintree or Authorize.net token.
If you are managing card information in your own software, you must ensure that you are adhering to the Payment Card Industry (PCI)
security standards. Their documentation can be found here.
You will choose the token type based on the gateway being used. For a test gateway, you can supply test card information using the
extra parameters below.
Stripe integrations, please check documentation on how to obtain a stripeToken and send that to the server.
Additionally, please check documentation on how to save card details requiring Strong Customer Authentication (SCA). This endpoint allows you to send paymentMethodId or paymentIntentId instead of stripeToken if you are using the new Stripe Payment Intents API.
Braintree integrations, please check documentation on how to obtain the payment method nonce and send that to the server.
Authorize.net integrations, please check documentation on how to obtain the dataDescriptor and dataValue tokens and send those to the server.
Square integrations, please check documentation on how to obtain a secure single-use token (nonce) and send that to the server.
Email Settings: this method will trigger the New Card Email event if you've elected to create and use a new card email.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/create/card', [ 'json' => [ 'id' => 54398, 'number' => '4242424242424242', 'exp_month' => '12', 'exp_year' => '2024', 'first_name' => 'John', 'last_name' => 'Doe', 'address' => '123 Main St', 'city' => 'Springfield', 'state' => 'IL', 'zip' => '62701', 'country' => 'US', ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => '1234546', 'user_id' => 1234, 'customer_id' => 54398, 'gateway_id' => 18, 'gateway_reference' => '66ac9a3e6404f', 'brand' => 'Credit', 'funding' => 'Credit', 'country' => 'US', 'last4' => '4242', 'exp_date' => '12/2024', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
Delete a card based on the card's unique card ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/delete/card', [ 'json' => [ 'id' => 12353, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Promo codes allow you to specify special prices for limited amounts of time or for a certain number of users, without the need to create multiple temporary plans.
The methods in this section allow you to view, create, and delete promo codes.
A promo code object itself stores a reference to the plans it affects, so you might do something like create a 20% off code for the first 100 customers that use any of your plans.
Get a list of all promo codes on file.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/promo/');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 836, 'user_id' => 1234, 'code' => 'PROMO-1234', 'amount_off' => NULL, 'percent_off' => 10, 'duration' => 'once', 'duration_uses' => 0, 'redeem_by' => 0, 'max_redemptions' => 0, 'times_redeemed' => 0, 'is_valid' => 1, 'one_use' => 0, 'apply_to' => 'grandtotal', 'plans' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, ), 1 => array ( 'id' => 837, 'user_id' => 1234, 'code' => 'PROMO-9876', 'amount_off' => NULL, 'percent_off' => 10, 'duration' => 'once', 'duration_uses' => 0, 'redeem_by' => 0, 'max_redemptions' => 0, 'times_redeemed' => 0, 'is_valid' => 1, 'one_use' => 0, 'apply_to' => 'grandtotal', 'plans' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, ), )
Get a promo code.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/promo/365');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 365, 'user_id' => 1234, 'code' => 'PROMO-1234', 'amount_off' => NULL, 'percent_off' => 10, 'duration' => 'once', 'duration_uses' => 0, 'redeem_by' => 0, 'max_redemptions' => 0, 'times_redeemed' => 0, 'is_valid' => 1, 'one_use' => 0, 'apply_to' => 'grandtotal', 'plans' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Create a promo code.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/create/promo', [ 'json' => [ 'code' => '1STSUB20', 'duration' => 'once', 'percent_off' => 20, 'max_redemptions' => 300, 'redeem_by' => 1717500240, 'apply_to' => 'subtotal', 'one_use' => 1, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 7467, 'user_id' => 1234, 'code' => '1STSUB20', 'amount_off' => '0.00', 'percent_off' => 20, 'duration' => 'once', 'duration_uses' => 0, 'redeem_by' => 1717500240, 'max_redemptions' => 300, 'times_redeemed' => 0, 'is_valid' => 1, 'one_use' => 1, 'apply_to' => 'subtotal', 'plans' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', 'deleted_at' => NULL, )
Delete a promo code by passing in the promo ID.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/delete/promo', [ 'json' => [ 'id' => 1234, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
Gift Codes allow you to create objects that store a limited amount of value, which allow your customers to use their gift code balance instead of your regular currency.
Get a list of all gift codes on file.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/gift-codes/');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => NULL, 'code' => '222-WKO-731', 'amount' => 10, 'remaining' => 8.99, 'currency' => 'USD', 'sender_id' => 71756, 'sender' => 'Thomas Tester', 'recipient_email' => 'recipient@example.com', 'redeemer_id' => 83595, 'redeemer' => 'Awesome Person', 'redeemer_email' => 'recipient@example.com', 'send_on' => NULL, 'redeemed_at' => NULL, 'gift_message' => 'A wonderful gift awaits!', 'sent_at' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', ), 1 => array ( 'id' => NULL, 'code' => '947-EFC-851', 'amount' => 15, 'remaining' => 15, 'currency' => 'USD', 'sender_id' => 71756, 'sender' => 'Thomas Tester', 'recipient_email' => 'recipient@example.com', 'redeemer_id' => 83595, 'redeemer' => 'Awesome Person', 'redeemer_email' => 'recipient@example.com', 'send_on' => NULL, 'redeemed_at' => NULL, 'gift_message' => 'Hey here is a present for you!', 'sent_at' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', ), )
The email section of the API just returns any emails you've created via the email-template page.
This is mostly used for displaying a page in your app that is identical to those you send to customers automatically when they make purchases or initially register.
For information on when your emails will be automatically sent, check your email settings page on your dashboard.
Get a single email template via email ID. You can find your email ids at the end of the URL in the paywhirl email-template page. This functionality is mostly used to acquire copies of emails that are automatically sent on a variety of triggers. The template builder on the main paywhirl site is currently the best way to create and edit your templates.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/email/453');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 453, 'user_id' => 1234, 'type' => '', 'name' => 'Welcome Email', 'from_name' => '', 'subject' => 'Welcome Aboard!', 'created_from' => 'welcome', 'template' => '
', 'error_message' => '', 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
Send a system generated email.
Email Settings: this method will trigger the corresponding email event if you've enabled it.
The parameters you pass in will be different depending on the email you want to send. The following list contains the basic structures that go
with each type
,
while the parameter section below will indicate where to find specific id
s or tokens.
"Welcome"
, customer_id
"NewSubscription"
, customer_id
, invoice_id
"CancelledSubscription"
, customer_id
, invoice_id
"NewCard"
, customer_id
, card_id
"PaymentReminder"
, customer_id
, invoice_id
"PaymentReceipt"
, customer_id
, invoice_id
"PaymentRequest"
, customer_id
, invoice_id
"ChargeFailed"
, customer_id
, invoice_id
"PasswordReminder"
, customer_id
, token (optional)
"RefundPayment"
, customer_id
, charge_id
"ProfileUpdate"
, customer_id
, changes[]
"RedeemGiftCode"
, customer_id
, gift_code_id
customer_id
using get customers
invoice_id
using get invoices
subscription_id
can be used instead of invoice_id
param for NewSubscription and
CancelledSubscription emails
card_id
using get cards
charge_id
using get charge
gift_code_id
using get gift codes
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/send-email/', [ 'json' => [ 'type' => 'PasswordReminder', 'customer_id' => 54398, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'status' => 'success', )
The account object is our internal representation of you or your company.
The information contained here also has information related to your account settings, so you can use this to determine the state of each variable option in your dashboard without needing to log in to the app to check each submenu.
In other methods, you might also have noticed a user_id
field, which refers to the id of the account holder (you or your business)
rather
than any of your users.
Get information about the account of the user calling this method. (The account information returned is the account that matches the API credentials used to connect to the PayWhirl API.)
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/account');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 1234, 'company_name' => 'Selling Business Things Inc.', 'email' => 'a.business.email@companyName.com', 'plan' => 'ultimate', 'trial_end' => 1710156240, 'first_name' => 'Business', 'last_name' => 'Person', 'address' => '', 'city' => '', 'country' => 'US', 'state' => '', 'phone' => '', 'zip' => '', 'gateway_id' => 1, 'currency' => 'USD', 'login_enabled' => 1, 'logo' => '', 'promo_codes' => 1, 'reg_enabled' => 1, 'retry_days' => 7, 'slug' => 'sell-business-things-inc', 'application_fee_percent' => 3, 'badge' => 'on', 'favicon' => NULL, 'timezone' => NULL, 'send_reminders' => 3, 'email_settings' => array ( 'test_mode' => 'off', 'welcome_email' => 'default', 'welcome_email_cc' => '', 'new_subscription' => 'default', 'new_subscription_cc' => '', 'cancel_subscription' => 'default', 'cancel_subscription_cc' => '', 'new_card' => 'default', 'new_card_cc' => '', 'payment_reminder' => 'default', 'payment_reminder_cc' => '', 'payment_receipt' => 'default', 'payment_receipt_cc' => '', 'payment_problem' => 'default', 'payment_problem_cc' => '', 'payment_request' => 'default', 'payment_request_cc' => '', 'password_reminder' => 'default', 'profile_update' => 'off', 'profile_update_cc' => '', 'email_via' => 'paywhirl', 'host' => '', 'username' => '', 'password' => '', 'from_address' => '', 'from_name' => '', 'port' => '', ), 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
Get invoice and revenue statistics about the account of the user calling this method. (The account information returned is the account that matches the API credentials used to connect to the PayWhirl API.)
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/stats');
Sample response:var_export(json_decode($response->getBody())); array ( 'plan' => 'ultimate', 'company_name' => 'Selling Business Things Inc.', 'logo' => '', 'active' => 1, 'trial_end' => '2024-03-11 11:24:00', 'customers' => 1, 'invoices' => 3, 'revenue_today' => '436.34', 'revenue_month' => '5892.79', 'revenue_total' => '29947.02', )
Shipping rules allow you to create and review shipping prices for items based on things like customer location or item price.
These are often used to handle covering international shipping costs, or to allow for deals like "free shipping on orders over $50".
Shipping rules can be created in the "Settings & Account" section of the PayWhirl dashboard.
Get all shipping rules.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/shipping/');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 365, 'user_id' => 1234, 'name' => 'Local Shipping', 'type' => 'in_location', 'plan_id' => 0, 'min_price' => 0, 'max_price' => 0, 'country' => 'CA', 'state' => '', 'zip' => '', 'shipping_price' => 5, 'zero_price' => 0, 'restrict_location' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), 1 => array ( 'id' => 366, 'user_id' => 1234, 'name' => 'International Shipping', 'type' => 'out_location', 'plan_id' => 0, 'min_price' => 0, 'max_price' => 0, 'country' => 'US', 'state' => '', 'zip' => '', 'shipping_price' => 15, 'zero_price' => 0, 'restrict_location' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), )
Get a single shipping rule. Shipping rules can be created in the "Settings & Account" section of the PayWhirl dashboard.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/shipping/365');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 365, 'user_id' => 1234, 'name' => 'Local Shipping', 'type' => 'in_location', 'plan_id' => 0, 'min_price' => 0, 'max_price' => 0, 'country' => 'CA', 'state' => '', 'zip' => '', 'shipping_price' => 5, 'zero_price' => 0, 'restrict_location' => NULL, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
Tax rules allow you to set specific percentages to charge based on customer location.
In general, you create a tax rule by choosing a name, a percentage, and a region. After the rules are made, customers in the set regions will automatically have the tax rules applied.
Tax rules can be created in the "Settings & Account" section of the PayWhirl dashboard.
Get all tax rules.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/tax/');
Sample response:var_export(json_decode($response->getBody())); array ( 0 => array ( 'id' => 365, 'user_id' => 1234, 'name' => 'VAT', 'country' => 'GB', 'state' => '', 'zip' => '', 'tax_price' => 20, 'tax_shipping' => 0, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), 1 => array ( 'id' => 366, 'user_id' => 1234, 'name' => 'New York sales tax', 'country' => 'US', 'state' => 'New York', 'zip' => '', 'tax_price' => 4, 'tax_shipping' => 0, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', ), )
Get a single tax rule. Tax rules can be created in the "Settings & Account" section of the PayWhirl dashboard.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('GET', '/tax/365');
Sample response:var_export(json_decode($response->getBody())); array ( 'id' => 365, 'user_id' => 1234, 'name' => 'VAT', 'country' => 'GB', 'state' => '', 'zip' => '', 'tax_price' => 20, 'tax_shipping' => 0, 'created_at' => '2024-03-04T11:24:00.000000Z', 'updated_at' => '2024-03-04T11:24:00.000000Z', )
MultiAuth tokens are usually used as a method for allowing your customers to skip dealing with a PayWhirl login after they've decided to make a purchase. If you've chosen to embed PayWhirl widgets into your page or app, including a MultiAuth token in your widget script allows your customers to go straight from selecting an option directly to payment.
For other purposes, you can also use the MultiAuth tokens to redirect your customers directly to their carts, show them their payment schedules, and log them in via a PayWhirl button. Each of these options will be explained in slightly more detail below, after the rest make sense conceptually.
A MultiAuth token will expire at the end of the given duration, it will not be 'consumed' when used.
For the timestamp, you will want to use a UTC timestamp that is current_time + seconds_in_24_hours
rather than
seconds_in_24_hours
.
Get a MultiAuth token to use to automatically login a customer to a widget.
The most common method for embedding a widget into an HTML page is to copy and paste your the script from the bottom of the page after selecting
edit
from this table.
You can also find the table at by following this path from your dashboard.
Widgets & Forms > Manage Widgets > Edit
At the bottom of the edit page, there will be two embed codes that have the following form:
<script type="text/javascript" id='{your account id}' src="https://app.paywhirl.com/pw.js"> </script> <script> paywhirl('widget', {domain:'{your paywhirl domain}', autoscroll: 1, uuid:'{the uuid of your widget}'}, '{your account id}'); </script>
In general, copy-pasting the script from your widget page will work fine. But to add a login token that allows customers to skip that step
because
they're already logged in to your service, you need to use the get multiauth
method to retrieve a token for whichever customer you
want to log in,
then you can use your favorite method to generate the following snippet:
<script type="text/javascript"
id='{your account id}'
src="https://app.paywhirl.com/pw.js">
</script>
<script> paywhirl('widget',
{domain:'{your paywhirl domain}',
multiauth: '{your multiauth_token}',
autoscroll: 1,
uuid:'{the uuid of your widget}'},
'{your account id}');
</script>
When you use the get multiauth
method, a token is returned, along with the customer's ID and email address so you can verify the
correct
customer was selected before you generate a login code for them.
Another set of options is to replace the widget
string in the examples with cart
to skip directly to checkout;
button
to generate a small "Buy now with PayWhirl" button that will display your widgets in a new frame; or create
to display the selected customer's payment calendar.
Sample request:$client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.paywhirl.com', 'headers' => ['api-key' => $apiKey, 'api-secret' => $apiSecret], ]); $response = $client->request('POST', '/multiauth', [ 'json' => [ 'id' => 54398, ] ]);
Sample response:var_export(json_decode($response->getBody())); array ( 'multiauth_token' => 'raiI3...ZyI6IiJ9', 'email' => 'awesome+person37@example.com', 'id' => 54398, )
Webhooks will allow you to receive push notifications for your account. Certain third-party plugins will create them for you or ask your to register your webhooks URL. You can register a URL under the Developer tab on your PayWhirl account page. You can choose the event types you want to be notified for. The object to the right shows the format the data will be sent in.
As an optional security precaution, you may enter a signing secret to confirm the webhook notification was sent by PayWhirl. PayWhirl signs the full response HTTP body with a SHA256 HMAC hashing function using the secret you enter and sends the hash as "Paywhirl-Secret" HTTP header so you can validate against it.
For any fields with variable output types, there is a small explanation beneath the example webhook object on the right.
Customer Created
The JSON object will have the following form:
{ "type": String, "customer": Object, "answers": Array.of(Object) }
Example:
{
"type": "customer.created",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"answers": [
{
"label": "Is the sky blue?",
"answer": "Yes"
},
{
"label": "Are all skies on all planets blue?",
"answer": "Maybe?"
}
]
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Customer Updated
The JSON object will have the following form:
{ "type": String, "customer": Object, "answers": array.of(Object) }
Example:
{
"type": "customer.updated",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"answers": [
{
"label": "Is the sky blue?",
"answer": "Yes"
},
{
"label": "Are all skies on all planets blue?",
"answer": "Maybe?"
}
]
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Plan Created
The JSON object will have the following form:
{ "type": String, "plan": Object }
Example:
{
"type": "plan.created",
"plan": {
"questions": "[{\"name\":\"checkbox-1513638794611\",\"repeated\":1}]",
"name": "webhook test plan",
"billing_amount": "0.01",
"billing_interval": "1",
"billing_dates": "[]",
"billing_frequency": "month",
"require_shipping": "1",
"require_tax": "1",
"trial_days": "5",
"sku": "455KHU67",
"setup_fee": "5.05",
"autorenew_setup_fee": "0",
"billing_cycle_anchor": "0",
"billing_cycle_anchor_time": "",
"currency": "USD",
"enabled": "1",
"installments": "0",
"autorenew_plan": "0",
"tags": "testplan, masterplan, goodplan?",
"user_id": 1,
"file": "",
"updated_at": "2018-02-07 00:15:13",
"created_at": "2018-02-07 00:15:13",
"id": 41052
}
}
If the "billing_frequency" field is set to "dates" you will see the following
form:
{
"billing_frequency": "dates",
"billing_dates": "[\"2018-03-21\",\"2018-03-31\",\"2018-03-07\"]",
}
Plan Updated
The JSON object will have the following form:
{ "type": String, "plan": Object }
Example:
{
"type": "plan.updated",
"plan": {
"id": 23,
"user_id": 1,
"name": "webhook test plan",
"setup_fee": "5.05",
"installments": "0",
"require_shipping": "1",
"active": 0,
"image": "",
"starting_day": 0,
"description": "A fantastic plan!",
"metadata": "{\"4277\":{\"place_orders\":\"all\"},\"4280\":{\"place_orders\":\"all\",\"customer_group\":\"none\"}}",
"created_at": "2018-02-07 00:15:13",
"updated_at": "2018-02-07 00:20:42",
"billing_amount": "0.11",
"billing_interval": "1",
"billing_frequency": "month",
"billing_dates": "[]",
"trial_days": "0",
"sku": "455KHU67",
"currency": "USD",
"require_tax": "1",
"billing_cycle_anchor": "0",
"billing_cycle_anchor_time": "",
"deleted_at": null,
"file": "",
"autorenew_plan": "0",
"tags": "testplan, masterplan, good... plan?",
"enabled": "1",
"questions": "[{\"name\":\"checkbox-1513638794611\",\"repeated\":1}]",
"autorenew_setup_fee": "0"
}
}
If the "billing_frequency" field is set to "dates" you will see the following
form:
{
"billing_frequency": "dates",
"billing_dates": "[\"2018-03-21\",\"2018-03-31\",\"2018-03-07\"]",
}
Card Created
The JSON object will have the following form:
{ "type": String, "customer": Object, "card": Object }
Example:
{
"type": "card.created",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"card": {
"gateway_reference": "5a7a47e944e3b",
"brand": "Credit",
"funding": "Credit",
"country": "US",
"customer_id": 29489320,
"last4": "2222",
"user_id": 1,
"gateway_id": 18,
"updated_at": "2018-02-07 00:27:21",
"created_at": "2018-02-07 00:27:21",
"id": 15
}
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Card Deleted
The JSON object will have the following form:
{ "type": String, "customer": Object, "card": Object }
Example:
{
"type": "card.deleted",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "2018-02-05 13:42:23",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"card": {
"gateway_reference": "5a7a47e944e3b",
"brand": "Credit",
"funding": "Credit",
"country": "US",
"customer_id": 29489320,
"last4": "2222",
"user_id": 1,
"gateway_id": 18,
"updated_at": "2018-02-07 00:27:21",
"created_at": "2018-02-07 00:27:21",
"id": 15
}
}
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Subscription Created
The JSON object will have the following form:
{ "type": String, "customer": Object, "subscription": Object, "invoice": Object }
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
Example:
{
"type": "subscription.created",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"subscription": {
"user_id": 1,
"customer_id": 36,
"plan_id": 1,
"widget_id": 0,
"quantity": "1",
"cancel_at_period_end": 0,
"current_period_start": 1517963629,
"current_period_end": 1517963629,
"updated_at": "2018-02-07 00:33:49",
"created_at": "2018-02-07 00:33:49",
"id": 1337
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 27,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 0,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 0,
"attempt_count": 0,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 1517963629,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Subscribed",
"paid": 0,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"paid_on": 0,
"deleted_at": null,
"promo_id": 0,
"promo_code": "123PROMO",
"promo_uses": 0,
"integration_errors": "",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": null,
"is_queued": 0
}
}
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Subscription Updated
The JSON object will have the following form:
{ "type": String, "customer": Object, "subscription": Object, "invoice": Object, "order_address": Object }
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
Example:
{
"type": "subscription.updated",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"subscription": {
"user_id": 1,
"customer_id": 36,
"plan_id": 1,
"widget_id": 0,
"quantity": "1",
"cancel_at_period_end": 0,
"current_period_start": 1517963629,
"current_period_end": 1517963629,
"updated_at": "2018-02-07 00:33:49",
"created_at": "2018-02-07 00:33:49",
"id": 1337
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 27,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 0,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 0,
"attempt_count": 0,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 1517963629,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Subscribed",
"paid": 0,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"paid_on": 0,
"deleted_at": null,
"promo_id": 0,
"promo_code": "123PROMO",
"promo_uses": 0,
"integration_errors": "",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": null,
"is_queued": 0
},
"order_address": {
"first_name": "Terrelle",
"last_name": "Suggs",
"address": "3322 Golfers Dr",
"city": "Oceanside",
"state": "California",
"zip": "92056",
"country": "US",
"phone": "3105555555"
}
}
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Subscription Deleted
The JSON object will have the following form:
{ "type": String, "customer": Object, "subscription": Object, "invoice": Object }
Example:
{
"type": "subscription.deleted",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"subscription": {
"id": 150700,
"user_id": 1,
"customer_id": 27,
"plan_id": 41052,
"widget_id": 0,
"quantity": 1,
"cancel_at_period_end": 0,
"current_period_start": 1517963629,
"current_period_end": 1520382829,
"trial_start": 0,
"trial_end": 0,
"installment_plan": 0,
"installments_left": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 27,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 361457,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 1,
"attempt_count": 1,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 0,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Paid",
"paid": 1,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:53",
"paid_on": 1517963629,
"deleted_at": null,
"promo_id": 0,
"promo_code": "",
"promo_uses": 0,
"integration_errors": "null",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": "2018-02-07 00:33:52",
"is_queued": 0
}
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Invoice Created
The JSON object will have the following form:
{ "type": String, "customer": Object, "invoice": Object, "items": Array.of(Object), "answers": Array.of(Object) }
Example:
{
"type": "invoice.created",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"invoice": {
"customer_id": 227913,
"currency": "USD",
"shipping": 1,
"tax": 1,
"status": "Subscribed",
"period_start": 1517963629,
"period_end": 1517963629,
"next_payment_attempt": 1517963629,
"card_id": 273194,
"updated_at": "2018-02-07 00:33:49",
"created_at": "2018-02-07 00:33:49",
"id": 461175,
"user_id": 6529,
"subscription_id": 150700,
"subtotal": 0.11,
"discount": 0,
"tax_total": 0,
"shipping_total": 600,
"amount_due": 600.11,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 1,
"customer_id": 27,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
},
"answers": [
{
"label": "Is the sky blue?",
"answer": "Yes"
},
{
"label": "Are all skies on all planets blue?",
"answer": "Maybe?"
}
]
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Invoice Processed
The JSON object will have the following form:
{ "type": String, "customer": Object, "invoice": Object, "items": Array.of(Object) }
Example:
{
"type": "invoice.processed",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 27,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 0,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 1,
"attempt_count": 1,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 1517963629,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Attempting Payment",
"paid": 0,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"paid_on": 1517963629,
"deleted_at": null,
"promo_id": 0,
"promo_code": "123PROMO",
"promo_uses": 5,
"integration_errors": "",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": null,
"is_queued": 0,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 6529,
"customer_id": 227913,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
}
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Invoice Paid
The JSON object will have the following form:
{ "type": String, "customer": Object, "invoice": Object, "items": Array.of(Object) }
Example:
{
"type": "invoice.paid",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"invoice": {
"id": 461175,
"user_id": 6529,
"customer_id": 227913,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 361457,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 1,
"attempt_count": 1,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 0,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Paid",
"paid": 1,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"paid_on": 1517963629,
"deleted_at": null,
"promo_id": 0,
"promo_code": "",
"promo_uses": 0,
"integration_errors": "",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": null,
"is_queued": 0,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 6529,
"customer_id": 227913,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
}
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Charge Succeeded
The JSON object will have the following form:
{ "type": String, "customer": Object, "charge": Object, "invoice": Object }
Example:
{
"type": "charge.succeeded",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"charge": {
"gateway_reference": "5a7a496d74572",
"amount": 600.11,
"currency": "USD",
"customer_id": 227913,
"description": "Payment for Invoice #461175",
"user_id": 6529,
"gateway_id": 11203,
"usd": 600.11,
"fee": 0,
"bill_fee": 0,
"updated_at": "2018-02-07 00:33:49",
"created_at": "2018-02-07 00:33:49",
"id": 361457
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 34,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": null,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 1,
"attempt_count": 1,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 0,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Paid",
"paid": 1,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:53",
"paid_on": 1517963629,
"deleted_at": null,
"promo_id": 0,
"promo_code": "123PROMO",
"promo_uses": 0,
"integration_errors": "null",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": "2018-02-07 00:33:52",
"is_queued": 0,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 1,
"customer_id": 34,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
}
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Charge Failed
The JSON object will have the following form:
{ "type": String, "customer": Object, "invoice": Object }
Example:
{
"type": "charge.failed",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 227913,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 0,
"additional_charge_id": null,
"card_id": 0,
"shipping": 0,
"tax": 0,
"attempted": 1,
"attempt_count": 0,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 1517966629,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Cannot charge a customer that has no active card",
"paid": 0,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 0,
"tax_total": 0,
"amount_due": 0.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:53",
"paid_on": 0,
"deleted_at": null,
"promo_id": 0,
"promo_code": "",
"promo_uses": 0,
"integration_errors": "",
"address_id": 0,
"carrier": "",
"service": "",
"tracking_number": "",
"is_order": 1,
"shopify_created_at": 0,
"is_queued": 0,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 1,
"customer_id": 227913,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
},
"subscription": {
"user_id": 1,
"customer_id": 227913,
"plan_id": 1,
"widget_id": 0,
"quantity": "1",
"cancel_at_period_end": 0,
"current_period_start": 1517963629,
"current_period_end": 1517963629,
"updated_at": "2018-02-07 00:33:49",
"created_at": "2018-02-07 00:33:49",
"id": 150700
},
"plan": {
"questions": "[{\"name\":\"checkbox-1513638794611\",\"repeated\":1}]",
"name": "webhook test plan",
"billing_amount": "0.01",
"billing_interval": "1",
"billing_dates": "[]",
"billing_frequency": "month",
"require_shipping": "1",
"require_tax": "1",
"trial_days": "5",
"sku": "455KHU67",
"setup_fee": "5.05",
"autorenew_setup_fee": "0",
"billing_cycle_anchor": "0",
"billing_cycle_anchor_time": "",
"currency": "USD",
"enabled": "1",
"installments": "0",
"autorenew_plan": "0",
"tags": "testplan, masterplan, goodplan?",
"user_id": 1,
"file": "",
"updated_at": "2018-02-07 00:15:13",
"created_at": "2018-02-07 00:15:13",
"id": 1
}
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Charge Refunded
The JSON object will have the following form:
{ "type": String, "customer": Object, "charge": Object, "invoice": Object, "items": Array.of(Object) }
Example:
{
"type": "charge.refunded",
"customer": {
"id": 34,
"user_id": 1,
"first_name": "Awesome",
"last_name": "Person",
"email": "awesome+person@paywhirl.com",
"phone": "4564564566",
"address": "123 Easy Street",
"city": "Los Angeles",
"state": "California",
"zip": 93003,
"country": "US",
"created_at": "2015-11-17 19:52:34",
"updated_at": "2015-11-21 04:29:45",
"gateway_reference": "783789y6r890",
"default_card": 34,
"gateway_type": "PayPal",
"gateway_id": 18,
"currency": "USD",
"deleted_at": "",
"utm_source": "Google",
"utm_medium": "cpc",
"utm_term": "online payments",
"utm_content": "logolink",
"utm_campaign": "spring_sale",
"utm_group": "users",
"ip_address":"76.176.160.450",
"metadata": ""
},
"charge": {
"id": 361457,
"user_id": 1,
"gateway_reference": "5a7a496d74572",
"amount": 600.11,
"currency": "USD",
"customer_id": 227913,
"description": "Payment for Invoice #461175",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:39:58",
"gateway_id": 11203,
"refunded": 1,
"refund_reference": "5a7a4ade245e6",
"fee": 0,
"bill_fee": 0,
"fee_item_id": 0,
"fee_refund_item_id": 0,
"deleted_at": null,
"usd": "600.11"
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 227913,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 361457,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 1,
"attempt_count": 1,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 0,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Paid",
"paid": 1,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:53",
"paid_on": 1517963629,
"deleted_at": null,
"promo_id": 0,
"promo_code": "123PROMO",
"promo_uses": 0,
"integration_errors": "null",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": "2018-02-07 00:33:52",
"is_queued": 0,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 1,
"customer_id": 227913,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}
Gift Code Sent
The JSON object will have the following form:
{ "type": String, "customer": Object, "giftcode": Object, "invoice": Object, "items": Array.of(Object) }
Example:
{
"type": "giftcode.sent",
"customer": {
id: 34,
user_id: 1,
first_name: 'Awesome',
last_name: 'Person',
email: 'awesome+person@paywhirl.com',
phone: '4564564566',
address: '123 Easy Street',
city: 'Los Angeles',
state: 'California',
zip: 93003,
country: 'US',
created_at: '2015-11-17 19:52:34',
updated_at: '2015-11-21 04:29:45',
gateway_reference: '783789y6r890',
default_card: 34,
gateway_type: 'PayPal',
gateway_id: 18,
currency: 'USD',
deleted_at: '',
utm_source: 'Google',
utm_medium: 'cpc',
utm_term: 'online payments',
utm_content: 'logolink',
utm_campaign: 'spring_sale',
utm_group: 'users',
"ip_address":"76.176.160.450",
metadata: ''
},
"giftcode": {
"id": 2,
"user_id": 1,
"customer_id": 34,
"invoice_item_id": 7880,
"redeemed_by": null,
"redeemed_at": null,
"code": "947-EFC-851",
"amount": 20.00,
"remaining": 20.00,
"currency": "USD",
"gift_message": "A present for you!",
"recipient_email": "friend@paywhirl.com",
"email_template": null,
"redeem_url": null,
"send_on": null,
"sent_at": "2017-10-27 08:22:11",
"created_at": "2017-10-25 12:05:45",
"updated_at": "2017-10-27 08:22:11"
},
"invoice": {
"id": 461175,
"user_id": 1,
"customer_id": 227913,
"discount_id": 0,
"subscription_id": 150700,
"charge_id": 361457,
"additional_charge_id": null,
"card_id": 273194,
"shipping": 1,
"tax": 1,
"attempted": 1,
"attempt_count": 1,
"currency": "USD",
"due_date": 0,
"next_payment_attempt": 0,
"period_end": 1517963629,
"period_start": 1517963629,
"status": "Paid",
"paid": 1,
"subtotal": 0.11,
"discount": "0.00",
"shipping_total": 600,
"tax_total": 0,
"amount_due": 600.11,
"webhooks_delivered_at": 0,
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:53",
"paid_on": 1517963629,
"deleted_at": null,
"promo_id": 0,
"promo_code": "123PROMO",
"promo_uses": 0,
"integration_errors": "null",
"address_id": 0,
"carrier": "UBS",
"service": "SV",
"tracking_number": "1Z 999 AA1 01 2345 6784",
"is_order": 1,
"shopify_created_at": "2018-02-07 00:33:52",
"is_queued": 0,
"items": [
{
"id": 518501,
"type": "plan",
"user_id": 1,
"customer_id": 227913,
"invoice_id": 461175,
"quantity": 1,
"description": "Subscription to webhook test plan",
"amount": 0.11,
"currency": "USD",
"created_at": "2018-02-07 00:33:49",
"updated_at": "2018-02-07 00:33:49",
"deleted_at": null,
"sku": "455KHU67"
}
]
}
The "deleted_at" field will have the same timestamp format as "created_at"
and "updated_at".
The "metadata" field may contain a formatted JSON object:
{
\"extra_data\":\"something\",
\"more_extra_data\":1
}