Create a Subscription

Step 1: Create a Customer

If this is a new customer, please use the Create Customer guide to create them in the system. If you already have the customer ID, please jump to Step 2. Let's assume the Customer ID you have is KPxMADVnxMV4nNjp.

Step 2 - option 1: Tokenize a Card

We will store and tokenize a card credential, then attach it to the customer ID.

POSThttps://testapi.payarc.net/v1/tokens

We will use this API to create the token that represents a credit or debit card used to carry out a transaction.

We are assuming the card source is INTERNET, and will capture the card number 4012000098765439, expiration month 12and year 2025 and CVV 999.

We can choose if we want to perform a zero-dollar authorization, which will ensure that the card is active. Please note that this may result in additional fees. We will set authorize_card to 1 for this example, which will perform the authorization.

import http.client

conn = http.client.HTTPSConnection("testapi.payarc.net")
payload = 'card_source=INTERNET&card_number=4012000098765439&exp_month=12&exp_year=2025&cvv=999&authorize_card=1'
headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/x-www-form-urlencoded',
  'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI0NTIyIiwianRpIjoiYmQ5NjhjZDVlMDI5ZDg3MGMzNjljZmExOGZkN2IxMTk3MjJlYWQ4YzcxODMzNTM0ZjE0OTU3Zjc1Y2E4ZWI2NmM5MTIwMDk0NTI0NWFmNzMiLCJpYXQiOjE3MDE5MzU4NjEsIm5iZiI6MTcwMTkzNTg2MSwiZXhwIjoxODU5NjE1ODYxLCJzdWIiOiI4NTI2MTg4Iiwic2NvcGVzIjoiKiJ9.KOJALGZ-u8CuRJcapzV22anTy7VGYyEUm3qzAaXVpQfX5rX_8bmuD9Kl2vF4FfvCreJ-cOem0-c3BZLLd6cEOiV4v0kwA2O70g3HCg80g8YCPsw9F3ggOtVFWgLPofBZp56WI0q-slykAQhXQOeM7MbqnHvLUdVQClCTrxb4-_332wyZUbX_zMj2Q_o-Wunzo0DPQhGrBTV7Va-jTXwOfcHcFMtuGTVoCGoz0qqmpO5E5QuAP9DQW2296SWd-zNF90XJ9RiqKN5BUQjx9-0m7TV0ryYpm4H-bhdOwuDpWBrJyIhNsQ9hpOjF8MXEXPho5weJwMKTsDk3iii6x7AAWv_8WvppC0ZGBLxT-TcV09vVumbsm2JVjG8wKLZRYE16Y2VFXrQc8s7TkZ-h-vHbHEGantICV5XdAZ9eTVnSY9NhgNlvsC4DYdw9hL7mW3F5qpT8mqFVzVGDIUMdXkuGuFpX7BZHw-pKU82ID7P3Jxpv8t1QzES7ITyCCGZswtOiNTh8PaPRIcLHtOWxaNUQTk0BCWuvNDesqkRDKBm8bQKfXu3vjBFq-_MHV4HiylGaec_KBSJv0fLyzTcwfHrXFbFFoevJANzw5BMezMwEPWY7XL-tH2LZ3HfiwiQcjFkNYyYVzrzOa-dIzHx0U35BzQdCxKEqxLpgFUY1T-PIr08'
}
conn.request("POST", "/v1/tokens", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
var https = require('follow-redirects').https;
var fs = require('fs');

var qs = require('querystring');

var options = {
  'method': 'POST',
  'hostname': 'testapi.payarc.net',
  'path': '/v1/tokens',
  'headers': {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI0NTIyIiwianRpIjoiYmQ5NjhjZDVlMDI5ZDg3MGMzNjljZmExOGZkN2IxMTk3MjJlYWQ4YzcxODMzNTM0ZjE0OTU3Zjc1Y2E4ZWI2NmM5MTIwMDk0NTI0NWFmNzMiLCJpYXQiOjE3MDE5MzU4NjEsIm5iZiI6MTcwMTkzNTg2MSwiZXhwIjoxODU5NjE1ODYxLCJzdWIiOiI4NTI2MTg4Iiwic2NvcGVzIjoiKiJ9.KOJALGZ-u8CuRJcapzV22anTy7VGYyEUm3qzAaXVpQfX5rX_8bmuD9Kl2vF4FfvCreJ-cOem0-c3BZLLd6cEOiV4v0kwA2O70g3HCg80g8YCPsw9F3ggOtVFWgLPofBZp56WI0q-slykAQhXQOeM7MbqnHvLUdVQClCTrxb4-_332wyZUbX_zMj2Q_o-Wunzo0DPQhGrBTV7Va-jTXwOfcHcFMtuGTVoCGoz0qqmpO5E5QuAP9DQW2296SWd-zNF90XJ9RiqKN5BUQjx9-0m7TV0ryYpm4H-bhdOwuDpWBrJyIhNsQ9hpOjF8MXEXPho5weJwMKTsDk3iii6x7AAWv_8WvppC0ZGBLxT-TcV09vVumbsm2JVjG8wKLZRYE16Y2VFXrQc8s7TkZ-h-vHbHEGantICV5XdAZ9eTVnSY9NhgNlvsC4DYdw9hL7mW3F5qpT8mqFVzVGDIUMdXkuGuFpX7BZHw-pKU82ID7P3Jxpv8t1QzES7ITyCCGZswtOiNTh8PaPRIcLHtOWxaNUQTk0BCWuvNDesqkRDKBm8bQKfXu3vjBFq-_MHV4HiylGaec_KBSJv0fLyzTcwfHrXFbFFoevJANzw5BMezMwEPWY7XL-tH2LZ3HfiwiQcjFkNYyYVzrzOa-dIzHx0U35BzQdCxKEqxLpgFUY1T-PIr08'
  },
  'maxRedirects': 20
};

var req = https.request(options, function (res) {
  var chunks = [];

  res.on("data", function (chunk) {
    chunks.push(chunk);
  });

  res.on("end", function (chunk) {
    var body = Buffer.concat(chunks);
    console.log(body.toString());
  });

  res.on("error", function (error) {
    console.error(error);
  });
});

var postData = qs.stringify({
  'card_source': 'INTERNET',
  'card_number': '4012000098765439',
  'exp_month': '12',
  'exp_year': '2025',
  'cvv': '999'
  'authorize_card': '1'
});

req.write(postData);

req.end();
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://testapi.payarc.net/v1/tokens");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI0NTIyIiwianRpIjoiYmQ5NjhjZDVlMDI5ZDg3MGMzNjljZmExOGZkN2IxMTk3MjJlYWQ4YzcxODMzNTM0ZjE0OTU3Zjc1Y2E4ZWI2NmM5MTIwMDk0NTI0NWFmNzMiLCJpYXQiOjE3MDE5MzU4NjEsIm5iZiI6MTcwMTkzNTg2MSwiZXhwIjoxODU5NjE1ODYxLCJzdWIiOiI4NTI2MTg4Iiwic2NvcGVzIjoiKiJ9.KOJALGZ-u8CuRJcapzV22anTy7VGYyEUm3qzAaXVpQfX5rX_8bmuD9Kl2vF4FfvCreJ-cOem0-c3BZLLd6cEOiV4v0kwA2O70g3HCg80g8YCPsw9F3ggOtVFWgLPofBZp56WI0q-slykAQhXQOeM7MbqnHvLUdVQClCTrxb4-_332wyZUbX_zMj2Q_o-Wunzo0DPQhGrBTV7Va-jTXwOfcHcFMtuGTVoCGoz0qqmpO5E5QuAP9DQW2296SWd-zNF90XJ9RiqKN5BUQjx9-0m7TV0ryYpm4H-bhdOwuDpWBrJyIhNsQ9hpOjF8MXEXPho5weJwMKTsDk3iii6x7AAWv_8WvppC0ZGBLxT-TcV09vVumbsm2JVjG8wKLZRYE16Y2VFXrQc8s7TkZ-h-vHbHEGantICV5XdAZ9eTVnSY9NhgNlvsC4DYdw9hL7mW3F5qpT8mqFVzVGDIUMdXkuGuFpX7BZHw-pKU82ID7P3Jxpv8t1QzES7ITyCCGZswtOiNTh8PaPRIcLHtOWxaNUQTk0BCWuvNDesqkRDKBm8bQKfXu3vjBFq-_MHV4HiylGaec_KBSJv0fLyzTcwfHrXFbFFoevJANzw5BMezMwEPWY7XL-tH2LZ3HfiwiQcjFkNYyYVzrzOa-dIzHx0U35BzQdCxKEqxLpgFUY1T-PIr08");
var collection = new List<KeyValuePair<string, string>>();
collection.Add(new("card_source", "INTERNET"));
collection.Add(new("card_number", "4012000098765439"));
collection.Add(new("exp_month", "12"));
collection.Add(new("exp_year", "2025"));
collection.Add(new("cvv", "999"));
collection.Add(new("authorize_card", "1"));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

We will receive a Token object - in this case it has the ID NmLY0wmqEYq8w8ql

{
  "data": {
    "object": "Token",
    "id": "NmLY0wmqEYq8w8ql",
    "used": false,
    "ip": null,
    "tokenization_method": null,
    "created_at": 1620129151,
    "updated_at": 1620129151,
    "card": {
      "data": {
        "object": "Card",
        "id": "15y2901N9L2L0MLv",
        "address1": null,
        "address2": null,
        "card_source": "INTERNET",
        "card_holder_name": null,
        "is_default": 0,
        "exp_month": "12",
        "exp_year": "2025",
        "is_verified": 0,
        "fingerprint": "my905PmvmPNmNP0M",
        "city": null,
        "state": null,
        "zip": null,
        "brand": "V",
        "last4digit": "5439",
        "first6digit": 401200,
        "country": null,
        "avs_status": null,
        "cvc_status": null,
        "address_check_passed": 0,
        "zip_check_passed": 0,
        "customer_id": null,
        "created_at": 1620129151,
        "updated_at": 1620129151
      }
    }
  },
  "meta": {
    "include": [],
    "custom": []
  }
}

We will then link the token ID we received to the customer. It will become the default payment credential.

PATCHhttps://api.payarc.net/v1/customers/{customer_id}

Remember, our customer ID was KPxMADVnxMV4nNjp, so we will have to PATCHhttps://api.payarc.net/v1/customers/KPxMADVnxMV4nNjp

The only parameter we need to send is our Token ID, NmLY0wmqEYq8w8ql

var request = require('request');
var options = {
  'method': 'PATCH',
  'url': 'https://api.payarc.net/v1/customers/{{customer_id}}',
  'headers': {
    'Authorization': '{{bearer_token}}',
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    'token_id': 'NmLY0wmqEYq8w8ql'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

Step 2 - option 2: Add a bank account

POSThttps://api.payarc.net/v1/bankaccounts/{id}

We will store the bank account information for the customer performing the transaction.

ParameterDescription
account_number
Required
Account Number for the account.
Format: Numeric, Length 3-17.
Example: 0114584906
routing_number
Required
Nine-digit routing number for the account.
Format: Numeric, Length:9
Example: 129131673
first_name
Required
Account holder's first name
Format: AlphaNumeric, Length 2-50
Example: John
last_name
Required
Account holder's first name
Format: AlphaNumeric, Length 2-50
Example: Hancock
account_type
Required
The type of account
Format: One of the following: Personal Checking, Personal Savings, Business Checking, Business Savings
Example:Personal Checking
customer_id
Optional
The Customer ID against which a new subscription will be created
Format: AlphaNumeric
Example: KPxMADVnxMV4nNjp
import http.client

conn = http.client.HTTPSConnection("api.payarc.net")
payload = 'account_number=%0114584906%22&routing_number=%129131673%22&first_name=%22John%22&last_name=%22Hancock%22&account_type=%22Personal%20Checking%22&&customer_id=%22KPxMADVnxMV4nNjp%22'
headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/x-www-form-urlencoded',
  'Authorization': 'Bearer {{Access-Token-From-Payarc-Dashboard}}'
}
conn.request("POST", "/v1/bankaccounts", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api.payarc.net/v1/bankaccounts',
  'headers': {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Bearer {{Access-Token-From-Payarc-Dashboard}}'
  },
  form: {
    'account_number': '"0114584906"',
    'routing_number': '"129131673"',
    'first_name': '"John"',
    'last_name': '"Hancock"',
    'account_type': '"Personal Checking"',
    'customer_id': '"DjPnVDNApDDnVpMN"'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.payarc.net/v1/bankaccounts");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer {{Access-Token-From-Payarc-Dashboard}}");
var collection = new List<KeyValuePair<string, string>>();
collection.Add(new("account_number", "\"0114584906\""));
collection.Add(new("routing_number", "\"129131673\""));
collection.Add(new("first_name", "\"John\""));
collection.Add(new("last_name", "\"Hancock\""));
collection.Add(new("account_type", "\"Personal Checking\""));
collection.Add(new("customer_id", "\"DjPnVDNApDDnVpMN\""));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

You will receive a BankAccount object.


Step 3: Create a Plan

In order to create a subscription, you need to have configured a plan that the subscription will be linked to. The plan is the template you will use for all customers, and a subscription is a specific user's instance of a plan.

If you have already configured plans, please find the relevant plan ID, we will assume it is Yq8wLY0wmqE8qlNm and skip to the next step. Otherwise, let's configure your first plan.

POSThttps://api.payarc.net/v1/plans

Let's say that you want to create a subscription for a magazine, for $10 a month.

You can use an internal ID for the plan, let's call it plan_id=Magazine10Monthly. Otherwise, Payarc will generate a plan ID for you.

The amount to be charged is represented in cents, so we will have to use 1000 to represent our $10 subscription.

We will also name the plan Magazine subscription for $10 and set the intervalfor billing to month and interval_count to 1, to represent that we will be billing every month. If we had wanted to bill every second month, we would have set interval_count to 2.

We will also have to provide a short description for the plan in the statement_descriptor, it should be between 5 and 25 characters. We will choose "Magazine subscription 10 2024"

We will signal that this is a digital plan by setting plan_type as digital.

import http.client

conn = http.client.HTTPSConnection("https")
payload = 'amount=1000&currency=usd&interval=month&interval_count=1&name=Magazine%20subscription%20for%20%2410&plan_code=Magazine10Monthly&statement_descriptor=Magazine%20subscription%2010%202024'
headers = {
  'Authorization': '{{bearer_token}}',
  'Accept': 'application/json'
}
conn.request("POST", "//api.payarc.net/v1/plans", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api.payarc.net/v1/plans',
  'headers': {
    'Authorization': '{{bearer_token}}',
    'Accept': 'application/json'
  },
  form: {
    'amount': ' 1000',
    'currency': 'usd',
    'interval': 'month',
    'interval_count': ' 1',
    'name': 'Magazine Subscription for $10',
    'plan_code': 'Magazine10Monthly',
    'statement_descriptor': 'Magazine subscription 10 2024',
    'trial_period_days': '3'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.payarc.net/v1/plans");
request.Headers.Add("Authorization", "{{bearer_token}}");
request.Headers.Add("Accept", "application/json");
var collection = new List<KeyValuePair<string, string>>();
collection.Add(new("amount", " 1000"));
collection.Add(new("currency", "usd"));
collection.Add(new("interval", "day"));
collection.Add(new("interval_count", " 1"));
collection.Add(new("name", "Magazine subscription for $10"));
collection.Add(new("plan_code", "Magazine10Monthly"));
collection.Add(new("statement_descriptor", "Magazine subscription 10 2024"));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

We will receive a Plan object.

{
  "data": {
    "object": "Plan",
    "id": "Yq8wLY0wmqE8qlNm",
    "real_id": 9,
    "amount": "1000",
    "interval": "month",
    "interval_count": "1",
    "name": "Magazine subscription for $10",
    "description": null,
    "statement_descriptor": "Magazine subscription 10 2024",
    "currency": "usd",
    "created_at": {
      "date": "2018-11-27 09:15:59.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    },
    "updated_at": {
      "date": "2018-11-27 09:15:59.000000",
      "timezone_type": 3,
      "timezone": "UTC"
    }
  },
  "meta": {
    "include": [],
    "custom": []
  }

}

Step 4 (optional): Create a Coupon

If you wish to offer either a percent off subscriptions, or an amount off, you can create a coupon, and at the next step, apply it to a subscription. The same coupon can be applied to multiple subscriptions.

If you have already created a coupon, grab its ID and skip to the next step.

POSThttps://api.payarc.net/v1/discounts

Let's suppose we want to create a discount code named 3MONTHS10 that will offer 10% off for the first 3 months of a subscription. We will set the name to 3MONTHS10, duration set to repeating, duration_in_months to 3 and percent_off to 10.

📘

If you want to offer high-value discounts, or discounts personalized to certain groups of users, you should use a discount code name that is hard to guess or randomly generated, instead.

import http.client

conn = http.client.HTTPSConnection("api.payarc.net")
payload = 'name=3MONTHS10&duration=repeating&duration_in_months=3&percent_off=10'
headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/x-www-form-urlencoded',
  'Authorization': 'Bearer {{Access-Token-From-Payarc-Dashboard}}'
}
conn.request("POST", "/v1/discounts", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.payarc.net/v1/discounts");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer {{Access-Token-From-Payarc-Dashboard}}");
var collection = new List<KeyValuePair<string, string>>();
collection.Add(new("name", "3MONTHS10"));
collection.Add(new("duration", "repeating"));
collection.Add(new("duration_in_months", "3"));
collection.Add(new("percent_off", "10"));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
var https = require('follow-redirects').https;
var fs = require('fs');

var qs = require('querystring');

var options = {
  'method': 'POST',
  'hostname': 'api.payarc.net',
  'path': '/v1/discounts',
  'headers': {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Bearer {{Access-Token-From-Payarc-Dashboard}}'
  },
  'maxRedirects': 20
};

var req = https.request(options, function (res) {
  var chunks = [];

  res.on("data", function (chunk) {
    chunks.push(chunk);
  });

  res.on("end", function (chunk) {
    var body = Buffer.concat(chunks);
    console.log(body.toString());
  });

  res.on("error", function (error) {
    console.error(error);
  });
});

var postData = qs.stringify({
  'name': '3MONTHS10',
  'duration': 'repeating',
  'duration_in_months': '3',
  'percent_off': '99'
});

req.write(postData);

req.end();

We will receive the new coupon ID dc_c7cc1e9c

Step 5: Create a Subscription

Now we will put everything together and create a subscription for our customer idKPxMADVnxMV4nNjp, using our plan Yq8wLY0wmqE8qlNm, applying our coupon dc_c7cc1e9c.

We will not set up a subscription end date.

In order to charge the customer's card on file automatically, we will set the billing_type to 1.

We will POST to the endpoint https://api.payarc.net/v1/subscriptions

import http.client

conn = http.client.HTTPSConnection("api.payarc.net")
payload = 'customer_id=KPxMADVnxMV4nNjp&plan_id=Yq8wLY0wmqE8qlNm&discount_id=dc_c7cc1e9c&billing_type=1'
headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/x-www-form-urlencoded',
  'Authorization': 'Bearer {{Access-Token-From-Payarc-Dashboard}}'
}
conn.request("POST", "/v1/subscriptions", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
var https = require('follow-redirects').https;
var fs = require('fs');

var qs = require('querystring');

var options = {
  'method': 'POST',
  'hostname': 'api.payarc.net',
  'path': '/v1/subscriptions',
  'headers': {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Bearer {{Access-Token-From-Payarc-Dashboard}}'
  },
  'maxRedirects': 20
};

var req = https.request(options, function (res) {
  var chunks = [];

  res.on("data", function (chunk) {
    chunks.push(chunk);
  });

  res.on("end", function (chunk) {
    var body = Buffer.concat(chunks);
    console.log(body.toString());
  });

  res.on("error", function (error) {
    console.error(error);
  });
});

var postData = qs.stringify({
  'customer_id': 'KPxMADVnxMV4nNjp',
  'plan_id': 'Yq8wLY0wmqE8qlNm',
  'discount_id': 'dc_c7cc1e9c',
  'billing_type': '1'
});

req.write(postData);

req.end();
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.payarc.net/v1/subscriptions");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer {{Access-Token-From-Payarc-Dashboard}}");
var collection = new List<KeyValuePair<string, string>>();
collection.Add(new("customer_id", "KPxMADVnxMV4nNjp"));
collection.Add(new("plan_id", "Yq8wLY0wmqE8qlNm"));
collection.Add(new("discount_id", "dc_c7cc1e9c"));
collection.Add(new("billing_type", "1"));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

We will receive the new subscription ID dc_c7cc1e9c