NAV Navbar
cURL Node

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
email 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
email 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
email 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
email 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.