NAV
shell javascript csharp python

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:

BlueTape expects the following API to be implemented on integrator side:

There are two models supported by BlueTape:

A. Invoice only

  1. Create an invoice in BlueTape

  2. BlueTape notifies the customer

  3. The customer selects the payment method and pays

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

  1. Create a quote in BlueTape

  2. BlueTape notifies the customer

  3. Customer approves or reject the quote

  4. BlueTape informs the integrator about the approval result

  5. Create the invoice in BlueTape

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

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

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

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

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

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.