Tax Payment Walkthrough
Money will not be submitted to the tax authority in your sandbox environment, so it’s the best way to test your integration before going to production. You can force a Quarterly Tax Payment to resolve to a specific status in your sandbox environment to test various scenarios by passing the amount
specified in the testing in the sandbox environment guide. This is especially useful when testing Webhooks for different statuses.
There are three steps to create your first Quarterly Tax Payment:
1. Create a User
A User is the individual for whom you will be submitting the tax payment. To create a User, you can follow the Creating a User guide.
2. Create a Payment Method
KYC verification required
When creating a paymentMethod in Abound, you are certifying that you have verified the owner of the account by adhering to federal KYC requirements. Reach out to Abound support if you have any questions.
A Payment Method represents the bank account from which the tax payment will be charged. For taxPayments to the IRS, Payment Method can be any checking or savings account that has routing and account numbers and supports ACH.
However, for taxPayments submitted to an individual state the Payment Method must be a checking account that supports digital checks.
Below is an example of how to create a Payment Method that is associated with the user
you created in the previous step.
paymentMethod
for Tax PaymentsIRS Tax Payments may come from a
paymentMethod
whose "accountClass" is either "checking" or "savings"State Quarterly Tax Payments must be associated with a
paymentMethod
whose "accountClass" is "checking".
curl \
--request POST \
--url https://sandbox-api.withabound.com/v2/users/<<testUserId>>/paymentMethods \
--header 'Authorization: Bearer <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"paymentMethod": {
"accountNumber": "1234567890",
"routingNumber": "121042882",
"accountType": "personal",
"accountClass": "checking"
}
}'
const { default: Abound, Environment } = require("@withabound/node-sdk");
const abound = new Abound({
appId: "<<sandbox_app_id>>",
appSecret: "<<sandbox_app_secret>>",
environment: Environment.SANDBOX,
apiVersion: "v2",
});
(async () => {
const response = await abound.paymentMethods.create(
"<<testUserId>>",
{
accountNumber: "1234567890",
routingNumber: "121042882",
accountType: "personal",
accountClass: "checking",
}
);
console.log(response);
})();
import requests
url = "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/paymentMethods"
payload = {"paymentMethod": {
"accountNumber": "1234567890",
"routingNumber": "121042882",
"accountType": "personal",
"accountClass": "checking"
}}
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer <<apiKey>>"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
// import com.squareup.okhttp.*;
// import com.google.gson.JsonObject;
OkHttpClient client = new OkHttpClient();
JsonObject requestBody = new JsonObject();
JsonObject paymentMethod = new JsonObject();
paymentMethod.addProperty("accountNumber", "1234567890");
paymentMethod.addProperty("routingNumber", "121042882");
paymentMethod.addProperty("accountType", "personal");
paymentMethod.addProperty("accountClass", "checking");
requestBody.add("paymentMethod", paymentMethod);
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, requestBody.toString());
Request request = new Request.Builder()
.url("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/paymentMethods")
.post(body)
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer <<apiKey>>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"bytes"
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/paymentMethods"
var requestBody = []byte(`{
"paymentMethod": {
"accountNumber": "1234567890",
"routingNumber": "121042882",
"accountType": "personal",
"accountClass": "checking"
}
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer <<apiKey>>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
// using RestSharp;
var client = new RestClient("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/paymentMethods");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer <<apiKey>>");
request.AddJsonBody(new {
paymentMethod = new {
accountNumber = "1234567890",
routingNumber = "121042882",
accountType = "personal",
accountClass = "checking"
}
});
IRestResponse response = client.Execute(request);
require 'uri'
require 'net/http'
require 'openssl'
require 'json'
url = URI("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/paymentMethods")
requestBody = {
paymentMethod: {
accountNumber: '1234567890',
routingNumber: '121042882',
accountType: 'personal',
accountClass: 'checking'
}
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["Authorization"] = 'Bearer <<apiKey>>'
request.body = requestBody.to_json
response = http.request(request)
puts response.read_body
3. Create a Quarterly Tax Payment
The Quarterly Tax Payment represents the actual submission of money from the Payment Method to the IRS (or other government entity) on behalf of a User.
Determine the appropriate Tax Payment amount to submit as a Quarterly Tax Payment is easy by using the Taxes endpoint.
Submitting a Federal Tax Payment
Below is an example of the creation of a Quarterly Tax Payment for the User, where the funds are pulled from the Payment Method returned in the previous step and designated by the paymentMethodId
.
curl \
--request POST \
--url https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments \
--header 'Authorization: Bearer <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"taxPayment": {
"amount": 87.34,
"period": "Q2",
"year": "2020",
"entity": "IRS",
"paymentMethodId": "<<testPaymentMethodId>>"
}
}'
const { default: Abound, Environment } = require("@withabound/node-sdk");
const abound = new Abound({
appId: "<<sandbox_app_id>>",
appSecret: "<<sandbox_app_secret>>",
environment: Environment.SANDBOX,
apiVersion: "v2",
});
(async () => {
const response = await abound.taxPayments.create(
"<<testUserId>>",
{
amount: 87.34,
period: "Q2",
year: "2020",
entity: "IRS",
paymentMethodId:
"<<testPaymentMethodId>>",
}
);
console.log(response);
})();
import requests
url = "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments"
payload = {"taxPayment": {
"amount": 87.34,
"period": "Q2",
"year": "2020",
"entity": "IRS",
"paymentMethodId": "<<testPaymentMethodId>>"
}}
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer <<apiKey>>"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
// import com.squareup.okhttp.*;
// import com.google.gson.JsonObject;
OkHttpClient client = new OkHttpClient();
JsonObject requestBody = new JsonObject();
JsonObject taxPayment = new JsonObject();
taxPayment.addProperty("amount", 87.34);
taxPayment.addProperty("period", "Q2");
taxPayment.addProperty("year", "2020");
taxPayment.addProperty("entity", "IRS");
taxPayment.addProperty("paymentMethodId", "<<testPaymentMethodId>>");
requestBody.add("taxPayment", taxPayment);
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, requestBody.toString());
Request request = new Request.Builder()
.url("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments")
.post(body)
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer <<apiKey>>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"bytes"
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments"
var requestBody = []byte(`{
"taxPayment": {
"amount": 87.34,
"period": "Q2",
"year": "2020",
"entity": "IRS",
"paymentMethodId": "<<testPaymentMethodId>>"
}
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer <<apiKey>>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
// using RestSharp;
var client = new RestClient("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer <<apiKey>>");
request.AddJsonBody(new {
taxPayment = new {
amount = 87.34,
period = "Q2",
year = "2020",
entity = "IRS",
paymentMethodId = "<<testPaymentMethodId>>"
}
});
IRestResponse response = client.Execute(request);
require 'uri'
require 'net/http'
require 'openssl'
require 'json'
url = URI("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments")
requestBody = {
taxPayment: {
amount: 87.34,
period: 'Q2',
year: '2020',
entity: 'IRS',
paymentMethodId: '<<testPaymentMethodId>>'
}
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["Authorization"] = 'Bearer <<apiKey>>'
request.body = requestBody.to_json
response = http.request(request)
puts response.read_body
Submitting a State Tax Payment
Submitting a tax payment for a specific state is as simple as passing the two-character state code in the entity
field. The following code snippet provides an example of how to initiate a tax payment to California (notice the "entity": "CA").
State Tax Payment
amount
State tax payments require passing the
amount
as a whole number.
curl \
--request POST \
--url https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments \
--header 'Authorization: Bearer <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"taxPayment": {
"amount": 877,
"period": "Q3",
"year": "2020",
"entity": "CA",
"paymentMethodId": "<<testPaymentMethodId>>"
}
}'
const { default: Abound, Environment } = require("@withabound/node-sdk");
const abound = new Abound({
appId: "<<sandbox_app_id>>",
appSecret: "<<sandbox_app_secret>>",
environment: Environment.SANDBOX,
apiVersion: "v2",
});
(async () => {
const response = await abound.taxPayments.create(
"<<testUserId>>",
{
amount: 877,
period: "Q3",
year: "2020",
entity: "CA",
paymentMethodId:
"<<testPaymentMethodId>>",
}
);
console.log(response);
})();
import requests
url = "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments"
payload = {"taxPayment": {
"amount": 877,
"period": "Q3",
"year": "2020",
"entity": "CA",
"paymentMethodId": "<<testPaymentMethodId>>"
}}
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer <<apiKey>>"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
// import com.squareup.okhttp.*;
// import com.google.gson.JsonObject;
OkHttpClient client = new OkHttpClient();
JsonObject requestBody = new JsonObject();
JsonObject taxPayment = new JsonObject();
taxPayment.addProperty("amount", 877);
taxPayment.addProperty("period", "Q3");
taxPayment.addProperty("year", "2020");
taxPayment.addProperty("entity", "CA");
taxPayment.addProperty("paymentMethodId", "<<testPaymentMethodId>>");
requestBody.add("taxPayment", taxPayment);
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, requestBody.toString());
Request request = new Request.Builder()
.url("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments")
.post(body)
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer <<apiKey>>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"bytes"
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments"
var requestBody = []byte(`{
"taxPayment": {
"amount": 877,
"period": "Q3",
"year": "2020",
"entity": "CA",
"paymentMethodId": "<<testPaymentMethodId>>"
}
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer <<apiKey>>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
// using RestSharp;
var client = new RestClient("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer <<apiKey>>");
request.AddJsonBody(new {
taxPayment = new {
amount = 877,
period = "Q3",
year = "2020",
entity = "CA",
paymentMethodId = "<<testPaymentMethodId>>"
}
});
IRestResponse response = client.Execute(request);
require 'uri'
require 'net/http'
require 'openssl'
require 'json'
url = URI("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/taxPayments")
requestBody = {
taxPayment: {
amount: 877,
period: 'Q3',
year: '2020',
entity: 'CA',
paymentMethodId: '<<testPaymentMethodId>>'
}
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["Authorization"] = 'Bearer <<apiKey>>'
request.body = requestBody.to_json
response = http.request(request)
puts response.read_body
4. Monitor a Tax Payment
After your tax payment has been submitted, Abound uses webhooks to inform your backend when the tax payment has been updated. Read our Webhooks guide to learn more.
Updated 8 months ago