Introduction
The Partial.ly API allows you to programmatically access the data in your Partial.ly merchant account and create payment plans and payments. The API is currently in beta mode, so there may be minor changes. If you have feedback we would love to hear it.
Our API follows REST principles and accepts and returns all data in JSON format. All requests must include the Accept: application/json
HTTP header. POST and PUT data must be JSON encoded, and must have the Content-Type: application/json
HTTP header.
The base URL for all API calls is https://partial.ly/api.
We also have a staging server at demo.partial.ly, so if you want to test your integration please use the base URL https://demo.partial.ly/api. Note that you will have to register for a separate account here than your live Partial.ly account.
If you have any questions you can't find the answer to here, please contact our support.
Authentication
To authorize, use this code:
curl "https://partial.ly/api/offer" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
Make sure to replace
your_api_key
with your API key.
Partial.ly uses API keys to allow access to the API. You can find your API key in the Partial.ly merchant portal by navigating to Settings > general. If you have don't have any API key yet, click the generate key link to generate a new API key. Your API key carries many privileges, so be sure to keep it secure! Do not share your secret API key in publicly accessible areas such as GitHub, client-side code, and so forth.
Partial.ly expects for the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer your_api_key
All API requests must be made over HTTPS. Calls made over plain HTTP will be redirected to the corresponding HTTPS URL. API requests without authentication will also fail.
Pagination
Most API calls to list resources can be paginated using the following parameters. Some resources will have additional parameters you can use to filter the results.
Parameter | Description |
---|---|
page | the page number to return results for |
per_page | the number of results to return per page |
All response objects will have the following properties, in addition to a property containing the array of results.
Name | Description |
---|---|
page_number | the current page |
page_size | the number of results per page |
total_entires | the total number of objects returned |
total_pages | the total number of pages found |
Errors
{
"message": "Could not create offer",
"errors": [
"Name: can't be blank"
]
}
Successful API calls will return HTTP status code 200. API calls that result in an error will either return HTTP status code 400 is there is a problem with the input, or 404 if a given object could not be found. The response body will be JSON object with a message key giving an overview of the issue. If there are issues with specific fields, there will also be an errors key with an array of field specific errors.
Offers
An offer is a set of terms for a potential payment plan. Think of an offer as a template for a payment plan. There are 3 variables that can be customized for an offer: down payment, payment frequency, and term. Offers can additionally have dynamically added line items, such as a payment plan fee or service charge, which can be a fixed amount or percent of the payment plan subtotal. Offers can be embedded on your website (Shopify, WooCommerce, etc.) to provide a payment plan checkout option for your customers. Or they can be used as template to quickly and easily create payment plans for invoices (FreshBooks, QuickBooks, Harvest)
List All Offers
curl "https://partial.ly/api/offer" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, offers) {
// asynchronous callback function
// offers will be already decoded JSON array of offers
});
The above command returns JSON structured like this:
[
{
"updated_at": "2018-10-05T14:30:20.303624",
"term_units": "months",
"term_min": 3,
"term_max": 6,
"term_flexible": true,
"term_date": "2017-09-27",
"term": 3,
"require_ship_to": null,
"payment_schedule_description": null,
"name": "euro test",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"integration_options": null,
"inserted_at": "2015-09-11T05:50:30.000000",
"id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"frequency_units": "months",
"frequency_min": null,
"frequency_max": null,
"frequency_flexible": false,
"frequency_days": [],
"frequency": 1,
"down_payment_type": "percent",
"down_payment_min": 10,
"down_payment_max": 70,
"down_payment_flexible": false,
"down_payment": 25,
"currency": "EUR",
"auto_process": true
}
]
This endpoint retrieves all offers.
HTTP Request
GET /offer
Get a Specific Offer
curl "https://partial.ly/api/offer/60aed439-473f-48e0-80ef-3a8627dd243a" \
-H "Authorization: Bearer your_api_key"
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer/60aed439-473f-48e0-80ef-3a8627dd243a',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, offer) {
});
The above command returns JSON structured like this:
{
"updated_at": "2018-10-05T14:30:20.303624",
"term_units": "months",
"term_min": 3,
"term_max": 6,
"term_flexible": true,
"term_date": "2017-09-27",
"term": 3,
"require_ship_to": null,
"payment_schedule_description": null,
"name": "euro test",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"integration_options": null,
"inserted_at": "2015-09-11T05:50:30.000000",
"id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"frequency_units": "months",
"frequency_min": null,
"frequency_max": null,
"frequency_flexible": false,
"frequency_days": [],
"frequency": 1,
"down_payment_type": "percent",
"down_payment_min": 10,
"down_payment_max": 70,
"down_payment_flexible": false,
"down_payment": 25,
"currency": "EUR",
"auto_process": true
}
This endpoint retrieves a specific offer.
HTTP Request
GET /offer/:id
replace :id in the URL with the id of the offer to retrieve
Create a new offer
curl "https://partial.ly/api/offer" \
-X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"name": "Sample offer"}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
name: 'Sample offer'
}
};
request(options, function (error, response, offer) {
});
The above command returns JSON structured like this:
{
"updated_at": "2018-10-05T14:30:20.303624",
"term_units": "months",
"term_min": 0,
"term_max": 0,
"term_flexible": false,
"term_date": null,
"term": 3,
"require_ship_to": null,
"payment_schedule_description": null,
"name": "Sample offer",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"integration_options": null,
"inserted_at": "2015-09-11T05:50:30.000000",
"id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"frequency_units": "months",
"frequency_min": null,
"frequency_max": null,
"frequency_flexible": false,
"frequency_days": [],
"frequency": 1,
"down_payment_type": "percent",
"down_payment_min": 0,
"down_payment_max": 0,
"down_payment_flexible": false,
"down_payment": 0,
"currency": "USD",
"auto_process": true
}
This endpoint creates a new offer
HTTP Request
POST /offer
Parameters
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
name | string | yes | The name of the offer | |
auto_process | boolean | no | true | true to automatically schedule future payments, false for manual payments |
payment_schedule_description | string | no | for manual payment plans, a description of the payment schedule | |
currency | string | no | currency in merchant settings | The currency to use for payment plans |
down_payment | decimal | no | 0 | the amount or percent of down payment required, depending on down_payment_type |
down_payment_type | string | no | percent | "percent" for a percent of the payment plan subtotal or "fixed" for a fixed amount |
down_payment_flexible | boolean | no | false | allow the customer to choose their down payment within a specified range |
down_payment_min | decimal | no | min down payment percent or amount | |
down_payment_max | decimal | no | max down payment percent or amount | |
term | integer | no | 3 | the length of the payment plan |
term_units | string | no | months | type of units for the payment plan term. weeks, months, years, payments (a fixed number of payments), or date (pay by a date) |
term_date | date | no | final payment date when using term_units=date | |
term_flexible | boolean | no | false | allow the customer to choose their term within the specified range |
term_min | integer | no | the minimum term the customer can choose | |
term_max | integer | no | the maximum term the customer can choose | |
frequency | integer | no | 1 | the frequency of scheduled payments |
frequency_units | string | no | months | type of units for the payment plan term. days, weeks, months, days_month (for specific days of the month) |
frequency_days | array | no | array of specific days of the month for payments, for example [1, 15] for payments on the 1st and 15th of the month | |
frequency_flexible | boolean | no | false | allow the customer to choose their payment frequency within the specified range |
frequency_min | integer | no | the minimum payment frequency the customer can choose | |
frequency_max | integer | no | the maximum payment frequency the customer can choose | |
starts_auto | boolean | no | false | whether or not the first installment should automatically be scheduled relative to the date plan was opened |
starts_date | date | no | when starts_auto is false, use this date as the first scheduled installment date | |
starts_date_flexible | boolean | no | false | allow the customer to choose their first payment date |
starts_date_max_days | integer | no | the maximum payment frequency the customer can choose |
Update an offer
curl "https://partial.ly/api/offer/60aed439-473f-48e0-80ef-3a8627dd243a" \
-X PUT \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"down_payment": 5}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer/60aed439-473f-48e0-80ef-3a8627dd243a',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
down_payment: 5
}
};
request(options, function (error, response, offer) {
});
The above command returns JSON structured like this:
{
"updated_at": "2018-10-05T14:30:20.303624",
"term_units": "months",
"term_min": 0,
"term_max": 0,
"term_flexible": false,
"term_date": null,
"term": 3,
"require_ship_to": null,
"payment_schedule_description": null,
"name": "Sample offer",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"integration_options": null,
"inserted_at": "2015-09-11T05:50:30.000000",
"id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"frequency_units": "months",
"frequency_min": null,
"frequency_max": null,
"frequency_flexible": false,
"frequency_days": [],
"frequency": 1,
"down_payment_type": "percent",
"down_payment_min": 0,
"down_payment_max": 0,
"down_payment_flexible": false,
"down_payment": 5,
"currency": "USD",
"auto_process": true
}
Updates an existing offer
PUT /offer/:id
replace :id with the id of the offer to update
Same parameters as create offer
Offer Items
Offer items are additional line items that can automatically be added to a payment plan, a customer fee for instance. Offer items can be for fixed amounts or a percent of the payment plan subtotal.
List offer items
curl "https://partial.ly/api/offer_item?offer_id=60aed439-473f-48e0-80ef-3a8627dd243a" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer_item?offer_id=60aed439-473f-48e0-80ef-3a8627dd243a',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
// body.offer_items
});
The above command returns JSON structured like this:
{
"offer_items": [
{
"updated_at": "2018-10-05T14:49:20.558357",
"offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"name": "test api creation",
"inserted_at": "2018-10-05T14:44:59.631679",
"id": "61ed5fdf-fbdf-4b06-9a8a-0fb05cdf6f26",
"amount_type": "percent",
"amount": 2.2
}
]
}
Gets all the offer items associated with an offer
HTTP Request
GET /offer_item
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
offer_id | string | yes | offer id to get offer items for |
Create a new offer item
curl "https://partial.ly/api/offer_item" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
--data '{"name": "processing fee", "amount": 2.5, "amount_type": "percent", "offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer_item',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
offer_id: '60aed439-473f-48e0-80ef-3a8627dd243a',
name: 'processing fee',
amount: 2.5,
amount_type: 'percent'
}
};
request(options, function (error, response, offer_item) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"updated_at": "2018-11-27T21:00:47.730189",
"offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"name": "processing fee",
"inserted_at": "2018-11-27T21:00:47.730182",
"id": "a9bec449-da6e-4dea-ad4a-a716aa90d40c",
"amount_type": "percent",
"amount": 2.5
}
Creates a new offer item associated with an offer
HTTP Request
POST /offer_item
Parameters
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
name | string | yes | The name of the offer item | |
offer_id | string | yes | id of offer to associate item with | |
amount_type | string | yes | either percent or fixed | |
amount | decimal | yes | The amount to add to the plan. For percent will be this percent of the plan subtotal |
Update offer item
curl "https://partial.ly/api/offer_item/a9bec449-da6e-4dea-ad4a-a716aa90d40c" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X PUT \
--data '{"amount": 3.75}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer_item/a9bec449-da6e-4dea-ad4a-a716aa90d40c',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
amount: 3.75
}
};
request(options, function (error, response, offer_item) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"updated_at": "2018-11-27T21:00:47.730189",
"offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"name": "processing fee",
"inserted_at": "2018-11-27T21:00:47.730182",
"id": "a9bec449-da6e-4dea-ad4a-a716aa90d40c",
"amount_type": "percent",
"amount": 3.75
}
updates an existing offer item
PUT /offer_item/:id
replace :id with the id of the offer item to update
Same parameters as create offer item
Delete offer item
curl "https://partial.ly/api/offer_item/a9bec449-da6e-4dea-ad4a-a716aa90d40c" \
-H "Authorization: Bearer your_api_key" \
-X DELETE
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/offer_item/a9bec449-da6e-4dea-ad4a-a716aa90d40c',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'DELETE'
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"message": "OfferItem deleted"
}
deletes an offer item
DELETE /offer_item/:id
replace :id with the id of the offer item to delete
Customers
List All Customers
curl "https://partial.ly/api/customer" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, customers) {
// asynchronous callback function
// offers will be already decoded JSON array of customers
});
The above command returns JSON structured like this:
{
"total_pages": 1,
"total_entries": 2,
"page_size": 10,
"page_number": 1,
"customers": [
{
"timezone": "America/New_York",
"shipto_state": "FL",
"shipto_postal_code": "33601",
"shipto_name": "Sample Customer",
"shipto_country": "US",
"shipto_city": "Tampa",
"shipto_address2": null,
"shipto_address": "123 N. Tampa St.",
"phone": "81325551212",
"last_name": "Customer",
"inserted_at": "2015-09-11T05:54:27.000000",
"id": "6d30d3c8-d024-45cc-9c3f-356fc8aee23d",
"first_name": "Sample",
"email": "sample.customer@gmail.com"
},
{
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": null,
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": "5042265544",
"last_name": "Appleseed",
"inserted_at": "2015-09-23T15:03:20.000000",
"id": "9a426155-a927-4984-8738-0bd1ffc15248",
"first_name": "John",
"email": "jappleseed@yahoo.com"
}
]
}
This endpoint retrieves all customers.
HTTP Request
GET /customer
Query Parameters
Parameter | Description |
---|---|
q | Search query. Will search for email if query contains an @, otherwise will search for partial match on first and last names |
Get a Specific Customer
curl "https://partial.ly/api/customer/9a426155-a927-4984-8738-0bd1ffc15248" \
-H "Authorization: Bearer your_api_key"
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer/9a426155-a927-4984-8738-0bd1ffc15248',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, customer) {
});
The above command returns JSON structured like this:
{
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": null,
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": "5042265544",
"last_name": "Appleseed",
"inserted_at": "2015-09-23T15:03:20.000000",
"id": "9a426155-a927-4984-8738-0bd1ffc15248",
"first_name": "John",
"email": "jappleseed@yahoo.com"
}
This endpoint retrieves a specific customer.
HTTP Request
GET /customer/:id
replace :id in the URL with the id of the customer to retrieve
Create a new customer
curl "https://partial.ly/api/customer" \
-X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"email": "testing@aol.com", "first_name": "John", "last_name": "Doe"}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
email: 'testing@aol.com',
first_name: 'John',
last_name: 'Doe'
}
};
request(options, function (error, response, customer) {
});
The above command returns JSON structured like this:
{
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": "US",
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": null,
"last_name": "Doe",
"inserted_at": "2018-11-27T20:10:19.437168",
"id": "53479e98-27a9-49e2-856c-bf47d0796ffc",
"first_name": "John",
"email": "testing@aol.com"
}
This endpoint creates a new customer
HTTP Request
POST /customer
Parameters
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
string | yes | Customer email | ||
first_name | string | no | First name | |
last_name | string | no | Last name | |
phone | string | no | Phone number | |
language | string | no | en | Customer interface display language |
timezone | string | no | America/New_York | timezone for date formatting |
shipto_name | string | no | default ship to name for customer's payment plans | |
shipto_address | string | no | street address | |
shipto_address2 | string | no | street address line 2 | |
shipto_city | string | no | city | |
shipto_state | string | no | 2 letter state/province/region code | |
shipto_country | string | no | US | 2 letter country code |
shipto_postal_code | string | no | ZIP/postal code | |
password | string | no | if a new user is being created, use the supplied password. Otherwise a random password will be generated |
Update a customer
curl "https://partial.ly/api/customer/53479e98-27a9-49e2-856c-bf47d0796ffc" \
-X PUT \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"phone": "+12125551212"}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer/53479e98-27a9-49e2-856c-bf47d0796ffc',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
phone: '+12125551212'
}
};
request(options, function (error, response, customer) {
});
The above command returns JSON structured like this:
{
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": "US",
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": "+12125551212",
"last_name": "Doe",
"inserted_at": "2018-11-27T20:10:19.437168",
"id": "53479e98-27a9-49e2-856c-bf47d0796ffc",
"first_name": "John",
"email": "testing@aol.com"
}
Updates an existing customer
PUT /customer/:id
replace :id with the id of the customer to update
Same parameters as create customer
GDPR remove
curl "https://partial.ly/api/customer/gdpr_remove/53479e98-27a9-49e2-856c-bf47d0796ffc" \
-X PUT \
-H "Authorization: Bearer your_api_key"
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer/gdpr_remove/53479e98-27a9-49e2-856c-bf47d0796ffc',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true
};
request(options, function (error, response, body) {
});
The above command returns JSON structured like this:
{
"message": "Customer account deleted"
}
Removal of customer information for GDPR. Customers with open payment plans cannot be deleted. If the customer has payment and payment plan information in Partial.ly, the payment and payment plan information will not be deleted, but all personally identifiable customer information will be anonymized. If the customer has no payment plan history all information will be deleted.
PUT /customer/gdpr_remove/:id
replace :id with the id of the customer to to remove
Log in with password
curl "https://partial.ly/api/customer/login_password" \
-X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"email": "aaa@y.co", "password": "test"}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer/login_password',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
email: 'aaa@y.co',
password: 'test'
}
};
request(options, function (error, response, cust) {
});
The above command returns JSON structured like this:
{
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": "US",
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": null,
"last_name": "Person",
"inserted_at": "2018-11-28T16:57:42.923471",
"id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"first_name": "Testing",
"email": "aaa@y.co"
}
Authenticate a customer with their email and password. Alternatively, customers can have a token generated and sent to their email with the email login token method, which can then be used to login with the login with a token method.
POST /customer/login_password
Parameters
Parameter | Type | Required |
---|---|---|
string | yes | |
password | string | yes |
Email login token
curl "https://partial.ly/api/customer/login_email" \
-X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"email": "aaa@y.co"}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer/login_email',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
email: 'aaa@y.co'
}
};
request(options, function (error, response, body) {
});
The above command returns JSON structured like this:
{
"message": "Token sent"
}
Generates a token which can be used with the login with a token method and emails it to the customer.
POST /customer/login_email
Parameters
Parameter | Type | Required |
---|---|---|
string | yes |
Login with a token
curl "https://partial.ly/api/customer/login_token" \
-X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
--data '{"token": "N5E9gL", "email": "aaa@y.co"}'
var request = require('request');
var options = {
url: 'https://partial.ly/api/customer/login_token',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
token: 'N5E9gL',
email: 'aaa@y.co'
}
};
request(options, function (error, response, cust) {
});
The above command returns JSON structured like this:
{
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": "US",
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": null,
"last_name": "Person",
"inserted_at": "2018-11-28T16:57:42.923471",
"id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"first_name": "Testing",
"email": "aaa@y.co"
}
Authenticate a customer with a token generated from the email a login token step.
POST /customer/login_token
Parameters
Parameter | Type | Required |
---|---|---|
token | string | yes |
string | yes |
Payment Methods
A saved payment method attached to a customer. May be any type of credit or debit card.
Create payment method
curl "https://partial.ly/api/payment_method" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
--data '{"type": "card", "token_id": "tok_ch", "customer_id": "452cc42f-d999-4c0f-998b-325c4e0e8f57"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_method',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
customer_id: '452cc42f-d999-4c0f-998b-325c4e0e8f57',
type: 'card',
token_id: 'tok_ch'
}
};
request(options, function (error, response, payment_method) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"type": "card",
"integration_details": {
"last4": "0009",
"funding": "credit",
"exp_year": 2019,
"exp_month": 11,
"country": "CH",
"brand": "Visa"
},
"inserted_at": "2018-11-27T21:38:39.520750",
"id": "36afc659-f03d-485b-a850-65871fa759a7"
}
Example HTML to capture card details with Stripe.js
<form id="payment-form">
<div id="card-element">
<!-- A Stripe Element will be inserted here. -->
</div>
<button id="btnSubmit">Add Payment Method</button>
</form>
<script src="https://js.stripe.com/v3/"></script>
<script>
// partial.ly public key
var publicKey = 'pk_test_eV3vdXbE4SrfLjJYn9XUSUwx',
stripe = Stripe(publicKey),
elements = stripe.elements();
// Create an instance of the card Element.
var card = elements.create('card');
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function() {
// tokenize payment data with Stripe
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error.
alert(result.error.message);
} else {
// use result.token.id to send in the token_id field to Partial.ly
}
});
});
</script>
Payment method details must not be sent directly to Partial.ly. They need to be captured and tokenized with Stripe.js before being sent to Partial.ly.
When creating your Stripe.js object, use the following public key to initialize the Stripe SDK
pk_live_huSEiMMI7gSK7ORKzZB448xr
When testing with our Partial.ly test server, use the following public key
pk_test_eV3vdXbE4SrfLjJYn9XUSUwx
HTTP Request
GET /payment_method
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
customer_id | string | yes | id of customer to associate with |
type | string | yes | "card" |
token_id | string | no | the token id returned from Stripe.js. Required for "card" type |
List payment methods
curl "https://partial.ly/api/payment_method?customer_id=452cc42f-d999-4c0f-998b-325c4e0e8f57" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_method?customer_id=452cc42f-d999-4c0f-998b-325c4e0e8f57',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, payment_methods) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"payment_methods": [
{
"type": "card",
"integration_details": {
"last4": "0009",
"funding": "credit",
"exp_year": 2019,
"exp_month": 11,
"country": "CH",
"brand": "Visa"
},
"inserted_at": "2018-11-27T21:38:39.520750",
"id": "36afc659-f03d-485b-a850-65871fa759a7"
},
{
"type": "bank_account",
"integration_details": {
"routing_number": "110000000",
"plaid_access_token": "access-sandbox-a5232606-49c8-4768-b07e-4fd0baf38c21",
"last4": "6789",
"country": "US",
"bank_name": "STRIPE TEST BANK",
"account_holder_type": null,
"account_holder_name": null
},
"inserted_at": "2018-06-05T13:33:04.980000",
"id": "1754a33c-419f-4233-9c62-7fd9f5f7d088"
}
]
}
Gets the list of payment methods associated with a customer
HTTP Request
GET /payment_method
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
customer_id | string | yes | id of customer to get payment methods for |
Delete payment method
curl "https://partial.ly/api/payment_method/36afc659-f03d-485b-a850-65871fa759a7" \
-H "Authorization: Bearer your_api_key" \
-X DELETE
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_method/36afc659-f03d-485b-a850-65871fa759a7',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'DELETE'
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"message": "Payment method deleted"
}
Deletes a payment method. Payment methods which are attached to open payment plans may not be deleted.
DELETE /payment_method/:id
replace :id with the id of the payment method to delete
Payment Plans
Create a new payment plan
curl "https://partial.ly/api/payment_plan" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
--data '{"amount": "1000", "customer_id": "452cc42f-d999-4c0f-998b-325c4e0e8f57", "offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
amount: 1000,
customer: {
email: 'aaa@y.co',
first_name: 'Testing',
last_name: 'Person'
},
offer_id: '60aed439-473f-48e0-80ef-3a8627dd243a'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"payment_schedule": {
"term_units": "months",
"term": 3,
"starts_date": null,
"starts_auto": true,
"repay_by_date": "2019-02-28",
"payment_amount": 256.25,
"num_payments": 3,
"inserted_at": "2018-11-28T17:20:46.753612",
"id": "8e2db276-7b45-4f1b-b479-0c25544d90c2",
"frequency_units": "months",
"frequency": 1,
"down_payment_amount": 256.25,
"description": null,
"contract_signed_date": null,
"contract_signature": null,
"contract_body": "By submitting your order and authorizing the charges on your card, you are legally bound to...",
"balance": 768.75,
"auto_process": true,
"amount": 1025
},
"payment_plan": {
"user_agent": null,
"subtotal": 1000,
"status": "checkout",
"number": null,
"meta": null,
"merchant_notes": null,
"ip_address": null,
"integration_id": null,
"integration": null,
"inserted_at": "2018-11-28T17:20:46.711165",
"id": "2ab17c1a-860d-4575-be11-dcd5bbab467d",
"customer_id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"customer": {
"timezone": "America/New_York",
"shipto_state": null,
"shipto_postal_code": null,
"shipto_name": null,
"shipto_country": "US",
"shipto_city": null,
"shipto_address2": null,
"shipto_address": null,
"phone": null,
"last_name": "Person",
"inserted_at": "2018-11-28T16:57:42.923471",
"id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"first_name": "Testing",
"email": "aaa@y.co"
},
"currency": "USD",
"amount_paid": 0,
"amount": 1025
},
"line_items": [
{
"quantity": 1,
"meta": null,
"inserted_at": "2018-11-28T17:20:46.766599",
"id": "f345d9da-b67f-4056-8224-f7d9599f9439",
"dynamic_type": "generic",
"dynamic": true,
"description": "processing fee",
"amount": 25
}
],
"installments": [
{
"scheduled": "2018-12-28T17:20:46.752714Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 256.25
},
{
"scheduled": "2019-01-28T17:20:46.752714Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 256.25
},
{
"scheduled": "2019-02-28T17:20:46.752714Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 256.25
}
]
}
Creates a new payment plan in checkout status. The payment schedule can automatically be created from an offer by sending an offer_id parameter, otherwise a payment_schedule can be specified. Likewise, either a customer_id for an existing customer can be specified, or a customer object can be sent and a new customer will be created, or the existing one attached. To open the payment plan, use the open method after it has been created.
A payment schedule will also be created and associated with the payment plan. The scheduled installments will also be generated and returned, but they will not be stored in the database until the payment plan is opened.
HTTP Request
POST /payment_plan
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
amount | decimal | yes | total amount of the payment plan |
customer_id | string | no | id of customer to associate with, required if customer not set |
customer | object | no | customer object to associate with, required if customer_id not set |
offer_id | string | no | id of offer to use to generate payment schedule, required if payment_schedule not set |
payment_schedule | object | no | payment schedule parameters, required if offer_id not set |
meta | object | no | any custom meta data. May also set line_items key to an array of line_items (see below) |
currency | string | no | 3 letter currency code. Default to USD |
ip_address | string | no | ip address of customer |
user_agent | string | no | user agent of customer |
shipto_name | string | no | shipping address name |
shipto_address | string | no | street address |
shipto_address2 | string | no | street address line 2 |
shipto_city | string | no | city |
shipto_state | string | no | 2 letter state/region/province code |
shipto_postal_code | string | no | zip/postal code |
shipto_country | string | no | 2 letter country abbreviation |
integration | string | no | third party integration to send payment plan to. shopify, woocommerce, bigcommerce, opencart, or prestashop |
status | string | no | checkout or pending. default is checkout |
send_plan_request | string | no | set to true to send a plan request email to customer to complete checkout. plan must be in pending status |
line_items
Parameter | Type | Required | Description |
---|---|---|---|
name | string | yes | description of the line item |
price | decimal | yes | unit price of the line item |
quantity | integer | yes | quantity |
image | string | no | URL for an image to display in Partial.ly |
weight | decimal | no | weight of the item |
weight_units | string | no | lb, g, kg, oz |
meta | object | no | additional meta data for line item. For Shopify integrations, meta.product_id and meta.variant_id must be set |
Open a payment plan
curl "https://partial.ly/api/payment_plan/open/ef2b5088-10cc-4246-914d-1f2de7a4075c" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X PUT \
--data '{"payment_schedule": {"contract_signature": "Customer Signature"}, "payment_method": {"type": "card", "token_id": "tok_ch"}}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan/open/ef2b5088-10cc-4246-914d-1f2de7a4075c',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
payment_schedule: {
contract_signature: 'Customer Signature'
},
payment_method: {
type: 'card',
token_id: 'tok_ch'
}
}
};
request(options, function (error, response, payment_plan) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"user_agent": null,
"subtotal": 6981,
"status": "open",
"number": 142,
"meta": {
"quickbooks_invoice_number": "1045",
"description": "Payment Plan for invoice 1045"
},
"merchant_notes": null,
"ip_address": null,
"integration_id": "167",
"integration": "quickbooks",
"inserted_at": "2018-11-05T22:19:33.441694",
"id": "ef2b5088-10cc-4246-914d-1f2de7a4075c",
"customer_id": "b4b15b3b-281a-41be-9690-e7f51666b8ef",
"currency": "USD",
"amount_paid": 30,
"amount": 7330.05
}
Opens a payment plan by signing the customer contract, attaching a payment method (new or existing), and processing the down payment if there is one. Only payment plans in checkout or pending status can be opened.
In case the supplied payment method requires 3d secure authentication (required for Strong Customer Authentication), the resulting payment plan will have status "requires_action" and will contain the "redirect_url" key. In this scenario, you should redirect the user to the "redirect_url" to authorize the payment, after which point they will be redirected back to the "return_url" you provide.
HTTP request
PUT /payment_plan/open/:id
replace :id with the id of the payment plan to open
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
payment_schedule.contract_signature | string | yes | customer's signature |
payment_method.id | string | no | existing payment method id |
payment_method.type | string | no | "card", required if payment_method.id not sent |
payment_method.token_id | string | no | see Payment Methods for details on creating new payment methods |
return_url | string | no | your URL to redirect user to after 3d secure authentication |
Cancel a payment plan
curl "https://partial.ly/api/payment_plan/cancel/ef2b5088-10cc-4246-914d-1f2de7a4075c" \
-H "Authorization: Bearer your_api_key" \
-X PUT
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan/cancel/ef2b5088-10cc-4246-914d-1f2de7a4075c',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT'
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"message": "PaymentPlan canceled"
}
Cancels a payment plan. Only payment plans in open or pending status may be canceled
HTTP Request
PUT /payment_plan/cancel/:id
replace :id with the id of the payment plan to cancel
Parameter | Type | Required | Description |
---|---|---|---|
cancel_shopify | boolean | no | if this payment plan is for a Shopify order, also cancel the Shopify order |
cancel_shopify_restock | boolean | no | if this payment plan is for a Shopify order, also restock the items from the order |
Update a payment plan
curl "https://partial.ly/api/payment_plan/cancel/8f999efe-5798-4b51-a6c5-d21b0d04124b" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X PUT \
-- data '{"merchant_notes": "Customer is very happy"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan/8f999efe-5798-4b51-a6c5-d21b0d04124b',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
merchant_notes: 'Customer is very happy'
}
};
request(options, function (error, response, plan) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"user_agent": null,
"subtotal": 1000,
"status": "open",
"number": 140,
"meta": {
"items": [
{
"quantity": 1,
"price": 900,
"name": "Widget",
"id": "widget-id"
},
{
"quantity": 2,
"price": 50,
"name": "Small product",
"id": "prod-sm"
}
],
"description": "Sample api plan"
},
"merchant_notes": "Customer is very happy",
"ip_address": null,
"integration_id": null,
"integration": null,
"inserted_at": "2018-11-28T17:13:14.181300",
"id": "8f999efe-5798-4b51-a6c5-d21b0d04124b",
"customer_id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"currency": "USD",
"amount_paid": 256.25,
"amount": 1025
}
Updates an existing payment plan
HTTP Request
PUT /payment_plan/:id
replace :id with the id of the plan to update
Parameters
only the following properties may be updated
Parameter | Type | Description |
---|---|---|
merchant_notes | string | general notes, not visible to customer |
payment_method_id | string | id of a payment method to use when processing payments for this plan |
shipto_name | string | |
shipto_address | string | |
shipto_address2 | string | |
shipto_city | string | |
shipto_state | string | |
shipto_postal_code | string | |
shipto_country | string | |
integration | string | third party service to integrate plan with, for example "shopify" |
integration_id | string | third party service id, for example shopify order id |
Retrieve a payment plan
curl "https://partial.ly/api/payment_plan/cancel/8f999efe-5798-4b51-a6c5-d21b0d04124b" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan/8f999efe-5798-4b51-a6c5-d21b0d04124b',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'GET'
};
request(options, function (error, response, plan) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"refunds": [
{
"status": "succeeded",
"reason": "requested_by_customer",
"processor_id": "re_1DbaweEs15StTpSviCrp112t",
"processor": "stripe",
"notes": "discount",
"inserted_at": "2018-11-28T21:51:46.423002",
"id": "a0990737-9234-44fc-857b-eac7b4ef3cbf",
"failure_reason": null,
"failure_merchant_transfer_id": null,
"amount": 5.99
}
],
"payments": [
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbXklEs15StTpSvJfo02FRM",
"processor_destination_id": "py_E3f42E5m2H1p8b",
"processor": "stripe",
"payment_plan_id": "8f999efe-5798-4b51-a6c5-d21b0d04124b",
"paid_at": "2018-11-28T18:27:16",
"message": null,
"inserted_at": "2018-11-28T18:27:16.896811",
"id": "2d1d0234-87c4-4184-a49f-02f4c0c30abe",
"currency": "USD",
"amount": 256.25
},
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbaigEs15StTpSvhzmfGjSA",
"processor_destination_id": "py_E3i82Rh38K8Wg7",
"processor": "stripe",
"payment_plan_id": "8f999efe-5798-4b51-a6c5-d21b0d04124b",
"paid_at": "2018-11-28T21:37:21",
"message": null,
"inserted_at": "2018-11-28T21:37:21.296658",
"id": "291221ab-b0a2-41dc-909b-1d1793bd23d8",
"currency": "USD",
"amount": 256.25
}
],
"payment_schedule": {
"term_units": "months",
"term": 3,
"starts_date": null,
"starts_auto": true,
"repay_by_date": "2019-02-28",
"payment_amount": 256.25,
"num_payments": 3,
"inserted_at": "2018-11-28T17:13:14.235119",
"id": "1f5d9716-a041-47ef-8c57-86af22efa31c",
"frequency_units": "months",
"frequency": 1,
"down_payment_amount": 256.25,
"description": null,
"contract_signed_date": "2018-11-28T18:27:17",
"contract_signature": "Customer Signature",
"contract_body": "By submitting your order and authorizing...",
"balance": 768.75,
"auto_process": true,
"amount": 1025
},
"payment_plan": {
"user_agent": null,
"subtotal": 1000,
"status": "open",
"number": 140,
"offer_id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"meta": {
"items": [
{
"quantity": 1,
"price": 900,
"name": "Widget",
"id": "widget-id"
},
{
"quantity": 2,
"price": 50,
"name": "Small product",
"id": "prod-sm"
}
],
"description": "Sample api plan"
},
"merchant_notes": "Customer is very happy",
"ip_address": null,
"integration_id": null,
"integration": null,
"inserted_at": "2018-11-28T17:13:14.181300",
"id": "8f999efe-5798-4b51-a6c5-d21b0d04124b",
"customer_id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"customer": {
"timezone": "America/New_York",
"shipto_state": "FL",
"shipto_postal_code": "33601",
"shipto_name": "Sample Customer",
"shipto_country": "US",
"shipto_city": "Tampa",
"shipto_address2": null,
"shipto_address": "123 N. Tampa St.",
"phone": "81325551212",
"last_name": "Customer",
"inserted_at": "2015-09-11T05:54:27.000000",
"id": "6d30d3c8-d024-45cc-9c3f-356fc8aee23d",
"first_name": "Sample",
"email": "sample.customer@gmail.com"
},
"currency": "USD",
"balance": 518.49,
"amount_refunded": 5.99,
"amount_pending": 0,
"amount_paid": 512.5,
"amount_disputed": 0,
"amount": 1025
},
"line_items": [
{
"quantity": 1,
"meta": {
"quantity": 1,
"price": 900,
"name": "Widget",
"id": "widget-id"
},
"inserted_at": "2018-11-28T17:13:14.262856",
"id": "0da61119-ca96-410b-a1cb-ca059f2f8395",
"dynamic_type": "generic",
"dynamic": false,
"description": "Widget",
"amount": 900
},
{
"quantity": 2,
"meta": {
"quantity": 2,
"price": 50,
"name": "Small product",
"id": "prod-sm"
},
"inserted_at": "2018-11-28T17:13:14.264749",
"id": "16aa3a67-5efb-42c4-8b3b-e59940a7423f",
"dynamic_type": "generic",
"dynamic": false,
"description": "Small product",
"amount": 50
},
{
"quantity": 1,
"meta": null,
"inserted_at": "2018-11-28T17:13:14.249186",
"id": "1b7c8912-ee07-4731-a301-503160dc3365",
"dynamic_type": "generic",
"dynamic": true,
"description": "processing fee",
"amount": 25
}
],
"installments": [
{
"scheduled": "2018-12-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.911366",
"id": "6a85b229-69e6-4850-8309-edf7bfc3cec1",
"amount": 256.25
},
{
"scheduled": "2019-01-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.927898",
"id": "0caa4d95-2252-4855-8f78-a0ecf426bf09",
"amount": 256.25
},
{
"scheduled": "2019-02-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.931100",
"id": "7a6c0aba-1b55-43dc-8367-d7fada4f1bfa",
"amount": 256.25
}
],
"disputes": []
}
Retrieves an existing payment plan
HTTP Request
GET /payment_plan/:id
replace :id with the id of the plan
List all plans
curl "https://partial.ly/api/payment_plan?date=2018-11-28" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan?date=2018-11-28',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"total_pages": 1,
"total_entries": 1,
"payment_plans": [
{
"user_agent": null,
"subtotal": 1000,
"status": "open",
"number": 140,
"offer_id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"meta": {
"items": [
{
"quantity": 1,
"price": 900,
"name": "Widget",
"id": "widget-id"
},
{
"quantity": 2,
"price": 50,
"name": "Small product",
"id": "prod-sm"
}
],
"description": "Sample api plan"
},
"merchant_notes": "Customer is very happy",
"ip_address": null,
"integration_id": null,
"integration": null,
"inserted_at": "2018-11-28T17:13:14.181300",
"id": "8f999efe-5798-4b51-a6c5-d21b0d04124b",
"customer_id": "e3cbf1dc-0c11-483f-b604-d44fd93aac90",
"customer": {
"timezone": "America/New_York",
"shipto_state": "FL",
"shipto_postal_code": "33601",
"shipto_name": "Sample Customer",
"shipto_country": "US",
"shipto_city": "Tampa",
"shipto_address2": null,
"shipto_address": "123 N. Tampa St.",
"phone": "81325551212",
"last_name": "Customer",
"inserted_at": "2015-09-11T05:54:27.000000",
"id": "6d30d3c8-d024-45cc-9c3f-356fc8aee23d",
"first_name": "Sample",
"email": "sample.customer@gmail.com"
},
"currency": "USD",
"amount_paid": 256.25,
"amount": 1025,
"line_items": [
{
"quantity": 1,
"meta": {
"quantity": 1,
"price": 900,
"name": "Widget",
"id": "widget-id"
},
"inserted_at": "2018-11-28T17:13:14.262856",
"id": "0da61119-ca96-410b-a1cb-ca059f2f8395",
"dynamic_type": "generic",
"dynamic": false,
"description": "Widget",
"amount": 900
}
],
"payment_schedule": {
"term_units": "months",
"term": 3,
"starts_date": null,
"starts_auto": true,
"repay_by_date": "2019-02-28",
"payment_amount": 256.25,
"num_payments": 3,
"inserted_at": "2018-11-28T17:13:14.235119",
"id": "1f5d9716-a041-47ef-8c57-86af22efa31c",
"frequency_units": "months",
"frequency": 1,
"down_payment_amount": 256.25,
"description": null,
"contract_signed_date": "2018-11-28T18:27:17",
"contract_signature": "Customer Signature",
"contract_body": "By submitting your order and authorizing...",
"balance": 768.75,
"auto_process": true,
"amount": 1025,
"installments": [
{
"scheduled": "2018-12-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.911366",
"id": "6a85b229-69e6-4850-8309-edf7bfc3cec1",
"amount": 256.25
},
{
"scheduled": "2019-01-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.927898",
"id": "0caa4d95-2252-4855-8f78-a0ecf426bf09",
"amount": 256.25
},
{
"scheduled": "2019-02-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.931100",
"id": "7a6c0aba-1b55-43dc-8367-d7fada4f1bfa",
"amount": 256.25
}
]
}
}
],
"page_size": 10,
"page_number": 1
}
Lists all payment plans, with the optional filters listed below
HTTP Request
GET /payment_plan
Parameters
Parameter | Type | Description |
---|---|---|
status | string | plan status. checkout, pending, open, paid, canceled, or defaulted |
currency | string | 3 letter currency code |
date | date | plan created date. YYYY-MM-DD |
dateRange | string | plans created in a range of dates separated by the | character. Ex. use "2018-01-01|2018-02-01" |
customer | string | plans with the given customer id |
Send plan request email
curl "https://partial.ly/api/payment_plan/send_plan_request/8f999efe-5798-4b51-a6c5-d21b0d04124b" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
--data ''
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_plan/send_plan_request/8f999efe-5798-4b51-a6c5-d21b0d04124b',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"message": "Plan request email sent"
}
Send an emailed request to the customer to open the payment plan via Partially checkout. The payment plan must be in pending, canceled, defaulted, or paused status, and the merchant account must have an active Stripe account connected.
You can optionally choose to also update the payment plan status to pending, which will also allow the customer to open the payment plan from their portal.
HTTP Request
POST /payment_plan/send_plan_request/:id
Parameter | Type | Description |
---|---|---|
update_status | string | can only be updated to "pending" |
Line Items
Create a line item
curl "https://partial.ly/api/line_item" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
-- data '{"payment_plan_id": "4a2da2b5-ccbc-4631-93ad-ea30da49a412", "amount": 5.99, "description": "adjustment"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/line_item',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
payment_plan_id: '4a2da2b5-ccbc-4631-93ad-ea30da49a412',
amount: 5.99,
description: 'adjustment'
}
};
request(options, function (error, response, payment) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"amount": 5.99,
"description": "adjustment",
"dynamic": false,
"dynamic_type": "generic",
"id": "2faa91f1-7b01-4111-9af9-967e70c272e8",
"inserted_at": "2019-02-22T15:24:23",
"meta": null,
"quantity": 1
}
Adds a new line item to a payment plan. This can only be done on payment plans not in the open or paid statuses.
Adding a new line item to a payment plan will automatically adjust the payment plan total.
Line item amounts can be negative to decrease a payment plan amount, for example to give a customer a discount.
HTTP Request
POST /line_item
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
payment_plan_id | string | yes | id of the plan to make a payment on |
amount | decimal | yes | The unit price of the line item. May be positive or negative |
description | string | yes | the line item's description |
quantity | integer | no | Th quantity of the line item. Defaults to 1 if not specified |
image | string | no | URL to an image for the line item |
weight | decimal | no | weight of the line item |
weight_units | string | no | g, kg, oz, or lb. defaults to lb |
meta | object | no | additional meta information about the line item |
integration | string | no | third party service to send line item to, ex. "shopify" or "bigcommerce" |
integration_id | string | no | line item id for third party service |
Delete a line item
curl "https://partial.ly/api/line_item/a9bec449-da6e-4dea-ad4a-a716aa90d40c" \
-H "Authorization: Bearer your_api_key" \
-X DELETE
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/line_item/a9bec449-da6e-4dea-ad4a-a716aa90d40c',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'DELETE'
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"message": "LineItem deleted"
}
Deletes a line item. This can only be done on payment plans not in the open or paid statuses.
Deleting a line item will automatically decrease the associated payment plan's total amount.
DELETE /line_item/:id
replace :id with the id of the line item to delete
Payments
Payments can have a paid, pending, or failed status. Payments made with a bank account payment method will be pending for up to 5 business days while we wait for them to be confirmed.
Create a payment
Pay the entire balance
curl "https://partial.ly/api/payment/create" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
-- data '{"payment_plan_id": "1597c18b-ffd4-4641-b2ca-78cccd3547f5", "amount": 241.87}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment/create',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
payment_plan_id: '1597c18b-ffd4-4641-b2ca-78cccd3547f5',
amount: 241.87
}
};
request(options, function (error, response, payment) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbYxLEs15StTpSvFVKDzPIx",
"processor_destination_id": null,
"processor": "stripe",
"payment_plan_id": "1597c18b-ffd4-4641-b2ca-78cccd3547f5",
"paid_at": "2018-11-28T19:44:21",
"message": null,
"inserted_at": "2018-11-28T19:44:21.874251",
"id": "2c84ae4a-962c-479b-bed4-4696ef25099d",
"currency": "USD",
"amount": 241.87,
"fee": 12.39,
"customer_fee_amount": 0.0
}
Making a payment for an amount less than the balance
curl "https://partial.ly/api/payment/create" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
-- data '{"payment_plan_id": "027bb022-40b4-4763-945c-baddc612cbbb", "amount": 5.99}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment/create',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
payment_plan_id: '027bb022-40b4-4763-945c-baddc612cbbb',
amount: 5.99
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"payment_schedule": {
"term_units": "months",
"term": 4,
"starts_date": null,
"starts_auto": true,
"repay_by_date": "2019-02-25",
"payment_amount": 116.91,
"num_payments": 8,
"inserted_at": null,
"id": null,
"frequency_units": "weeks",
"frequency": 2,
"down_payment_amount": 5.99,
"description": null,
"contract_signed_date": null,
"contract_signature": null,
"contract_body": "By submitting your order and authorizing the charges on your card, you are legally bound to the following terms:\r\n\r\nLayaway Agreement\r\n\r\nThis Layaway Agreement (\"Agreement\") is made...",
"balance": 935.26,
"auto_process": true,
"amount": 941.25
},
"installments": [
{
"scheduled": "2018-11-24T00:00:00",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2018-12-06T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2018-12-20T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2019-01-03T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2019-01-17T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2019-01-31T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2019-02-14T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.91
},
{
"scheduled": "2019-02-28T23:26:47.492554",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 116.89
}
]
}
Make a payment on a payment plan for an arbitrary amount.
If the payment is for the entire remaining balance of the plan, it will be processed immediately.
If the payment is for less than the balance, a new payment schedule will need to be generated and signed by the customer. This step does not actually process the payment, but instead returns the adjusted payment schedule, installments, and contract for the customer to sign. Which is completed in the Confirm a payment step
In case the supplied payment method requires 3d secure authentication (required for Strong Customer Authentication), the resulting payment will have status "requires_action" and will contain the "redirect_url" key. In this scenario, you should redirect the user to the "redirect_url" to authorize the payment, after which point they will be redirected back to the "return_url" you provide.
HTTP Request
POST /payment/create
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
payment_plan_id | string | yes | id of the plan to make a payment on |
amount | decimal | yes | amount of the payment |
return_url | string | no | your URL to redirect user to after 3d secure authentication |
Confirm a payment
curl "https://partial.ly/api/payment/confirm" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
-- data '{"payment_plan_id": "027bb022-40b4-4763-945c-baddc612cbbb", "amount": 5.99, "contract_signature": "Customer signature"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment/confirm',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
payment_plan_id: '027bb022-40b4-4763-945c-baddc612cbbb',
amount: 5.99,
contract_signature: 'Customer signature'
}
};
request(options, function (error, response, payment) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbZ8sEs15StTpSvDs76XSVh",
"processor_destination_id": null,
"processor": "stripe",
"payment_plan_id": "027bb022-40b4-4763-945c-baddc612cbbb",
"paid_at": "2018-11-28T19:56:17",
"message": null,
"inserted_at": "2018-11-28T19:56:17.050690",
"id": "e632f099-4c2b-4de9-b632-3966539be2d5",
"currency": "USD",
"amount": 5.99,
"fee": 0.6,
"customer_fee_amount": 0.0
}
step 2 in making a payment on a payment plan, adjusting future installments signs the updated payment schedule contract from the create step and processes the payment
In case the supplied payment method requires 3d secure authentication, the resulting payment will have status "requires_action" and will contain the "redirect_url" key. In this scenario, you should redirect the user to the "redirect_url" to authorize the payment, after which point they will be redirected back to the "return_url" you provide.
HTTP Request
POST /payment/confirm
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
payment_plan_id | string | yes | id of the plan to make a payment on |
amount | decimal | yes | amount of the payment |
contract_signature | string | yes | the customer's signature for the new payment schedule contract |
return_url | string | no | your URL to redirect user to after 3d secure authentication |
List all payments
curl "https://partial.ly/api/payment" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"total_pages": 24,
"total_entries": 234,
"payments": [
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbZ8sEs15StTpSvDs76XSVh",
"processor_destination_id": "py_E3gVHD2z4rtVl9",
"processor": "stripe",
"payment_plan_id": "027bb022-40b4-4763-945c-baddc612cbbb",
"paid_at": "2018-11-28T19:56:17",
"message": null,
"inserted_at": "2018-11-28T19:56:17.050690",
"id": "e632f099-4c2b-4de9-b632-3966539be2d5",
"currency": "USD",
"amount": 5.99,
"fee": 0.6,
"customer_fee_amount": 0.0
},
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbYxLEs15StTpSvFVKDzPIx",
"processor_destination_id": "py_E3gK6PBRACnhi5",
"processor": "stripe",
"payment_plan_id": "1597c18b-ffd4-4641-b2ca-78cccd3547f5",
"paid_at": "2018-11-28T19:44:21",
"message": null,
"inserted_at": "2018-11-28T19:44:21.874251",
"id": "2c84ae4a-962c-479b-bed4-4696ef25099d",
"currency": "USD",
"amount": 241.87,
"fee": 12.39,
"customer_fee_amount": 0.0
},
// ...
],
"page_size": 10,
"page_number": 1
}
Lists all payments, with the optional filters listed below
HTTP Request
GET /payment
Parameters
Parameter | Type | Description |
---|---|---|
payment_plan_id | string | payments only for the given plan |
q | string | a stripe payment id |
status | string | payment status. paid, pending, or failed |
currency | string | 3 letter currency code |
date | date | payment created date. YYYY-MM-DD |
dateRange | string | payments created in a range of dates separated by the | character. Ex. use "2018-01-01|2018-02-01" |
customer | string | payments with the given customer id |
Retrieve a payment
curl "https://partial.ly/api/payment/b1873714-bb39-4b07-ac54-10501a60c98a" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment/b1873714-bb39-4b07-ac54-10501a60c98a',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"amount": 52.5,
"charge_type": "direct",
"currency": "USD",
"customer_fee_amount": 0.0,
"fee": 1.05,
"id": "b1873714-bb39-4b07-ac54-10501a60c98a",
"inserted_at": "2024-06-11T14:39:20Z",
"message": null,
"paid_at": "2024-06-11T14:41:28Z",
"payment_method": {
"id": "ee067511-2028-40e0-855d-50420dda6fcb",
"inserted_at": "2024-02-17T21:32:51Z",
"integration_details": {
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": "pass",
"cvc_check": "pass"
},
"country": "US",
"display_brand": "visa",
"exp_month": 11,
"exp_year": 2026,
"fingerprint": "nSxT4fpABgc4m4xm",
"funding": "credit",
"generated_from": null,
"last4": "4242",
"networks": {
"available": [
"visa"
],
"preferred": null
},
"three_d_secure_usage": {
"supported": true
},
"wallet": null
},
"type": "card"
},
"payment_plan_id": "5f179a30-264f-41d2-84bf-f62f2e1870d4",
"processor": "stripe",
"processor_destination_id": null,
"processor_id": "pi_2PQVr02J8rf5dfhT1nbObkMv",
"redirect_url": null,
"retry_number": 0,
"status": "paid",
"type": "down_merchant",
"user": {
"email": "customer@google.com",
"id": "b2cb785c-6230-414e-ab43-311f8baf97ed",
"inserted_at": "2017-09-06T04:46:42Z"
}
}
Get a single payment by id
HTTP Request
GET /payment/:id
replace :id with the id of the payment
Payment Schedules
A payment schedule represents the terms and schedule for a payment plan. A payment plan can have multiple payment schedules if the customer makes a one off payment that adjusts the current payment schedule. A payment plan only has one active payment schedule
Update a payment schedule
curl "https://partial.ly/api/payment_schedule/64823d54-9d47-4cd9-9db0-b293294ca341" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X PUT \
-- data '{"term": 3}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_schedule/64823d54-9d47-4cd9-9db0-b293294ca341',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
term: 3
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"payment_schedule": {
"term_units": "months",
"term": 3,
"starts_date": null,
"starts_auto": true,
"repay_by_date": "2019-03-21",
"payment_amount": 256.25,
"num_payments": 3,
"inserted_at": "2018-12-21T22:01:18.623163",
"id": "64823d54-9d47-4cd9-9db0-b293294ca341",
"frequency_units": "months",
"frequency": 1,
"down_payment_amount": 256.25,
"description": null,
"contract_signed_date": null,
"contract_signature": null,
"contract_body": "By submitting your order and authorizing the charges on your card...",
"balance": 768.75,
"auto_process": true,
"amount": 1025
},
"installments": [
{
"scheduled": "2019-01-21T22:10:14.518787Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 256.25
},
{
"scheduled": "2019-02-21T22:10:14.518787Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 256.25
},
{
"scheduled": "2019-03-21T22:10:14.518787Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 256.25
}
]
}
Can only be done for active schedules of plans in checkout status. If customer flexibility enabled, updates either the term, frequency, or down payment, and reevaluates the payment schedule and installments.
HTTP request
PUT /payment_schedule/:id
Parameters
Parameter | Description |
---|---|
down_payment_amount | amount of down payment |
term | term or length of payment plan |
frequency | frequency of payments |
Get contract pdf
Gets the binary pdf of the signed contract
HTTP Request
GET /payment_schedule/contract_pdf/:id
Create a new payment schedule
curl "https://partial.ly/api/payment_schedule" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
-- data '{"payment_plan_id": "71f98dc3-6d89-4e56-b14b-c0e27dac0158", "amount": 188.88, "term": 1, "term_units": "months", "frequency": 1, "frequency_units": "weeks"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/payment_schedule',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
payment_plan_id: '71f98dc3-6d89-4e56-b14b-c0e27dac0158',
amount: 188.88,
term: 1,
term_units: 'months',
frequency: 1,
frequency_units: 'weeks'
}
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"payment_schedule": {
"term_units": "months",
"term": 1,
"starts_date": null,
"starts_auto": true,
"repay_by_date": "2018-12-26",
"payment_amount": 47.21,
"num_payments": 4,
"inserted_at": "2018-11-28T20:49:46.792362",
"id": "0ec6f76b-8675-449f-9414-ccf44cc9c148",
"frequency_units": "weeks",
"frequency": 1,
"down_payment_amount": 0,
"description": null,
"contract_signed_date": null,
"contract_signature": null,
"contract_body": null,
"balance": 188.8,
"auto_process": true,
"amount": 188.8
},
"installments": [
{
"scheduled": "2018-12-05T20:49:46.791705Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 47.21
},
{
"scheduled": "2018-12-12T20:49:46.791705Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 47.21
},
{
"scheduled": "2018-12-19T20:49:46.791705Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 47.21
},
{
"scheduled": "2018-12-26T20:49:46.791705Z",
"retry_number": 0,
"inserted_at": null,
"id": null,
"amount": 47.17
}
]
}
Creates a new PaymentSchedule for a PaymentPlan, making it the active schedule and deactivating all others. Can't be done for open or paid status plans.
HTTP Request
POST /payment_schedule
Parameters
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
payment_plan_id | string | yes | id of the payment plan | |
amount | decimal | yes | amount of the payment schedule | |
auto_process | boolean | no | true | true to automatically schedule future payments, false for manual payments |
description | string | no | for manual payment schedules (auto_process=false), a description of how the payments will be processed | |
currency | string | no | currency in merchant settings | The currency to use for payment plans |
down_payment | decimal | no | 0 | the amount or percent of down payment required, depending on down_payment_type |
down_payment_type | string | no | percent | percent or amount |
down_payment_flexible | boolean | no | false | allow the customer to choose their down payment within a specified range |
down_payment_min | decimal | no | min down payment percent or amount | |
down_payment_max | decimal | no | max down payment percent or amount | |
term | integer | no | 3 | the length of the payment plan |
term_units | string | no | months | type of units for the payment plan term. weeks, months, years, payments (a fixed number of payments), or date (pay by a date) |
term_date | date | no | final payment date when using term_units=date | |
term_flexible | boolean | no | false | allow the customer to choose their term within the specified range |
term_min | integer | no | the minimum term the customer can choose | |
term_max | integer | no | the maximum term the customer can choose | |
frequency | integer | no | 1 | the frequency of scheduled payments |
frequency_units | string | no | months | type of units for the payment plan term. days, weeks, months, days_month (for specific days of the month) |
frequency_days | array | no | array of specific days of the month for payments, for example [1, 15] for payments on the 1st and 15th of the month | |
frequency_flexible | boolean | no | false | allow the customer to choose their payment frequency within the specified range |
frequency_min | integer | no | the minimum payment frequency the customer can choose | |
frequency_max | integer | no | the maximum payment frequency the customer can choose | |
starts_auto | boolean | no | true | whether or not to automatically schedule the first installment relative to today's date |
starts_date | string | no | if starts_auto is false, the specified date will be the date of the first scheduled installment. YYYY-mm-dd |
Installments
Installments represent a payment to be processed in the future, as scheduled by a payment plan's payment schedule.
Pay scheduled installment
curl "https://partial.ly/api/installment/pay/6a85b229-69e6-4850-8309-edf7bfc3cec1" \
-H "Authorization: Bearer your_api_key" \
-X PUT
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/installment/pay/6a85b229-69e6-4850-8309-edf7bfc3cec1',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT'
};
request(options, function (error, response, payment) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"status": "paid",
"retry_number": 0,
"processor_id": "ch_1DbaigEs15StTpSvhzmfGjSA",
"processor_destination_id": null,
"processor": "stripe",
"payment_plan_id": "8f999efe-5798-4b51-a6c5-d21b0d04124b",
"paid_at": "2018-11-28T21:37:21",
"message": null,
"inserted_at": "2018-11-28T21:37:21.296658",
"id": "291221ab-b0a2-41dc-909b-1d1793bd23d8",
"currency": "USD",
"amount": 256.25
}
Pays a scheduled installment. Must be scheduled in the future and not already paid. If successful will return the payment.
In case the supplied payment method requires 3d secure authentication, the resulting payment will have status "requires_action" and will contain the "redirect_url" key. In this scenario, you should redirect the user to the "redirect_url" to authorize the payment, after which point they will be redirected back to the "return_url" you provide.
HTTP request
PUT /installment/pay/:id
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
return_url | string | no | your URL to redirect user to after 3d secure authentication |
List installments
curl "https://partial.ly/api/installment?payment_schedule_id=1f5d9716-a041-47ef-8c57-86af22efa31c" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/installment?payment_schedule_id=1f5d9716-a041-47ef-8c57-86af22efa31c',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, installments) {
// asynchronous callback function
});
Returns an array of installments as follows
[
{
"scheduled": "2018-12-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.911366",
"id": "6a85b229-69e6-4850-8309-edf7bfc3cec1",
"amount": 256.25
},
{
"scheduled": "2019-01-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.927898",
"id": "0caa4d95-2252-4855-8f78-a0ecf426bf09",
"amount": 256.25
},
{
"scheduled": "2019-02-28T18:27:16.910618",
"retry_number": 0,
"inserted_at": "2018-11-28T18:27:16.931100",
"id": "7a6c0aba-1b55-43dc-8367-d7fada4f1bfa",
"amount": 256.25
}
]
Gets all installments for the given payment_schedule_id. You can also list all upcoming installments for a customer by providing a customer_id parameter.
Refunds
Refund a payment
curl "https://partial.ly/api/refund" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
--data '{"payment_id": "2d1d0234-87c4-4184-a49f-02f4c0c30abe", "amount": 5.99, "notes": "discount"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/refund',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
payment_id: '2d1d0234-87c4-4184-a49f-02f4c0c30abe',
amount: 5.99,
notes: 'discount'
}
};
request(options, function (error, response, refund) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"status": "succeeded",
"reason": "requested_by_customer",
"processor_id": "re_1DbaweEs15StTpSviCrp112t",
"processor": "stripe",
"notes": "discount",
"inserted_at": "2018-11-28T21:51:46.423002",
"id": "a0990737-9234-44fc-857b-eac7b4ef3cbf",
"failure_reason": null,
"failure_merchant_transfer_id": null,
"amount": 5.99
}
Refunds the given amount of the payment. The refund amount must not exceed the amount of the payment or the amount not already refunded.
HTTP request
POST /refund
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
payment_id | string | yes | id of the payment to refund |
amount | decimal | yes | amount to refund |
notes | string | no |
List refunds
curl "https://partial.ly/api/refund" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/refund',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, refunds) {
// asynchronous callback function
});
Returns an array of refunds as follows
{
"total_pages": 1,
"total_entries": 5,
"refunds": [
{
"status": "succeeded",
"reason": "requested_by_customer",
"processor_id": "re_1DbaweEs15StTpSviCrp112t",
"processor": "stripe",
"notes": "discount",
"inserted_at": "2018-11-28T21:51:46.423002",
"id": "a0990737-9234-44fc-857b-eac7b4ef3cbf",
"failure_reason": null,
"failure_merchant_transfer_id": null,
"amount": 5.99
},
{
"status": "succeeded",
"reason": "requested_by_customer",
"processor_id": "re_1COApEEs15StTpSviNl0Utby",
"processor": "stripe",
"notes": null,
"inserted_at": "2018-05-04T20:48:22.062965",
"id": "dd9778b8-7576-40a2-912c-223fe8a1df29",
"failure_reason": null,
"failure_merchant_transfer_id": null,
"amount": 5
},
{
"status": "failed",
"reason": "requested_by_customer",
"processor_id": "re_1BTuvkEs15StTpSvSTTpommv",
"processor": "stripe",
"notes": null,
"inserted_at": "2017-11-30T16:30:34.631848",
"id": "aad5ba81-d73a-4a99-bd82-823e490b7d68",
"failure_reason": "customer_account_closed",
"failure_merchant_transfer_id": "tr_1BTv3SEs15StTpSvoFttIcYV",
"amount": 2
},
{
"status": "succeeded",
"reason": "requested_by_customer",
"processor_id": "re_1BR0AtEs15StTpSv4nRc0UZE",
"processor": "stripe",
"notes": "customer was furious. oh well",
"inserted_at": "2017-11-22T15:30:09.120225",
"id": "be123b2d-2d0d-4d58-abab-bff04382685c",
"failure_reason": null,
"failure_merchant_transfer_id": null,
"amount": 50
},
{
"status": "succeeded",
"reason": null,
"processor_id": "re_17FoZ1Es15StTpSvXcn4uLPp",
"processor": "stripe",
"notes": null,
"inserted_at": "2015-12-08T16:43:43.000000",
"id": "6e071d81-f030-41db-8511-6aa646f6dc75",
"failure_reason": null,
"failure_merchant_transfer_id": null,
"amount": 472.19
}
],
"page_size": 10,
"page_number": 1
}
Gets all refunds
HTTP request
GET /refund
Parameters
Parameter | Type | Description |
---|---|---|
reason | string | reason for the refund. requested_by_customer, duplicate, or fraudulent |
date | date | refund created date. YYYY-MM-DD |
dateRange | string | refunds created in a range of dates. Ex. use "2018-01-01 |
customer | string | refunds with the given customer id |
Disputes
List disputes
curl "https://partial.ly/api/dispute" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/dispute',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, disputes) {
// asynchronous callback function
});
Returns an array of disputes as follows
[
{
"payment_id": "3098916e-1eb1-4a02-83a2-99e32d6d606f",
"amount": 25.65,
"inserted_at": "2017-09-05T07:35:45.000000",
"status": "warning_needs_response",
"reason": "unrecognized"
}
]
Gets all disputes
HTTP request
GET /dispute
Parameters
Parameter | Type | Description |
---|---|---|
status | string | status of the dispute |
reason | string | reason for the dispute |
date | date | dispute created date. YYYY-MM-DD |
dateRange | string | disputes created in a range of dates. Ex. use "2018-01-01 |
customer | string | disputes with the given customer id |
Webhooks
Webhooks overview
// sample server for partial.ly webhooks with signature validation
const express = require('express');
const crypto = require('crypto');
const app = express();
const port = 3000;
// make sure to validate signature before parsing body
const apiKey = 'sample-key';
// Middleware to parse the body as raw buffer
app.use(express.raw({ type: '*/*' }));
// Middleware to validate Partially-Signature header
app.use((req, res, next) => {
const signature = req.headers['partially-signature'];
if (!signature) {
return res.status(401).send('No signature provided');
}
const hmac = crypto.createHmac('sha256', apiKey);
const computedSignature = hmac.update(req.body).digest('hex');
if (signature !== computedSignature) {
return res.status(401).send('Invalid signature');
}
// Parse raw body to JSON after signature validation
req.body = JSON.parse(req.body);
next();
});
app.post('/', (req, res) => {
console.log(`partial.ly event ${req.body.event}`);
res.send('ok');
});
app.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
});
With our webhook system, when key events are triggered in Partial.ly we will deliver the relevant data to any listeners you have configured to receive those events. This allows you to respond to events in real time, such as notifying support, integrating with other systems such as accounting, etc.
All events will be sent over HTTP and JSON encoded, with the following keys:
Key | Description |
---|---|
event | the event type, for example plan_opened |
id | the id of the event |
data | the data specific to the event |
To secure webhook delivery and guarantee events are sent by Partial.ly and unmodified, we will always include the HTTP header Partially-Signature with every webhook event delivered. The value of this header will be the sha-256 HMAC of the HTTP request body, using your API key as the secret key. You should calculate this value yourself and compare it to the value in the Partially-Signature header to guarantee the security and accuracy of events. Make sure to calculate using the request body before it's been parsed, as some programming languages may change the order of keys, which could change the value of the signature.
Your webhook listener should return an HTTP 200 status code response within 15 seconds, if not the request is considered failed. If a request fails, we will retry sending it after 1 hour. If there are 20 consecutive failed requests to resend a webhook, it will be automatically disabled.
Webhook listeners can be managed using the API, or through the webhook user interface in the merchant portal.
Create a webhook listener
curl "https://partial.ly/api/webhook" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X POST \
--data '{"url": "http://localhost:8888/hook"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/webhook',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'POST',
json: true,
body: {
url: 'http://localhost:8888/hook'
}
};
request(options, function (error, response, webhook) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"version": "2.0",
"url": "http://localhost:8888/hook",
"updated_at": "2018-11-28T22:22:06.355439",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"inserted_at": "2018-11-28T22:22:06.355432",
"id": "d5e43bed-041c-4ff4-b422-a401b10aad79",
"event": "*"
}
Creates a new webhook listener. Events that can be subscribed to are plan_opened, plan_paid, plan_defaulted, plan_canceled, payment_succeeded, payment_failed, refund_created, dispute_created, dispute_closed, and checkout_abandoned.
HTTP request
POST /webhook
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
url | string | yes | complete URL of the webhook, including https |
event | string | no | the event to subscribe to, or * for all events (default) |
List webhook listeners
curl "https://partial.ly/api/webhook" \
-H "Authorization: Bearer your_api_key"
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/webhook',
headers: {
Authorization: 'Bearer your_api_key'
}
};
request(options, function (error, response, hooks) {
// asynchronous callback function
});
Returns an array of webhooks as follows
[
{
"version": "2.0",
"url": "http://prestashop.local:8080/index.php?fc=module&module=partially&controller=notify&action=webhook",
"updated_at": "2018-03-08T15:34:35.207108",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"inserted_at": "2018-03-08T15:34:35.207102",
"id": "0aeece05-8e24-419b-a2ad-466a70de9b4b",
"event": "*"
}
]
Gets all webhook listeners
HTTP request
GET /webhook
Update a webhook listener
curl "https://partial.ly/api/webhook/d5e43bed-041c-4ff4-b422-a401b10aad79" \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-X PUT \
--data '{"url": "http://localhost:8888/hook"}'
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/webhook/d5e43bed-041c-4ff4-b422-a401b10aad79',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'PUT',
json: true,
body: {
url: 'http://localhost:8888/hook'
}
};
request(options, function (error, response, webhook) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"version": "2.0",
"url": "http://localhost:8888/hook",
"updated_at": "2018-11-28T22:22:06.355439",
"merchant_id": "60689b2d-d391-417e-9f59-7b65e3e50d8d",
"inserted_at": "2018-11-28T22:22:06.355432",
"id": "d5e43bed-041c-4ff4-b422-a401b10aad79",
"event": "*",
"active": true
}
Updates an existing webhook listener
HTTP request
PUT /webhook/:id
replace :id with the id of the webhook to update
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
url | string | no | complete URL of the webhook, including https |
event | string | no | the event to subscribe to, or * for all events (default) |
active | boolean | no | whether or not the webhook is active |
Delete a webhook listener
curl "https://partial.ly/api/webhook/a9bec449-da6e-4dea-ad4a-a716aa90d40c" \
-H "Authorization: Bearer your_api_key" \
-X DELETE
// examples use the request library
// https://github.com/request/request
var request = require('request');
var options = {
url: 'https://partial.ly/api/webhook/a9bec449-da6e-4dea-ad4a-a716aa90d40c',
headers: {
Authorization: 'Bearer your_api_key'
},
method: 'DELETE'
};
request(options, function (error, response, body) {
// asynchronous callback function
});
The above command returns JSON structured like this:
{
"message": "Webhook deleted"
}
deletes a webhook listener
DELETE /webhook/:id
replace :id with the id of the webhook to delete
Webhook events
These are the possible event types delivered via webhook, with examples for each.
plan_opened event
{
"event": "plan_opened",
"id": "test",
"data": {
"payment_plan": {
"amount": 96.78999999999999,
"amount_paid": 0.0,
"currency": "USD",
"customer": {
"email": "bob@fake.com",
"first_name": "Bob",
"id": "f4948b98-cef1-49a6-8a8b-3f196f45f917",
"inserted_at": "2017-09-27T14:20:50Z",
"last_name": "Fake",
"phone": null,
"shipto_address": "345 bayshore blvd",
"shipto_address2": null,
"shipto_city": "TAMPA",
"shipto_country": "US",
"shipto_name": "Bob Fake",
"shipto_postal_code": "33611",
"shipto_state": "FL",
"timezone": "America/New_York"
},
"customer_id": "f4948b98-cef1-49a6-8a8b-3f196f45f917",
"id": "cefab646-aa25-4c03-979a-e4c291288f97",
"inserted_at": "2022-05-02T16:04:48Z",
"integration": null,
"integration_id": null,
"ip_address": null,
"is_reopened": false,
"line_items": [],
"merchant_notes": null,
"meta": {
"description": ""
},
"number": 416,
"offer_id": null,
"payment_method_id": "8148229a-146c-4abe-8700-8fbe71707046",
"payment_schedule": {
"amount": 48.39000000000001,
"auto_process": true,
"balance": -0.009999999999990905,
"contract_body": "By submitting your order and <em>authorizing</em> the charges on your card, you are legally bound to the following terms:\r\n\r\nI, Bob Fake, acknowledge that I authorize Partial.ly to charge $48.40 USD on behalf of Store Startup today, and $48.40 USD on the following payment dates:\r\n\r\n$48.39 USD on Thursday June 2, 2022\r\n\r\nI acknowledge that a total of $96.79 USD USD will be paid to Store Startup by June 2, 2022.\r\n\r\n\r\nI <strong>acknowledge</strong> that the credit card(s) or payment method(s) I am using to make this purchase will be active, valid and have sufficient funds available during the entire term of the payback period. If for any reason my payment is declined, I will provide an alternative, valid payment method.\r\n\r\nI understand that I may be assessed a late fee(s) if a payment is missed on any of the agreed-upon payment dates for any reason whatsoever.\r\n\r\nI understand that I am legally bound to these terms and required by law to make all payments on the agreed-upon payment dates.\r\n\r\nStore Startup reserves the right to report delinquent payments to credit agencies and collections agencies.\r\n\r\n",
"contract_signature": "Bilbo Baggins",
"contract_signed_date": "2022-05-02T16:05:40Z",
"description": null,
"down_payment_amount": 48.4,
"first_payment_date_buffer_days": null,
"first_payment_date_buffer_days_enabled?": false,
"frequency": 1,
"frequency_days": [],
"frequency_units": "months",
"id": "d6fd47da-bbfe-41fd-bc63-0d9521716391",
"inserted_at": "2022-05-02T16:05:40Z",
"installments": [
{
"amount": 48.39,
"id": "9ae02520-6be2-4fff-9d50-5f0c94f872fc",
"inserted_at": "2022-05-02T16:05:40Z",
"retry_number": 0,
"scheduled": "2022-06-02T16:05:03Z"
}
],
"ip_address": "127.0.0.1",
"num_payments": 1,
"payment_amount": 48.4,
"repay_by_date": "2022-06-02",
"starts_auto": true,
"starts_date": null,
"term": 1,
"term_date": null,
"term_units": "months"
},
"shipto_address": null,
"shipto_address2": null,
"shipto_city": null,
"shipto_country": "US",
"shipto_name": null,
"shipto_postal_code": null,
"shipto_state": null,
"status": "open",
"subtotal": 96.78999999999999,
"user_agent": null
}
}
}
Sent when a payment plan is opened. Note that this will be sent when a new plan is opened for the first time, as well as when an existing plan is re-opened (a defaulted plan being reopened, for example).
plan_paid event
{
"event": "plan_paid",
"id": "test",
"data": {
"payment_plan": {
"amount": 3265.0,
"amount_paid": 3265.0,
"currency": "USD",
"customer": {
"email": "bob@fake.com",
"first_name": "Bob",
"id": "69acb831-9d4d-4d2c-8cc9-f2e75214aa5b",
"inserted_at": "2016-09-12T16:07:44Z",
"last_name": "Fake",
"phone": "678-555-1212",
"shipto_address": "",
"shipto_address2": "",
"shipto_city": "",
"shipto_country": "",
"shipto_name": "",
"shipto_postal_code": "",
"shipto_state": "",
"timezone": "America/New_York"
},
"customer_id": "69acb831-9d4d-4d2c-8cc9-f2e75214aa5b",
"id": "0c9593ff-22b3-4324-a123-919fb7fcca5d",
"inserted_at": "2015-09-15T21:55:53Z",
"integration": null,
"integration_id": null,
"ip_address": "::ffff:10.182.8.87",
"is_reopened": false,
"line_items": [],
"merchant_notes": null,
"meta": {
"description": "Sample Design Invoice"
},
"number": 1,
"offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"payment_method_id": "ab27241e-eafb-4385-88b0-a488580afb4a",
"payment_schedule": {
"amount": 3265.0,
"auto_process": true,
"balance": 3065.0,
"contract_body": "By submitting your order and authorizing the charges on your card, you are legally bound to the following terms:\n\nI, Bob Fake, acknowledge that I authorize Partial.ly to charge $200.00 on behalf of Store Startup today, and $510.84 on the following payment dates:\n\n$510.84 on October 15th, 2015\n\n$510.84 on November 15th, 2015\n\n$510.84 on December 15th, 2015\n\n$510.84 on January 15th, 2016\n\n$510.84 on February 15th, 2016\n\n$510.80 on March 15th, 2016\n\nI acknowledge that a total of $3,265.00 will be paid to Store Startup by April 15th, 2016.\n\nI acknowledge that the credit card(s) or payment method(s) I am using to make this purchase will be active, valid and have sufficient funds available during the entire term of the payback period. If for any reason my payment is declined, I will provide an alternative, valid payment method.\n\nI understand that I may be assessed a late fee(s) if a payment is missed on any of the agreed-upon payment dates for any reason whatsoever.\n\nI understand that I am legally bound to these terms and required by law to make all payments on the agreed-upon payment dates.\n\nStore Startup reserves the right to report delinquent payments to credit agencies and collections agencies.",
"contract_signature": "Bob Fake",
"contract_signed_date": "2015-09-15T21:55:52Z",
"description": null,
"down_payment_amount": 200.0,
"first_payment_date_buffer_days": null,
"first_payment_date_buffer_days_enabled?": false,
"frequency": 1,
"frequency_days": null,
"frequency_units": "months",
"id": "2f4dd052-8642-48d9-b9b8-92d6e3118473",
"inserted_at": "2015-09-15T21:55:53Z",
"installments": [],
"ip_address": "::ffff:10.182.8.87",
"num_payments": 6,
"payment_amount": 510.84,
"repay_by_date": "2016-04-15",
"starts_auto": true,
"starts_date": null,
"term": 6,
"term_date": null,
"term_units": "months"
},
"shipto_address": null,
"shipto_address2": null,
"shipto_city": null,
"shipto_country": "US",
"shipto_name": null,
"shipto_postal_code": null,
"shipto_state": null,
"status": "paid",
"subtotal": 3265.0,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9"
}
}
}
The plan_paid event is triggered when a payment plan is fully paid.
plan_defaulted event
{
"event": "plan_defaulted",
"id": "test",
"data": {
"payment_plan": {
"amount": 21.2,
"amount_paid": 0.0,
"currency": "USD",
"customer": {
"email": "test@testing.com",
"first_name": "Test",
"id": "bc8929b8-e0ab-4149-bb13-3159776cdceb",
"inserted_at": "2016-10-20T11:25:09Z",
"last_name": "Tester",
"phone": "1234567890",
"shipto_address": "12312 ",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "US",
"shipto_name": "test",
"shipto_postal_code": "33611",
"shipto_state": "FL",
"timezone": "America/New_York"
},
"customer_id": "bc8929b8-e0ab-4149-bb13-3159776cdceb",
"id": "80be6129-6a26-4330-983c-5f56f1619f72",
"inserted_at": "2017-09-08T20:51:33Z",
"integration": "woocommerce",
"integration_id": null,
"ip_address": "127.0.0.1",
"is_reopened": true,
"line_items": [
{
"amount": 10.0,
"description": "Sample with variants",
"dynamic": false,
"dynamic_type": "generic",
"id": "6dfae68a-3dbd-4d3b-bd44-48e429c6b2ea",
"inserted_at": "2017-09-08T20:51:33Z",
"integration": "woocommerce",
"integration_id": "8e325a79cd78833c32ddd2afa10eec8a",
"meta": {
"id": "8e325a79cd78833c32ddd2afa10eec8a",
"name": "Sample with variants",
"price": "10",
"product_id": "67",
"quantity": "1",
"sku": "abas23423",
"total": "10",
"variant_id": "70"
},
"quantity": 1,
"weight": 0.0,
"weight_units": "lb"
}
],
"merchant_notes": null,
"meta": null,
"number": 29,
"offer_id": "fe042bc3-336f-4ade-bcdb-77fc1fc0ceb2",
"payment_method_id": "9ecd1a09-0b8d-4d07-bfe6-3c2def0d1b2d",
"payment_schedule": {
"amount": 15.9,
"auto_process": true,
"balance": 15.9,
"contract_body": "By submitting your order and authorizing the electronic debits from your bank account, you are legally bound to the following terms:\r\n\r\nI, Test Tester, acknowledge that I authorize Partial.ly to electronically debit my account $5.30 on the following payment dates:\r\n\r\n$5.30 on Saturday October 14, 2017\r\n\r\n$5.30 on Tuesday November 14, 2017\r\n\r\n$5.30 on Thursday December 14, 2017\r\n\r\nI acknowledge that a total of $21.20 USD will be paid to Store Startup by Thursday December 14, 2017.\r\n\r\n\r\nI acknowledge that the credit card(s) or payment method(s) I am using to make this purchase will be active, valid and have sufficient funds available during the entire term of the payback period. If for any reason my payment is declined, I will provide an alternative, valid payment method.\r\n\r\nI understand that I may be assessed a late fee(s) if a payment is missed on any of the agreed-upon payment dates for any reason whatsoever.\r\n\r\nI understand that I am legally bound to these terms and required by law to make all payments on the agreed-upon payment dates.\r\n\r\nStore Startup reserves the right to report delinquent payments to credit agencies and collections agencies.\r\n\r\n",
"contract_signature": "tha merchant",
"contract_signed_date": "2017-09-14T18:13:28Z",
"description": null,
"down_payment_amount": 0.0,
"first_payment_date_buffer_days": null,
"first_payment_date_buffer_days_enabled?": false,
"frequency": 1,
"frequency_days": [],
"frequency_units": "months",
"id": "cde89c56-1110-4af8-aa21-04e0731f7617",
"inserted_at": "2017-09-14T18:13:24Z",
"installments": [
{
"amount": 5.3,
"id": "58784b85-c59a-4720-bc8e-f02331b785a6",
"inserted_at": "2017-09-14T18:13:28Z",
"retry_number": 0,
"scheduled": "2017-10-14T18:13:28Z"
},
{
"amount": 5.3,
"id": "d0e8fe1c-bc5d-4ca1-88c8-e079715d2cac",
"inserted_at": "2017-09-14T18:13:28Z",
"retry_number": 0,
"scheduled": "2017-11-14T18:13:28Z"
},
{
"amount": 5.3,
"id": "30404e14-922b-47d2-80ad-56ffee3f5940",
"inserted_at": "2017-09-14T18:13:28Z",
"retry_number": 0,
"scheduled": "2017-12-14T18:13:28Z"
}
],
"ip_address": "127.0.0.1",
"num_payments": 3,
"payment_amount": 5.3,
"repay_by_date": "2017-12-14",
"starts_auto": true,
"starts_date": "2017-09-14",
"term": 3,
"term_date": "2017-09-14",
"term_units": "months"
},
"shipto_address": "12312 ",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "US",
"shipto_name": "Test",
"shipto_postal_code": "33611",
"shipto_state": "FL",
"status": "defaulted",
"subtotal": 21.2,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:55.0) Gecko/20100101 Firefox/55.0"
}
}
}
Sent when a payment plan status changes to defaulted, which will occurr when the configured number of consecutive scheduled installments have failed (default 3).
payment_succeeded event
{
"event": "payment_succeeded",
"id": "test",
"data": {
"payment": {
"amount": 510.84,
"charge_type": "destination",
"currency": "USD",
"customer_fee_amount": 0.0,
"fee": 25.84,
"id": "4b2f7372-b8ca-47fb-948d-b34a418150ce",
"inserted_at": "2015-11-15T12:00:02Z",
"message": null,
"paid_at": "2015-11-15T12:00:02Z",
"payment_method": {
"id": "12b61a91-9934-453f-9fd0-ad22c343a087",
"inserted_at": "2015-09-15T21:36:53Z",
"integration_details": {
"brand": "American Express",
"country": "US",
"exp_month": "8",
"exp_year": "2019",
"funding": null,
"last4": "1111"
},
"type": "card"
},
"payment_plan": {
"amount": 3265.0,
"amount_paid": 3265.0,
"currency": "USD",
"customer": {
"email": "bob@fake.com",
"first_name": "Bob",
"id": "69acb831-9d4d-4d2c-8cc9-f2e75214aa5b",
"inserted_at": "2016-09-12T16:07:44Z",
"last_name": "Fake",
"phone": "678-520-8206",
"shipto_address": "",
"shipto_address2": "",
"shipto_city": "",
"shipto_country": "",
"shipto_name": "",
"shipto_postal_code": "",
"shipto_state": "",
"timezone": "America/New_York"
},
"customer_id": "69acb831-9d4d-4d2c-8cc9-f2e75214aa5b",
"id": "0c9593ff-22b3-4324-a123-919fb7fcca5d",
"inserted_at": "2015-09-15T21:55:53Z",
"integration": null,
"integration_id": null,
"ip_address": "::ffff:10.182.8.87",
"is_reopened": false,
"merchant_notes": null,
"meta": {
"description": "Sample Design Invoice"
},
"number": 1,
"offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"payment_method_id": "ab27241e-eafb-4385-88b0-a488580afb4a",
"shipto_address": null,
"shipto_address2": null,
"shipto_city": null,
"shipto_country": "US",
"shipto_name": null,
"shipto_postal_code": null,
"shipto_state": null,
"status": "paid",
"subtotal": 3265.0,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9"
},
"payment_plan_id": "0c9593ff-22b3-4324-a123-919fb7fcca5d",
"processor": "stripe",
"processor_destination_id": null,
"processor_id": "ch_177PArEs15StTpSvMeqwLJFr",
"redirect_url": null,
"retry_number": null,
"status": "paid",
"type": "auto",
"user": null
}
}
}
Sent when a payment suceeds. Note that for certain payment method types, such as bank account, this maybe event may be up to 5 business days after the payment is submit until it's confirmed.
payment_failed event
{
"event": "payment_failed",
"id": "test",
"data": {
"payment": {
"amount": 2.5,
"charge_type": "destination",
"currency": "EUR",
"customer_fee_amount": 0.0,
"fee": 0.0,
"id": "dcd36f39-0539-40ce-8fce-77709ea05008",
"inserted_at": "2019-07-01T15:23:05Z",
"message": "Error from Stripe: The card has insufficient funds",
"paid_at": null,
"payment_method": {
"id": "b7a7b42a-a693-4fe9-b265-99d304cf3b93",
"inserted_at": "2018-08-21T17:56:00Z",
"integration_details": {
"brand": "American Express",
"country": "US",
"exp_month": "8",
"exp_year": "2019",
"funding": null,
"last4": "1111"
},
"type": "card"
},
"payment_plan": {
"amount": 255.0,
"amount_paid": 50.5,
"currency": "EUR",
"customer": {
"email": "bob@fake.com",
"first_name": "Bob",
"id": "452cc42f-d999-4c0f-998b-325c4e0e8f57",
"inserted_at": "2015-11-16T16:03:22Z",
"last_name": "Fake",
"phone": "+18135551212",
"shipto_address": "345 bayshore blvd",
"shipto_address2": null,
"shipto_city": "TAMPA",
"shipto_country": "US",
"shipto_name": "Test Customer",
"shipto_postal_code": "33611-4728",
"shipto_state": "FL",
"timezone": "America/New_York"
},
"customer_id": "452cc42f-d999-4c0f-998b-325c4e0e8f57",
"id": "34661b40-3fcc-4e65-a156-4c57054527ec",
"inserted_at": "2018-08-21T17:46:49Z",
"integration": null,
"integration_id": null,
"ip_address": "127.0.0.1",
"is_reopened": false,
"merchant_notes": null,
"meta": {
"description": "testing manuel"
},
"number": 124,
"offer_id": "203fb249-b43b-4f9e-a31b-6690a6d8f660",
"payment_method_id": "b7a7b42a-a693-4fe9-b265-99d304cf3b93",
"shipto_address": "123123",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "DE",
"shipto_name": "Test Customer",
"shipto_postal_code": "33611",
"shipto_state": null,
"status": "open",
"subtotal": 255.0,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
},
"payment_plan_id": "34661b40-3fcc-4e65-a156-4c57054527ec",
"processor": "stripe",
"processor_destination_id": null,
"processor_id": null,
"redirect_url": null,
"retry_number": 0,
"status": "failed",
"type": "auto",
"user": null
}
}
}
Sent when a payment fails.
refund_created event
{
"event": "refund_created",
"id": "test",
"data": {
"refund": {
"amount": 472.19,
"failure_merchant_transfer_id": null,
"failure_reason": null,
"id": "6e071d81-f030-41db-8511-6aa646f6dc75",
"inserted_at": "2015-12-08T16:43:43Z",
"notes": null,
"payment": {
"amount": 472.19,
"charge_type": "destination",
"currency": "USD",
"customer_fee_amount": 0.0,
"fee": 23.91,
"id": "5266501d-d953-4a1d-82f2-ed67e8a6af09",
"inserted_at": "2015-12-08T16:30:57Z",
"message": null,
"paid_at": "2015-12-08T16:30:57Z",
"payment_method": {
"id": "12b61a91-9934-453f-9fd0-ad22c343a087",
"inserted_at": "2015-09-15T21:36:53Z",
"integration_details": {
"brand": "American Express",
"country": "US",
"exp_month": "8",
"exp_year": "2019",
"funding": null,
"last4": "1111"
},
"type": "card"
},
"payment_plan": {
"amount": 1888.75,
"amount_paid": 0.0,
"currency": "USD",
"customer": {
"email": "bob@fake.com",
"first_name": "Bob",
"id": "69acb831-9d4d-4d2c-8cc9-f2e75214aa5b",
"inserted_at": "2016-09-12T16:07:44Z",
"last_name": "Fake",
"phone": "678-520-8206",
"shipto_address": "",
"shipto_address2": "",
"shipto_city": "",
"shipto_country": "",
"shipto_name": "",
"shipto_postal_code": "",
"shipto_state": "",
"timezone": "America/New_York"
},
"customer_id": "69acb831-9d4d-4d2c-8cc9-f2e75214aa5b",
"id": "17c6f090-de95-4e04-9469-32c017567b1d",
"inserted_at": "2015-12-08T16:30:57Z",
"integration": null,
"integration_id": null,
"ip_address": "::ffff:10.182.8.87",
"is_reopened": false,
"merchant_notes": null,
"meta": {
"description": "Harvest Invoice ID 158"
},
"number": 9,
"offer_id": "60aed439-473f-48e0-80ef-3a8627dd243a",
"payment_method_id": "12b61a91-9934-453f-9fd0-ad22c343a087",
"shipto_address": null,
"shipto_address2": null,
"shipto_city": null,
"shipto_country": "US",
"shipto_name": null,
"shipto_postal_code": null,
"shipto_state": null,
"status": "canceled",
"subtotal": 1888.75,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/601.2.7 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.7"
},
"payment_plan_id": "17c6f090-de95-4e04-9469-32c017567b1d",
"processor": "stripe",
"processor_destination_id": null,
"processor_id": "ch_17FoMeEs15StTpSvpltBMWbg",
"redirect_url": null,
"retry_number": 0,
"status": "paid",
"type": "auto",
"user": null
},
"payment_id": "5266501d-d953-4a1d-82f2-ed67e8a6af09",
"processor": "stripe",
"processor_id": "re_17FoZ1Es15StTpSvXcn4uLPp",
"reason": null,
"status": "succeeded"
}
}
}
Sent when a refund is created.
dispute_created event
{
"event": "dispute_created",
"id": "test",
"data": {
"dispute": {
"amount": 150.0,
"id": "bc1311c5-73db-4ca5-9550-891db55b767d",
"inserted_at": "2023-07-16T18:02:26Z",
"payment": {
"amount": 150.0,
"charge_type": "destination",
"currency": "USD",
"customer_fee_amount": 0.0,
"fee": 6.6,
"id": "53e64081-659a-4df8-ab8e-7bfb06ec09fa",
"inserted_at": "2023-07-16T18:02:23Z",
"message": null,
"paid_at": "2023-07-16T18:02:23Z",
"payment_method": {
"id": "b828da1c-58f6-4a87-b870-e04c51f013c6",
"inserted_at": "2023-07-16T17:59:07Z",
"integration_details": {
"brand": "visa",
"country": "US",
"exp_month": 11,
"exp_year": 2028,
"fingerprint": "cTA72UojsYE5ZUqQ",
"funding": "credit",
"last4": "1234"
},
"type": "card"
},
"payment_plan": {
"amount": 450.0,
"amount_paid": 300.0,
"currency": "USD",
"customer": {
"email": "jdoe@fake.com",
"first_name": "John",
"id": "fa42b43d-af00-411a-89e1-dc415849652b",
"inserted_at": "2021-04-19T17:55:09Z",
"last_name": "Doe",
"phone": "+15045551212",
"shipto_address": "123 maine Ave",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "US",
"shipto_name": "John Doe",
"shipto_postal_code": "33611",
"shipto_state": "FL",
"timezone": "America/New_York"
},
"customer_id": "fa42b43d-af00-411a-89e1-dc415849652b",
"id": "b86e7f4a-abe9-4541-b42a-4cea49304c4f",
"inserted_at": "2023-07-16T17:56:37Z",
"integration": null,
"integration_id": null,
"ip_address": "127.0.0.1",
"is_reopened": false,
"merchant_notes": null,
"meta": {
"description": "test"
},
"number": 463,
"offer_id": "998f5c9d-b359-42da-a9ac-0a416c819091",
"payment_method_id": "48b5f2ac-e3b6-4c67-8077-bad0eba48bfc",
"shipto_address": "123 main Ave",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "US",
"shipto_name": "J Doe",
"shipto_postal_code": "33611",
"shipto_state": "FL",
"status": "open",
"subtotal": 400.0,
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
},
"payment_plan_id": "b86e7f4a-abe9-4541-b42a-4cea49304c4f",
"processor": "stripe",
"processor_destination_id": "py_1NUZGzJdLv8qpyyQ1jz7ZO1M",
"processor_id": "pi_3NUZGzEs15StTpSv0xROLwe8",
"redirect_url": null,
"retry_number": 0,
"status": "paid",
"type": "manual_admin",
"user": {
"email": "partiallyadmin@gmail.com",
"id": "3a68691f-27c1-4fca-b618-c08eb56a2c1b",
"inserted_at": "2017-09-06T04:46:42Z"
}
},
"payment_id": "53e64081-659a-4df8-ab8e-7bfb06ec09fa",
"reason": "product_not_received",
"status": "needs_response"
}
}
}
Sent when a new dispute is created.
dispute_closed event
{
"event": "dispute_closed",
"id": "123456789",
"data": {
"dispute": {
"amount": 25.0,
"id": "123abc",
"payment": {
"amount": 25.0,
"currency": "USD",
"id": "143345",
"payment_plan": {
"amount": 100.0,
"amount_paid": 50.0,
"currency": "USD",
"customer": {
"email": "jdoe@gmail.com",
"first_name": "John",
"last_name": "Doe"
},
"id": "234234",
"number": "1",
"status": "open"
},
"status": "paid"
},
"reason": "unrecognized",
"status": "won"
}
}
}
Sent when a dispute is closed, either won or lost.
checkout_abandoned event
{
"event": "checkout_abandoned",
"id": "test",
"data": {
"payment_plan": {
"amount": 275.6,
"amount_paid": 0.0,
"currency": "USD",
"customer": {
"email": "jdoe@partial.ly",
"first_name": "John",
"id": "89c25cc8-d94c-45f6-b728-279928aeb3c8",
"inserted_at": "2018-07-20T14:51:20Z",
"last_name": "Doe",
"phone": "+18135551212",
"shipto_address": "123 main Ave",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "US",
"shipto_name": "J Doe",
"shipto_postal_code": "33611",
"shipto_state": "FL",
"timezone": "America/New_York"
},
"customer_id": "89c25cc8-d94c-45f6-b728-279928aeb3c8",
"id": "da8c46c5-518c-4a6b-87fb-4878a5b2ed8e",
"inserted_at": "2018-08-06T14:59:58Z",
"integration": "woocommerce",
"integration_id": "191",
"ip_address": "127.0.0.1",
"is_reopened": false,
"line_items": [
{
"amount": 250.0,
"description": "The new hotness",
"dynamic": false,
"dynamic_type": "generic",
"id": "7be7275d-1518-4837-ac9e-ddde24904b2a",
"inserted_at": "2018-08-06T14:59:58Z",
"integration": "woocommerce",
"integration_id": null,
"meta": {
"name": "The new hotness",
"price": 250,
"product_id": 157,
"quantity": 1,
"sku": "",
"total": "250"
},
"quantity": 1,
"weight": 0.0,
"weight_units": "lb"
}
],
"merchant_notes": null,
"meta": {
"checkout_cancel_url": "http://wootest.local:8080/cart/?cancel_order=true&order=wc_order_5b68626d9daac&order_id=191&redirect&_wpnonce=0f4253a8fe",
"checkout_complete_url": "http://wootest.local:8080/checkout/order-received/191/?key=wc_order_5b68626d9daac",
"items": [
{
"name": "The new hotness",
"price": 250,
"product_id": 157,
"quantity": 1,
"sku": "",
"total": "250"
}
]
},
"number": null,
"offer_id": "fe042bc3-336f-4ade-bcdb-77fc1fc0ceb2",
"payment_method_id": null,
"payment_schedule": {
"amount": 275.6,
"auto_process": true,
"balance": 206.70000000000002,
"contract_body": null,
"contract_signature": null,
"contract_signed_date": null,
"description": null,
"down_payment_amount": 68.9,
"first_payment_date_buffer_days": null,
"first_payment_date_buffer_days_enabled?": false,
"frequency": 2,
"frequency_days": [],
"frequency_units": "weeks",
"id": "26cf43e4-1f19-4058-a7f1-b7ff57726ba4",
"inserted_at": "2018-08-06T14:59:58Z",
"installments": [],
"ip_address": null,
"num_payments": 6,
"payment_amount": 34.46,
"repay_by_date": "2018-10-29",
"starts_auto": true,
"starts_date": null,
"term": 3,
"term_date": "2017-09-27",
"term_units": "months"
},
"shipto_address": "123 main ave",
"shipto_address2": null,
"shipto_city": "Tampa",
"shipto_country": "US",
"shipto_name": null,
"shipto_postal_code": "33611",
"shipto_state": "FL",
"status": "checkout",
"subtotal": 275.6,
"user_agent": "WordPress/4.9.3; http://wootest.local:8080"
}
}
}
Sent when a Partial.ly checkout is abandoned. The amount of time it takes to triggered this can be configured in your abandoned cart settings in the Partial.ly merchant portal. Note that if the customer hasn't made it through the customer step of the checkout process by the time the checkout is considered abandoned, this information will be empty in the webhook.