Introduction
Welcome to BlueTape Generic Connector API developer documentation.
Download API definition in OpenAPI 3.0 format from here.
Authentication
BlueTape API uses API keys to authenticate requests. BlueTape team will share the keys.
All headers needs to be sent against our endpoints to identify who is sending request to us and distinguish what actions needs to be made, otherwise will get HTTP 401 Unauthorized response from our backend.
| Header Key | Description |
|---|---|
X-BlueTape-Key |
Unique secret key to protect our API-s. |
X-Integration-AccountId |
Unique identifier received to track you in our system. |
Integration models
BlueTape provides API for the following operations:
create / update a customer
create / update a quote
create an invoice
return credit information for a customer
create / update projects
BlueTape expects the following API to be implemented on integrator side:
add payment to an invoice
authorization result ( required only when quotes are used for approval)
get all customers (optional)
There are two models supported by BlueTape:
A. Invoice only
Create an invoice in BlueTape
BlueTape notifies the customer
The customer selects the payment method and pays
For packages with 100% advance rate BlueTape marks the invoice as paid. For packages with 80% or 90% advance rate BlueTape marks that invoice as “Partially Paid” for the amount of advance payment. During the final payment BlueTape marks the invoice as paid.
B. Using quote for approval
Create a quote in BlueTape
BlueTape notifies the customer
Customer approves or reject the quote
BlueTape informs the integrator about the approval result
Create the invoice in BlueTape
For packages with 100% advance rate BlueTape marks the invoice as paid. For packages with 80% or 90% advance rate BlueTape marks that invoice as “Partially Paid” for the amount of advance payment. During the final payment BlueTape marks the invoice as paid.
Environments
Available environments and URLs.
| Environment | URL |
|---|---|
| Sandbox | https://beta-api.bluetape.com/genericBthubService |
| Production | https://api.bluetape.com/genericBthubService |
API
Version: 1.1.0
Companies
Company related functions.
Add new company
Endpoint
POST /integration/company
Creates a company.
HTTP Request
POST /integration/company
Company Object
{
"id": "a0b9cedc32ce",
"businessAddress": "1400 24th Ave, San Francisco, CA 94122, USA",
"businessPhoneNumber": "+11234567890",
"businessName": "Acme Inc.",
"businessDisplayName": "Acme",
"creditDetails": {
"accountType": "credit",
"accountCreationDate": "2023-03-09T00:10:20.300Z",
"pricePackage": "A",
"creditProvider": "inhouse",
"creditStatus": "active",
"creditAmount": 10000,
"outstandingAmount": 3000,
"overdueBalance": 500,
"agingOverdueBalance": [
{
"name": "1-30 days",
"daysFrom": 1,
"daysTo": 30,
"overdueBalance": 3000
}
],
"invoicesOverallAmount": 7000,
"invoicesOverallCount": 58,
"invoicesLastYearAmount": 5000,
"invoicesLastYearCount": 33,
"invoicesYearToDateAmount": 2000,
"invoicesYearToDateCount": 25,
"invoicesLastMonthAmount": 300,
"invoicesLastMonthCount": 5,
"invoicesMonthToDateAmount": 500,
"invoicesMonthToDateCount": 2,
"invoicesMonthlyAverageAmount": 888.33,
"invoicesMonthlyAverageCount": 5.7
},
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "409",
"reason": "Company already exists."
}
Request parameters
Company Object
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the company | true | string |
| businessName | Name of the company | true | string |
| businessAddress | The company address | true | string |
| businessPhoneNumber | Phone number of the company, usually is the line number | false | string |
| businessDisplayName | Company display name | false | string |
| creditDetails | The credit details | false | object |
| sourceModifiedDate | Date the record was last changed in the accounting service provider | true | datetime |
CreditDetails Object
| Name | Description | Required | Type |
|---|---|---|---|
| accountType | The account type (credit, cash) | false | string |
| accountCreationDate | The account creation date | false | datetime |
| pricePackage | The price package of business (eg. A) | false | string |
| creditProvider | The credit provider (inhouse, co) | false | string |
| creditStatus | The actual credit status (active, suspended, closed) | false | string |
| creditAmount | Overall credit amount | false | decimal |
| outstandingAmount | The outstanding credit amount (current balance) | false | decimal |
| overdueBalance | The overall overdue amount | false | decimal |
| agingOverdueBalance | Aging overdue balance | false | array |
| invoicesOverallAmount | Overall amount of invoices | false | decimal |
| invoicesOverallCount | Overall number of invoices | false | integer |
| invoicesLastYearAmount | Overall number of invoices | false | decimal |
| invoicesLastYearCount | Number of invoices last year. | false | integer |
| invoicesYearToDateAmount | Amount of invoices in this year until current date. | false | decimal |
| invoicesYearToDateCount | Number of invoices in this year until current date. | false | integer |
| invoicesLastMonthAmount | Amount of invoices last month. | false | decimal |
| invoicesLastMonthCount | Number of invoices last month. | false | integer |
| invoicesMonthToDateAmount | Amount of invoices in this month until current date. | false | decimal |
| invoicesMonthToDateCount | Number of invoices in this month until current date. | false | integer |
| invoicesMonthlyAverageAmount | Average amount of invoices per month. | false | decimal |
| invoicesMonthlyAverageCount | Average number of invoices per month. | false | decimal |
AgingOverdueBalance Object
| Name | Description | Required | Type |
|---|---|---|---|
| name | Description of aging range (eg. 1-30 days) | false | string |
| daysFrom | Aging range start days | true | integer |
| daysTo | Aging range end days. If not set, consider as infinite. | false | integer |
| overdueBalance | Overdue balance for this period. | true | decimal |
curl https://api.bluetape.com/genericBthubService/integration/company \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const company = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/company';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(company)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var company = new Company() {
...
};
var result = await "https://api.bluetape.com/genericBthubService/integration/company"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(company)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/company"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-company-data>
response = requests.post(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Update a company
Endpoint
PUT /integration/company/{id}
Updates a specified company.
HTTP Request
PUT /integration/company/{id}
Company Object
{
"businessAddress": "1400 24th Ave, San Francisco, CA 94122, USA",
"businessPhoneNumber": "+11234567890",
"businessName": "Acme Inc.",
"businessDisplayName": "Acme",
"creditDetails": {
"accountType": "credit",
"accountCreationDate": "2023-03-09T00:10:20.300Z",
"pricePackage": "A",
"creditProvider": "inhouse",
"creditStatus": "active",
"creditAmount": 10000,
"outstandingAmount": 3000,
"overdueBalance": 500,
"agingOverdueBalance": [
{
"name": "1-30 days",
"daysFrom": 1,
"daysTo": 30,
"overdueBalance": 3000
}
],
"invoicesOverallAmount": 7000,
"invoicesOverallCount": 58,
"invoicesLastYearAmount": 5000,
"invoicesLastYearCount": 33,
"invoicesYearToDateAmount": 2000,
"invoicesYearToDateCount": 25,
"invoicesLastMonthAmount": 300,
"invoicesLastMonthCount": 5,
"invoicesMonthToDateAmount": 500,
"invoicesMonthToDateCount": 2,
"invoicesMonthlyAverageAmount": 888.33,
"invoicesMonthlyAverageCount": 5.7
},
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Company not found."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the company to update | Yes | string |
Request parameters
Company Object
| Name | Description | Required | Type |
|---|---|---|---|
| businessName | Name of the company | true | string |
| businessAddress | The company address | true | string |
| businessPhoneNumber | Phone number of the company, usually is the line number | false | string |
| businessDisplayName | Company display name | false | string |
| creditDetails | The credit details | false | object |
| sourceModifiedDate | Date the record was last changed in the accounting service provider | true | datetime |
CreditDetails Object
| Name | Description | Required | Type |
|---|---|---|---|
| accountType | The account type (credit, cash) | false | string |
| accountCreationDate | The account creation date | false | datetime |
| pricePackage | The price package of business (eg. A) | false | string |
| creditProvider | The credit provider (inhouse, co) | false | string |
| creditStatus | The actual credit status (active, suspended, closed) | false | string |
| creditAmount | Overall credit amount | false | decimal |
| outstandingAmount | The outstanding credit amount (current balance) | false | decimal |
| overdueBalance | The overall overdue amount | false | decimal |
| agingOverdueBalance | Aging overdue balance | false | array |
| invoicesOverallAmount | Overall amount of invoices | false | decimal |
| invoicesOverallCount | Overall number of invoices | false | integer |
| invoicesLastYearAmount | Overall number of invoices | false | decimal |
| invoicesLastYearCount | Number of invoices last year. | false | integer |
| invoicesYearToDateAmount | Amount of invoices in this year until current date. | false | decimal |
| invoicesYearToDateCount | Number of invoices in this year until current date. | false | integer |
| invoicesLastMonthAmount | Amount of invoices last month. | false | decimal |
| invoicesLastMonthCount | Number of invoices last month. | false | integer |
| invoicesMonthToDateAmount | Amount of invoices in this month until current date. | false | decimal |
| invoicesMonthToDateCount | Number of invoices in this month until current date. | false | integer |
| invoicesMonthlyAverageAmount | Average amount of invoices per month. | false | decimal |
| invoicesMonthlyAverageCount | Average number of invoices per month. | false | decimal |
AgingOverdueBalance Object
| Name | Description | Required | Type |
|---|---|---|---|
| name | Description of aging range (eg. 1-30 days) | false | string |
| daysFrom | Aging range start days | true | integer |
| daysTo | Aging range end days. If not set, consider as infinite. | false | integer |
| overdueBalance | Overdue balance for this period. | true | decimal |
curl https://api.bluetape.com/genericBthubService/integration/company/<companyId> \
-X PUT \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const company = { ... };
const url = `https://api.bluetape.com/genericBthubService/integration/company/${company.Id}`;
const options = {
method: 'PUT',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(company)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var companyId = "a0b9cedc32ce";
var company = <your-company-to-update>;
var result = await "https://api.bluetape.com/genericBthubService/integration/company"
.AppendPathSegment(companyId)
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PutJsonAsync(company)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
companyId = "a0b9cedc32ce"
url = f'https://api.bluetape.com/genericBthubService/integration/company/{companyId}'
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-company-data>
response = requests.put(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 202 | Accepted, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Link company to a customer
Endpoint
POST /integration/company/{id}/customer
This endpoint links specified company to a customer.
HTTP Request
POST /integration/company/{id}/customer
Customer
{
"customerId": "7ba4877cbf52"
}
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Customer not found."
}
Query Parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the company for attach to. | Yes | string |
Request parameters
| Name | Description | Required | Type |
|---|---|---|---|
| customerId | Identifier of the customer which is attaching to company. | Yes | string |
curl https://api.bluetape.com/genericBthubService/integration/company/<id>/customer \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-d "@request.json"
import fetch from 'node-fetch';
const companyId = 'a0b9cedc32ce';
const url = `https://api.bluetape.com/genericBthubService/integration/company/${companyId}/customer`;
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
customerId: '7ba4877cbf52'
})
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var companyId = "a0b9cedc32ce";
var url = $"https://api.bluetape.com/genericBthubService/integration/company/{companyId}/customer";
var result = await url
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(new() { customerId = "7ba4877cbf52" })
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
companyId = "a0b9cedc32ce"
customerId = "7ba4877cbf52"
url = f'https://api.bluetape.com/genericBthubService/integration/{companyId}/customer'
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
body = {
"customerId": "7ba4877cbf52"
}
response = requests.post(url, headers=headers, body=body)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Customers
Customer related functions.
Create a customer
Endpoint
POST /integration/customer
Creates a customer.
HTTP Request
POST /integration/customer
Customer Object
{
"id": "dc506b22c7fa",
"firstName": "John",
"lastName": "Doe",
"emailAddress": "john@doe.com",
"cellPhoneNumber": "+11234567890",
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "409",
"reason": "Customer already exists."
}
Request parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the customer | true | string |
| firstName | First name of the main contact for the customer / company | true | string |
| lastName | Last name of the main contact for the customer / company | true | string |
| emailAddress | Email address of the main contact for the customer / company. This email address will be used to send the notifications out | true | string |
| cellPhoneNumber | Cellphone number of the main contact for the customer / company. This phone number will be used to send the notifications out | true | string |
| sourceModifiedDate | Date the record was last changed in the accounting service provider | true | datetime |
curl https://api.bluetape.com/genericBthubService/integration/customer \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const customer = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/customer';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(customer)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var content = new Customer() {
...
};
var result = await "https://api.bluetape.com/genericBthubService/integration/customer"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(content)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/customer"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-customer-data>
response = requests.post(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Update a customer
Endpoint
PUT /integration/customer/{id}
Updates a specified customer
HTTP Request
PUT /integration/customer/{id}
Customer Object
{
"firstName": "John",
"lastName": "Doe",
"emailAddress": "john@doe.com",
"cellPhoneNumber": "+11234567890",
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Customer not found."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the customer to update | Yes | string |
Request parameters
| Name | Description | Required | Type |
|---|---|---|---|
| firstName | First name of the main contact for the customer / company | true | string |
| lastName | Last name of the main contact for the customer / company | true | string |
| emailAddress | Email address of the main contact for the customer / company. This email address will be used to send the notifications out | true | string |
| cellPhoneNumber | Cellphone number of the main contact for the customer / company. This phone number will be used to send the notifications out | true | string |
| sourceModifiedDate | Date the record was last changed in the accounting service provider | true | datetime |
curl https://api.bluetape.com/genericBthubService/integration/customer \
-X PUT \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const customer = { ... };
const url = `https://api.bluetape.com/genericBthubService/integration/customer/${customer.Id}`;
const options = {
method: 'PUT',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(customer)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var customerId = "dc506b22c7fa";
var content = <your-customer-to-update>;
var result = await "https://api.bluetape.com/genericBthubService/integration/customer"
.AppendPathSegment(customerId)
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PutJsonAsync(content)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
customerId = "dc506b22c7fa"
url = f'https://api.bluetape.com/genericBthubService/integration/customer/{customerId}'
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-customer-data>
response = requests.put(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 202 | Accepted, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Get customer credit info
Endpoint
GET /integration/customer/{id}/creditInfo
Gets specified customer's actual credit information.
HTTP Request
GET /integration/customer/{id}/creditInfo
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the customer to get credit information | Yes | string |
Successful response, Credit Info Object
{
"limit": 1000,
"balance": 5000,
"pastDueAmount": 450
}
Erroneous response
{
"code": "404",
"reason": "Customer not found."
}
curl https://api.bluetape.com/genericBthubService/integration/customer/<customerId>/creditInfo \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
import fetch from 'node-fetch';
const customerId = 'dc506b22c7fa';
const url = `https://api.bluetape.com/genericBthubService/integration/customer/${customerId}/creditInfo`;
const options = {
method: 'GET',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var customerId = "dc506b22c7fa";
var url = $"https://api.bluetape.com/genericBthubService/integration/customer/{customerId}/creditInfo";
var result = await url
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.GetJsonAsync<CreditInfo>();
import requests
customerId = "dc506b22c7fa"
url = f'https://api.bluetape.com/genericBthubService/integration/customer/{customerId}/creditInfo'
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
print(response.text)
Response parameters
Credit Information Object
| Name | Description | Type |
|---|---|---|
| limit | The company approved credit limit | decimal |
| balance | Available balance for the company | decimal |
| pastDueAmount | Total past due amount for the company | decimal |
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Invoices
Invoice functions.
Create new invoice
Endpoint
POST /integration/invoice
Creates an invoice.
HTTP Request
POST /integration/invoice
Invoice Object
{
"id": "2eb1acd98a86",
"invoiceNumber": "INV/00003/2023",
"customerId": "7ba4877cbf52",
"invoiceDate": "2023-01-04",
"dueDate": "2023-01-12",
"expirationDate": "2023-01-12",
"subTotal": 1000,
"totalAmount": 1100,
"taxAmount": 100,
"amountDue": 1100,
"lines": [
{
"description": "Item 1",
"unitAmount": 500,
"quantity": 2,
"subTotal": 1000,
"taxAmount": 100,
"totalAmount": 1100
}
],
"quoteRefNumber": "QUOT/0567/2022",
"quoteId": "cbabdcfecfeb",
"status": "open",
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "63168de0cbee"
}
Erroneous response
{
"code": "409",
"reason": "Invoice already exists, invoice number: {invoiceNumber}"
}
Request parameters
Invoice Object
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the invoice. | true | string |
| invoiceNumber | Friendly reference for the invoice. If available, this appears in the file name of invoice attachments. | true | string |
| customerId | Reference to the customer the invoice has been issued to. | true | string |
| invoiceDate | Date of the invoice as recorded in the accounting service provider. | true | string |
| dueDate | Date the invoice is due to be paid by. | true | string |
| expirationDate | Expiration date of the invoice. | true | string |
| subTotal | Value of the invoice, including discounts and excluding tax. | true | decimal |
| totalAmount | Amount of the invoice, inclusive of tax. | true | decimal |
| taxAmount | Any tax applied to the invoice amount. | true | decimal |
| amountDue | Amount outstanding on the invoice. | true | decimal |
| lines | An array of invoice lines. | false | array |
| quoteRefNumber | Reference to the quote. | false | string |
| quoteId | Reference to the quote. | false | string |
| status | Status of the invoice. Enum: open, draft, paid, partiallyPaid, unknown, void | true | string |
| sourceModifiedDate | Date the record was last changed in the accounting service provider. | true | string |
Invoice Line Object
| Name | Description | Required | Type |
|---|---|---|---|
| description | Friendly name of the goods or services received. | false | string |
| unitAmount | Price of each unit of goods or services. | true | decimal |
| quantity | Number of units of goods or services. | true | integer |
| subTotal | Amount of the line, inclusive of discounts but exclusive of tax. | true | decimal |
| taxAmount | Amount of tax for the line. | true | decimal |
| totalAmount | Total amount of the line, inclusive of discounts and tax. | true | decimal |
curl https://api.bluetape.com/genericBthubService/integration/invoice \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const invoice = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/invoice';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(invoice)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var invoice = new Invoice() {
...
};
var result = await "https://api.bluetape.com/genericBthubService/integration/invoice"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(invoice)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-invoice-data>
response = requests.post(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Update an invoice
Endpoint
PUT /integration/invoice/{id}
Updates an invoice.
HTTP Request
PUT /integration/invoice/{id}
Invoice Object
{
"invoiceNumber": "INV/00003/2023",
"customerId": "7ba4877cbf52",
"invoiceDate": "2023-01-04",
"dueDate": "2023-01-12",
"expirationDate": "2023-01-12",
"subTotal": 1000,
"totalAmount": 1100,
"taxAmount": 100,
"amountDue": 1100,
"lines": [
{
"description": "Item 1",
"unitAmount": 500,
"quantity": 2,
"subTotal": 1000,
"taxAmount": 100,
"totalAmount": 1100
}
],
"status": "open",
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "63168de0cbee"
}
Erroneous response
{
"code": "409",
"reason": ""
}
Request parameters
Invoice Object
| Name | Description | Required | Type |
|---|---|---|---|
| invoiceNumber | Friendly reference for the invoice. If available, this appears in the file name of invoice attachments. | true | string |
| customerId | Reference to the customer the invoice has been issued to. | true | string |
| invoiceDate | Date of the invoice as recorded in the accounting service provider. | true | string |
| dueDate | Date the invoice is due to be paid by. | true | string |
| expirationDate | Expiration date of the invoice. | true | string |
| subTotal | Value of the invoice, including discounts and excluding tax. | true | decimal |
| totalAmount | Amount of the invoice, inclusive of tax. | true | decimal |
| taxAmount | Any tax applied to the invoice amount. | true | decimal |
| amountDue | Amount outstanding on the invoice. | true | decimal |
| lines | An array of invoice lines. | false | array |
| status | Status of the invoice. Enum: open, draft, paid, partiallyPaid, unknown, void | true | string |
| sourceModifiedDate | Date the record was last changed in the accounting service provider. | true | string |
Invoice Line Object
| Name | Description | Required | Type |
|---|---|---|---|
| description | Friendly name of the goods or services received. | false | string |
| unitAmount | Price of each unit of goods or services. | true | decimal |
| quantity | Number of units of goods or services. | true | integer |
| subTotal | Amount of the line, inclusive of discounts but exclusive of tax. | true | decimal |
| taxAmount | Amount of tax for the line. | true | decimal |
| totalAmount | Total amount of the line, inclusive of discounts and tax. | true | decimal |
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId> \
-X PUT \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const invoice = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>';
const options = {
method: 'PUT',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(invoice)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var invoice = new Invoice() {
...
};
var result = await "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PutJsonAsync(invoice)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-invoice-data>
response = requests.put(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 202 | Accepted, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Cancel an invoice
Endpoint
PUT /integration/invoice/{id}/cancel
Cancels an invoice.
HTTP Request
PUT /integration/invoice/{id}/cancel
Request body
{ }
Successful response
{
}
Erroneous response
{
"code": "409",
"reason": "Invoice already canceled."
}
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/cancel \
-X PUT \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json"
import fetch from 'node-fetch';
const url = 'https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/cancel';
const options = {
method: 'PUT',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PutJsonAsync(null)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/cancel"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.put(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 202 | Accepted, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Link invoice to project
Endpoint
POST /integration/invoice/{id}/project
Links invoice to a project.
HTTP Request
POST /integration/invoice/{id}/project/{projectId}
Project Link Object
{
}
Successful response
{
}
Erroneous response
{
"code": "404",
"reason": "Invoice not exists."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the invoice to attach | Yes | string |
| projectId | Identifier of the project which is attaching to invoice | Yes | string |
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/project/<projectId> \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json"
import fetch from 'node-fetch';
const url = 'https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/project/<projectId>';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/invoice/{invoiceId}/project/{projectId}"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(null)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/project/<projectId>"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Unlink invoice to from project
Endpoint
DELETE /integration/invoice/{id}/project/{projectId}
Unlinks invoice from a project.
HTTP Request
DELETE /integration/invoice/{id}/project/{projectId}
Successful response
{
}
Erroneous response
{
"code": "404",
"reason": "Invoice not exists."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the invoice to unattach | Yes | string |
| projectId | Identifier of the project which is unattaching from invoice | Yes | string |
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/project/<projectId> \
-X DELETE \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
import fetch from 'node-fetch';
const project = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/project/<projectId>';
const options = {
method: 'DELETE',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/invoice/{invoiceId}/project/{projectId}"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.DeleteAsync();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/project/<projectId>"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.delete(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Download file of an invoice
Endpoint
GET /integration/invoice/{id}/file
Downloads file of an invoice.
HTTP Request
GET /integration/invoice/{id}/file
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the invoice | Yes | string |
Successful response, binary content
Erroneous response
{
"code": "404",
"reason": "Invoice not found."
}
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/file \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
import fetch from 'node-fetch';
const invoiceId = 'b22c7fadc506';
const url = `https://api.bluetape.com/genericBthubService/integration/invoice/${invoiceId}/file`;
const options = {
method: 'GET',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/pdf'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var invoiceId = "b22c7fadc506";
var url = $"https://api.bluetape.com/genericBthubService/integration/invoice/{invoiceId}/file";
var resultStream = await url
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/pdf")
.GetStreamAsync();
import requests
invoiceId = "b22c7fadc506"
url = f'https://api.bluetape.com/genericBthubService/integration/invoice/{invoiceId}/file'
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/pdf"
}
response = requests.get(url, headers=headers, allow_redirects=True)
open('filename.pdf', 'wb').write(r.content)
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Upload or replace file of an invoice
Endpoint
POST /integration/invoice/{id}/file
Uploads or replaces file of an invoice.
HTTP Request
POST /integration/invoice/{id}/file
Use Content-Type: application/pdf header value.
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the invoice | Yes | string |
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Invoice not found."
}
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/file \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/pdf" \
-F "file=@C:\Users\User\Desktop\Invoice.pdf"
import fetch, {
Blob,
blobFrom,
blobFromSync,
File,
fileFrom,
fileFromSync,
} from 'node-fetch'
const mimetype = 'application/pdf'
const blob = fileFromSync('./Invoice.pdf', mimetype)
const invoiceId = "5ec12449be5a";
const url = `https://api.bluetape.com/genericBthubService/integration/invoice/${invoiceId}/file`
const response = await fetch(url, { method: 'POST', body: blob })
const data = await response.json()
console.log(data)
using Flurl.Http;
var invoiceId = "5ec12449be5a";
var url = $"https://api.bluetape.com/genericBthubService/integration/invoice/{invoiceId}/file";
var fileName = @"C:\Users\User\Desktop\Invoice.pdf";
var result = await url
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/pdf")
.PostMultipartAsync(part => part
.AddFile("file", stream, fileName)
);
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/file"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/pdf"
}
file = {'file': open('C:\Users\User\Desktop\Invoice.pdf','rb')}
response = requests.post(url, headers=headers, files=file)
Responses
| Code | Description |
|---|---|
| 204 | No content |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Remove file of an invoice
Endpoint
DELETE /integration/invoice/{id}/file
Downloads file of an invoice.
HTTP Request
DELETE /integration/invoice/{id}/file
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the invoice | Yes | string |
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Invoice not found."
}
curl https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/file \
-X DELETE \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
import fetch from 'node-fetch';
const invoiceId = '27be905508e7';
const url = `https://api.bluetape.com/genericBthubService/integration/invoice/${invoiceId}/file`;
const options = {
method: 'DELETE',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/invoice/{invoiceId}/file"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.DeleteAsync();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/invoice/<invoiceId>/file"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.delete(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Quotes
Endpoint
POST /integration/quote
Quotes functions.
Create new quote
Creates a new quote.
HTTP Request
POST /integration/quote
Quote Object
{
"id": "cbabdcfecfeb",
"quoteNumber": "QUOT/0567/2022",
"customerId": "7ba4877cbf52",
"quoteDate": "2023-01-04",
"dueDate": "2023-01-12",
"expirationDate": "2023-01-12",
"subTotal": 1000,
"totalAmount": 1100,
"taxAmount": 100,
"lines": [
{
"description": "Item 1",
"unitAmount": 500,
"quantity": 2,
"subTotal": 1000,
"taxAmount": 100,
"totalAmount": 1100
}
],
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "9d86480a5a5d"
}
Erroneous response
{
"code": "409",
"reason": "Quote already exists."
}
Request parameters
Quote Object
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the quote. | true | string |
| quoteNumber | Friendly reference for the quote. If available, this appears in the file name of quote attachments. | true | string |
| customerId | Reference to the customer the quote has been issued to. | true | string |
| quoteDate | Date of the quote as recorded in the accounting service provider. | true | string |
| dueDate | Date the quote is due to be paid by. | true | string |
| expirationDate | Expiration date of the quote. | true | string |
| subTotal | Value of the quote, including discounts and excluding tax. | true | decimal |
| totalAmount | Amount of the quote, inclusive of tax. | true | decimal |
| taxAmount | Any tax applied to the quote amount. | true | decimal |
| lines | An array of quote lines. | false | array |
| sourceModifiedDate | Date the record was last changed in the accounting service provider. | true | string |
Quote Line Object
| Name | Description | Required | Type |
|---|---|---|---|
| description | Friendly name of the goods or services received. | false | string |
| unitAmount | Price of each unit of goods or services. | true | decimal |
| quantity | Number of units of goods or services. | true | integer |
| subTotal | Amount of the line, inclusive of discounts but exclusive of tax. | true | decimal |
| taxAmount | Amount of tax for the line. | true | decimal |
| totalAmount | Total amount of the line, inclusive of discounts and tax. | true | decimal |
curl https://api.bluetape.com/genericBthubService/integration/quote \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const quote = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/quote';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(quote)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var quote = new Quote() {
...
};
var result = await "https://api.bluetape.com/genericBthubService/integration/quote"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(quote)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/quote"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-quote-data>
response = requests.post(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Update a quote
Endpoint
PUT /integration/quote/{id}
This endpoint updates a specified quote.
HTTP Request
PUT /integration/quote/{id}
Quote Object
{
"quoteNumber": "QUOT/0567/2022",
"customerId": "7ba4877cbf52",
"quoteDate": "2023-01-04",
"dueDate": "2023-01-12",
"expirationDate": "2023-01-12",
"subTotal": 1000,
"totalAmount": 1100,
"taxAmount": 100,
"lines": [
{
"description": "Item 1",
"unitAmount": 500,
"quantity": 2,
"subTotal": 1000,
"taxAmount": 100,
"totalAmount": 1100
}
],
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "9d86480a5a5d"
}
Erroneous response
{
"code": "404",
"reason": "Quote not found."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the quote to update | Yes | string |
Request parameters
Quote Object
| Name | Description | Required | Type |
|---|---|---|---|
| quoteNumber | Friendly reference for the quote. If available, this appears in the file name of quote attachments. | true | string |
| customerId | Reference to the customer the quote has been issued to. | true | string |
| quoteDate | Date of the quote as recorded in the accounting service provider. | true | string |
| dueDate | Date the quote is due to be paid by. | true | string |
| expirationDate | Expiration date of the quote. | true | string |
| subTotal | Value of the quote, including discounts and excluding tax. | true | decimal |
| totalAmount | Amount of the quote, inclusive of tax. | true | decimal |
| taxAmount | Any tax applied to the quote amount. | true | decimal |
| lines | An array of quote lines. | false | array |
| sourceModifiedDate | Date the record was last changed in the accounting service provider. | true | string |
Quote Line Object
| Name | Description | Required | Type |
|---|---|---|---|
| description | Friendly name of the goods or services received. | false | string |
| unitAmount | Price of each unit of goods or services. | true | decimal |
| quantity | Number of units of goods or services. | true | integer |
| subTotal | Amount of the line, inclusive of discounts but exclusive of tax. | true | decimal |
| taxAmount | Amount of tax for the line. | true | decimal |
| totalAmount | Total amount of the line, inclusive of discounts and tax. | true | decimal |
curl https://api.bluetape.com/genericBthubService/integration/quote/<quoteId> \
-X PUT \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const quote = { ... };
const url = `https://api.bluetape.com/genericBthubService/integration/quote/${quote.Id}`;
const options = {
method: 'PUT',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(quote)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var quoteId = "cbabdcfecfeb";
var quote = <your-quote-to-update>;
var result = await "https://api.bluetape.com/genericBthubService/integration/quote"
.AppendPathSegment(quoteId)
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PutJsonAsync(quote)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
quoteId = "cbabdcfecfeb"
url = "https://api.bluetape.com/genericBthubService/integration/quote/{quoteId}"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-quote-data>
response = requests.put(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 202 | Accepted, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Link quote to project
Endpoint
POST /integration/quote/{id}/project/{projectId}
Links quote to a project.
HTTP Request
POST /integration/quote/{id}/project/{projectId}
Project Link Object
{
}
Successful response
{
}
Erroneous response
{
"code": "404",
"reason": "Quote not exists."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the quote to attach | Yes | string |
| projectId | Identifier of the project which is attaching to quote | Yes | string |
curl https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/project/<projectId> \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json"
import fetch from 'node-fetch';
const url = 'https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/project/<projectId>';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/quote/{quoteId}/project/{projectId}"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(null)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/project/<projectId>"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Unlink quote to from project
Endpoint
DELETE /integration/quote/{id}/project/{projectId}
Unlinks quote from a project.
HTTP Request
DELETE /integration/quote/{id}/project/{projectId}
Successful response
{
}
Erroneous response
{
"code": "404",
"reason": "Quote not exists."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the quote to unattach | Yes | string |
| projectId | Identifier of the project which is unattaching from quote | Yes | string |
curl https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/project/<projectId> \
-X DELETE \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
import fetch from 'node-fetch';
const project = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/project/<projectId>';
const options = {
method: 'DELETE',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/quote/{quoteId}/project/{projectId}"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.DeleteAsync();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/project/<projectId>"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.delete(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Download file of a quote
Endpoint
GET /integration/quote/{id}/file
Downloads file of a quote.
HTTP Request
GET /integration/quote/{id}/file
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the quote | Yes | string |
Successful response, binary content
Erroneous response
{
"code": "404",
"reason": "Quote not found."
}
curl https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/file \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
import fetch from 'node-fetch';
const quoteId = 'b22c7fadc506';
const url = `https://api.bluetape.com/genericBthubService/integration/quote/${quoteId}/file`;
const options = {
method: 'GET',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/pdf'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var quoteId = "b22c7fadc506";
var url = $"https://api.bluetape.com/genericBthubService/integration/quote/{quoteId}/file";
var resultStream = await url
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/pdf")
.GetStreamAsync();
import requests
quoteId = "b22c7fadc506"
url = f'https://api.bluetape.com/genericBthubService/integration/quote/{quoteId}/file'
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/pdf"
}
response = requests.get(url, headers=headers, allow_redirects=True)
open('filename.pdf', 'wb').write(r.content)
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Upload or replace file of a quote
Endpoint
POST /integration/quote/{id}/file
Uploads or replaces file of a quote.
HTTP Request
POST /integration/quote/{id}/file
Use Content-Type: application/pdf header value.
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the quote | Yes | string |
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Quote not found."
}
curl https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/file \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/pdf" \
-F "file=@C:\Users\User\Desktop\Quote.pdf"
import fetch, {
Blob,
blobFrom,
blobFromSync,
File,
fileFrom,
fileFromSync,
} from 'node-fetch'
const mimetype = 'application/pdf'
const blob = fileFromSync('./Quote.pdf', mimetype)
const quoteId = "5ec12449be5a";
const url = `https://api.bluetape.com/genericBthubService/integration/quote/${quoteid}/file`
const response = await fetch(url, { method: 'POST', body: blob })
const data = await response.json()
console.log(data)
using Flurl.Http;
var quoteId = "5ec12449be5a";
var url = $"https://api.bluetape.com/genericBthubService/integration/quote/{quoteid}/file";
var fileName = @"C:\Users\User\Desktop\Quote.pdf";
var result = await url
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/pdf")
.PostMultipartAsync(part => part
.AddFile("file", stream, fileName)
);
import requests
url = "https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/file"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/pdf"
}
file = {'file': open('C:\Users\User\Desktop\Quote.pdf','rb')}
response = requests.post(url, headers=headers, files=file)
Responses
| Code | Description |
|---|---|
| 204 | No content |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Remove file of a quote
Endpoint
DELETE /integration/quote/{id}/file
Downloads file of a quote.
HTTP Request
DELETE /integration/quote/{id}/file
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the quote | Yes | string |
Successful response
{
"blueTapeId": "fb5637b2e5f3"
}
Erroneous response
{
"code": "404",
"reason": "Quote not found."
}
curl https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/file \
-X DELETE \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
import fetch from 'node-fetch';
const quoteId = '27be905508e7';
const url = `https://api.bluetape.com/genericBthubService/integration/quote/${quoteId}/file`;
const options = {
method: 'DELETE',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
}
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var result = await "https://api.bluetape.com/genericBthubService/integration/quote/{quoteId}/file"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.DeleteAsync();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/quote/<quoteId>/file"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
response = requests.delete(url, headers=headers)
print(response.text)
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Invoice & Quote Error Codes
| Code | Description |
|---|---|
| project_does_not_exist | update or link non existing projectId |
| project_already_exist | create project with existing projectId |
| invoice_does_not_exist | update or link non existing invoiceId |
| invoice_already_linked_to_project | invoiceId already linked to project and can not be linked twice |
| customer_does_not_exist | customer update or quote/invoice create or update operations made for non synchronized customerId. You should synchronize customer before invoice or quote |
| invoice_payment_operation_exist | invoice can not be changed due to existing operation. Happens for Invoice Update/Cancel |
| customer_of_invoice_is_draft | customer saved as draft. (Customer cellphone and email is empty or invalid. So we can not send any notification about invoice or quote) |
| cant_set_new_customer_for_invoice | Once quote or invoice created, you can not assign invoice to new customer |
| invoice_can_not_be_updated_due_date | Once invoice or quote has expired DueDate, they can not be updated anymore |
| invoice_already_cancelled | Invoice can not be updated after cancelling |
| invoice_can_be_updated_only_in_placed_status | Invoice can be update only when there is no transactions or action from user |
| document_invalid_data | one parameters from invoice or quote request has invalid value or empty |
| invoice_already_exist | invoice with provided InvoiceId already exist |
| quote_reference_does_not_exist | QuoteId and QuoteRefId provided with during invoice creation does not exist. Please sync quote with such ids |
| quote_dismissed | Invoice can not be updated. Quote referenced to this invoice is dismissed by customer or cancelled |
| quote_amount_not_equal_to_invoice | Total amount of quote should be equal to invoice total amount |
| quote_already_referenced_to_invoice | Quote ids provided in request already referenced to another invoice and can not be referenced to another one |
| loan_application_not_approved | Loan application was not approved for quote linked to its invoice |
| invoice_amount_is_bigger_then_approved | Total amount of invoice is bigger then approved total amount of loan application that was approved for referenced quote. Invoice total amount should be equal or less then total amount of it’s quote |
| customer_invalid_data | one of customer or company fields has invalid data |
| customer_company_change | Once customer is already belong to one company. You can add him to another company. |
| customer_already_registered | customer is already registered and you can not do action like add him to company. |
| company_customer_does_not_exist | You can not add customer to company which is not synchronized before. |
| customer_with_phone_or_email_already_exist | Customer with such phone or email already added |
| quote_already_exist | Quote with such id already added |
| quote_does_not_exist | Can not update non existing quote. Try to create it instead of update. |
| customer_reference | Can not set new customer for existing quote |
| quote_update_rejected | Quote can not be updated once invoice referenced to this quote in already created |
| quote_and_loan_total_amount | Can not update quote. Total amount of quote should not be bigger then approved total amount of loan application. |
Projects
Endpoint
POST /integration/project
Projects functions.
Create new project
Creates a new project.
HTTP Request
POST /integration/project
Project Object
{
"id": "a0b9cedc32ce",
"name": "A new huge building",
"address": "285 Fulton St, New York, NY 10007, United States",
"creditAmount": 10000,
"status": "active",
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "9d86480a5a5d"
}
Erroneous response
{
"code": "409",
"reason": "Project already exists."
}
Request parameters
Project Object
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier for the project. | true | string |
| name | Project name. | false | string |
| address | Project address. | false | string |
| creditAmount | The total amount of contracted credit for the project. | false | decimal |
| status | Actual status. (active, inactive) | false | string |
| sourceModifiedDate | Date the record was last changed in the accounting service provider | true | datetime |
curl https://api.bluetape.com/genericBthubService/integration/project \
-X POST \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const project = { ... };
const url = 'https://api.bluetape.com/genericBthubService/integration/project';
const options = {
method: 'POST',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(project)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var project = new Project() {
...
};
var result = await "https://api.bluetape.com/genericBthubService/integration/project"
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PostJsonAsync(project)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
url = "https://api.bluetape.com/genericBthubService/integration/project"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-project-data>
response = requests.post(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 201 | Created, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Update a project
Endpoint
PUT /integration/project/{id}
This endpoint updates a specified project.
HTTP Request
PUT /integration/project/{id}
Project Object
{
"name": "A new huge building",
"address": "285 Fulton St, New York, NY 10007, United States",
"creditAmount": 10000,
"status": "active",
"sourceModifiedDate": "2023-01-04T09:47:57.477Z"
}
Successful response
{
"blueTapeId": "9d86480a5a5d"
}
Erroneous response
{
"code": "404",
"reason": "Project not found."
}
Query parameters
| Name | Description | Required | Type |
|---|---|---|---|
| id | Identifier of the project to update | Yes | string |
Request parameters
Project Object
| Name | Description | Required | Type |
|---|---|---|---|
| name | Project name. | false | string |
| address | Project address. | false | string |
| creditAmount | The total amount of contracted credit for the project. | false | decimal |
| status | Actual status. (active, inactive) | false | string |
| sourceModifiedDate | Date the record was last changed in the accounting service provider | true | datetime |
curl https://api.bluetape.com/genericBthubService/integration/project/<projectId> \
-X PUT \
-H "X-BlueTape-Key: <your-key>" \
-H "X-Integration-AccountId: <your-account-id>" \
-H "Content-Type: application/json" \
-d "@request.json"
import fetch from 'node-fetch';
const project = { ... };
const url = `https://api.bluetape.com/genericBthubService/integration/project/${project.Id}`;
const options = {
method: 'PUT',
headers: {
'X-BlueTape-Key': '<your-key>',
'X-Integration-AccountId': '<your-account-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify(project)
};
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
using Flurl.Http;
var projectId = "cbabdcfecfeb";
var project = <your-project-to-update>;
var result = await "https://api.bluetape.com/genericBthubService/integration/project"
.AppendPathSegment(projectId)
.WithHeader("X-BlueTape-Key", "<your-key>")
.WithHeader("X-Integration-AccountId", "<your-account-id>")
.WithHeader("Content-Type", "application/json")
.PutJsonAsync(project)
.ReceiveJson<BlueTapeIntegrationResult>();
import requests
projectId = "cbabdcfecfeb"
url = "https://api.bluetape.com/genericBthubService/integration/project/{projectId}"
headers = {
"X-BlueTape-Key": "<your-key>",
"X-Integration-AccountId": "<your-account-id>",
"Content-Type": "application/json"
}
data = <your-project-data>
response = requests.put(url, headers=headers, data=data)
print(response.text)
Responses
| Code | Description |
|---|---|
| 202 | Accepted, successful operation |
| 400 | Invalid request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Unexpected error |
Webhooks
Approve a quote
Example endpoint on your side
POST /webhook/quote/approval
BlueTape sends quote approvals to this endpoint.
HTTP Request
POST /webhook/quote/approval
Request parameters
Quote Appoval Object
{
"quoteId": "a0b9cedc32ce",
"result": "Approved",
"creditInfo": {
"limit": 1000,
"balance": 5000,
"pastDueAmount": 450
}
}
| Name | Description | Required | Type |
|---|---|---|---|
| quoteId | Unique identifier of the quote to be approved. | true | string |
| result | Approval result. Enum: Approved, Rejected | true | string |
| creditInfo | The company credit information. | true | credit info object |
Responses
Pay an invoice
Example endpoint on your side
POST /webhook/invoice/payment
BlueTape sends invoice payments to this endpoint.
HTTP Request
POST /webhook/invoice/payment
Request parameters
Invoice Payment Object
{
"invoiceId": "6c8f90e43e13",
"amount": 1100,
"fee": 0,
"paymentMethod": "card",
"status": "Paid"
}
| Name | Description | Required | Type |
|---|---|---|---|
| invoiceId | Unique identifier of the invoice. | true | string |
| amount | Paid amount. | true | decimal |
| fee | Fee amount. | true | decimal |
| paymentMethod | The applied payment method. Can be card, ach and loan. | true | string |
| status | Invoice payment status. Enum: Paid, PartiallyPaid | true | string |
Responses
| Code | Description |
|---|---|
| 200 | Successful operation |
| 400 | Invalid request |
Errors
The BlueTape Generic Integration API uses the following error codes:
| Error Code | Meaning |
|---|---|
400 |
Bad Request - Your request is invalid. |
401 |
Unauthorized - Your API key might be wrong. |
404 |
Not Found - The specified api endpoint could not be found. |
405 |
Method Not Allowed - You tried to access our api with an invalid method. |
429 |
Too Many Requests - Rate limiting error. Please slow down. |
500 |
Internal Server Error - We had a problem with our server. Try again later. |
503 |
Service Unavailable - We're temporarily offline for maintenance. Please try again later. |