Introduction
Welcome to the Nusii API! You can use our API to access Nusii API endpoints. All endpoint URLs begin with https://app.nusii.com/api/v2/
. All requests must be serialized in JSON and Nusii uses the jsonapi.org specification.
Authentication
We offer a token based authentication. You can find your API access token here. Tokens need to be added in the HTTP_AUTHORIZATION header as
Token token=YOUR_API_KEY
# With shell, you can just pass the correct header with each request
curl -H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposals"
Make sure to replace
YOUR_API_KEY
with your API key.
Nusii expects the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Token token=YOUR_API_KEY
Errors
The Nusii API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request could not be understood by the server due to malformed syntax. |
401 | Unauthorized -- Your API key is wrong. |
403 | Forbidden -- The resource requested is hidden and for administrators only. |
404 | Not Found -- The specified resource could not be found. |
405 | Method Not Allowed -- You tried to access a resource with an invalid method. |
406 | Not Acceptable -- You requested a format that isn't json. |
410 | Gone -- The resource requested has been removed from our servers. |
429 | Too Many Requests -- You're requesting too many times. |
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. |
Rate Limiting
There is a rate limit of 100 API calls every 30 seconds.
With every request to the API we add a couple of headers to the request.
If the rate limit is exceeded you will receive a response HTTP 429 (Too Many Requests)
.
Header | Description |
---|---|
X-Ratelimit-Limit | The amount of API calls you can make every 30 seconds (always 100) |
X-Ratelimit-Remaining | The amount of API calls that are still remaining. |
Retry-After | The amount of seconds untill it is allowed again to make API calls |
X-RateLimit-Reset | The timestamp when it is allowed again to make API calls. |
Pagination
Some endpoints that return collections are paginated. For these endpoints, the meta object will tell you the current page, count, total number of pages, and total count of the collection.
curl "https://app.nusii.com/api/v2/proposals" \
-H "Authorization: Token token=your_access_token"
{
"data": [
{...},
{...}
],
"meta": {
"current-page": 2,
"next-page": 3,
"prev-page": 1,
"total-pages": 4,
"total-count": 89
}
}
Query Parameters
Parameter | Default | Description |
---|---|---|
page | 1 | Page number |
per | 25 | Number of results per page |
Account
Get my Account
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/account/me"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Account.me
The above command returns JSON structured like this:
{
"data": {
"id": "3",
"type": "accounts",
"attributes": {
"email": "hello@your_company.com",
"name": "Your Company Name",
"subdomain": "your_company",
"web": "www.your_company.com",
"currency": "USD",
"pdf_page_size": "A4",
"locale": "en",
"address": "Your Street Address 50",
"address_state": "New York",
"postcode": "10022",
"city": "New York",
"telephone": "1234567890",
"default_theme": "clean"
}
}
}
This endpoint retrieves your personal account data.
HTTP Request
GET https://app.nusii.com/api/v2/account/me
Clients
Get all Clients
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/clients"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Client.list(page: 1)
The above command returns JSON structured like this:
{
"data": [
{
"id": "12",
"type": "clients",
"attributes": {
"email": "support@nusii.com",
"name": "Michael",
"surname": "Koper",
"full_name": "Michael Koper",
"currency": "EUR",
"business": "Michael Koper BV",
"locale": "nl",
"pdf_page_size": "A4",
"web": "www.michaelkoper.com",
"telephone": "1234567890",
"address": "Madrid Street 34",
"city": "Madrid",
"postcode": "28018",
"country": "Spain",
"state": "Madrid"
}
}
],
"meta": {
"current-page": 2,
"next-page": 3,
"prev-page": 1,
"total-pages": 4,
"total-count": 52
}
}
This endpoint retrieves all clients.
HTTP Request
GET https://app.nusii.com/api/v2/clients
Get a Client
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/clients/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Client.get(100)
The above command returns JSON structured like this:
{
"data": {
"id": "4",
"type": "clients",
"attributes": {
"email": "support@nusii.com",
"name": "Michael",
"surname": "Koper",
"full_name": "Michael Koper",
"currency": "EUR",
"business": "Michael Koper BV",
"locale": "nl",
"pdf_page_size": "A4",
"web": "www.michaelkoper.com",
"telephone": "1234567890",
"address": "Madrid Street 34",
"city": "Madrid",
"postcode": "28018",
"country": "Spain",
"state": "Madrid"
}
}
}
This endpoint retrieves a single client
HTTP Request
GET https://app.nusii.com/api/v2/clients/:id
Create a client
curl -X POST \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"client": {"email": "john@doe.com", "name": "John", "surname": "Doe", "locale": "en"}}' \
"https://app.nusii.com/api/v2/clients"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Client.create(
email: 'john@doe.com',
name: 'John',
surname: 'Doe'
)
The above command returns JSON structured like this:
{
"data": {
"id": "104",
"type": "clients",
"attributes": {
"email": "john@doe.com",
"name": "John",
"surname": "Doe",
"full_name": "John Doe",
"currency": "EUR",
"business": "Michael Koper BV",
"locale": "en",
"pdf_page_size": "A4",
"web": "www.michaelkoper.com",
"telephone": "1234567890",
"address": "Madrid Street 34",
"city": "Madrid",
"postcode": "28018",
"country": "Spain",
"state": "Madrid"
}
}
}
This will return 201 Created and the current JSON representation of the client if the creation was a success.
HTTP Request
POST https://app.nusii.com/api/v2/clients
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
yes | String | Email of the client. | |
name | yes | String | First name of the client. |
surname | no | String | Surname of the client. |
currency | no | String | Currency of the client. Default: Account's default currency or USD. |
business | no | String | Company name of the client |
locale | no | String | Locale of the client. The language of the client's proposal. |
pdf_page_size | no | String | The pdf page size of the client's proposal. Default: A4 |
web | no | String | Website of the client. |
telephone | no | String | Telephone number of the client. |
address | no | String | Address of the client. |
city | no | String | City of the client. |
postcode | no | String | Postcode of the client. |
country | no | String | Country name of the client |
state | no | String | State name of the client. |
Update a client
curl -X PUT \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"client": {"email": "john@doe.com", "name": "John Doe"}}' \
"https://app.nusii.com/api/v2/clients/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
client = Nusii::Client.get(100)
client.email = 'john@doe.com'
client.save
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "proposals",
"attributes": {
"email": "support@nusii.com",
"name": "Michael",
"surname": "Koper",
"full_name": "Michael Koper",
"currency": "EUR",
"business": "Michael Koper BV",
"locale": "nl",
"pdf_page_size": "A4",
"web": "www.michaelkoper.com",
"telephone": "1234567890",
"address": "Madrid Street 34",
"city": "Madrid",
"postcode": "28018",
"country": "Spain",
"state": "Madrid"
}
}
}
This will return 200 OK and the current JSON representation of the client if the creation was a success.
HTTP Request
PUT https://app.nusii.com/api/v2/clients/:id
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
yes | String | Email of the client. | |
name | yes | String | First name of the client. |
surname | no | String | Surname of the client. |
currency | no | String | Currency of the client. Default: Account's default currency or USD. |
business | no | String | Company name of the client |
locale | no | String | Locale of the client. The language of the client's proposal. |
pdf_page_size | no | String | The pdf page size of the client's proposal. Default: A4 |
web | no | String | Website of the client. |
telephone | no | String | Telephone number of the client. |
address | no | String | Address of the client. |
city | no | String | City of the client. |
postcode | no | String | Postcode of the client. |
country | no | String | Country name of the client |
state | no | String | State name of the client. |
Delete a client
curl -X DELETE \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/clients/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
client = Nusii::Client.get(100)
client.destroy
The above command returns JSON structured like this:
{
"data": {
"id": "12",
"type": "clients",
"attributes": {
"email": "support@nusii.com",
"name": "Michael",
"surname": "Koper",
"full_name": "Michael Koper",
"currency": "EUR",
"business": "Michael Koper BV",
"locale": "nl",
"pdf_page_size": "A4",
"web": "www.michaelkoper.com",
"telephone": "1234567890",
"address": "Madrid Street 34",
"city": "Madrid",
"postcode": "28018",
"country": "Spain",
"state": "Madrid"
}
}
}
This endpoint deletes a specific client.
HTTP Request
DELETE https://app.nusii.com/api/v2/clients/:id
Line Items
Get all line items
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/line_items"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::LineItem.list(page: 1)
The above command returns JSON structured like this:
{
"data": [
{
"id": "154",
"type": "line_items",
"attributes": {
"section_id": 458,
"name": "Redesign website",
"position": 1,
"cost_type": "fixed",
"recurring_type": null,
"per_type": null,
"quantity": null,
"updated_at": "2017-11-24T10:30:40.282Z",
"created_at": "2017-11-24T10:30:40.282Z",
"currency": "GBP",
"amount_in_cents": 150000,
"amount_formatted": "£1,500.00",
"total_in_cents": 150000,
"total_formatted": "£1,500.00"
}
},
{...}
],
"meta": {
"current_page": 1,
"next_page": 2,
"prev_page": null,
"total_pages": 5,
"total_count": 115
}
}
This endpoint retrieves all line items.
HTTP Request
GET https://app.nusii.com/api/v2/line_items
Get all line items from section
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/sections/100/line_items"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::LineItem.list(section_id: 100)
The above command returns JSON structured like this:
{
"data": [
{
"id": "154",
"type": "line_items",
"attributes": {
"section_id": 458,
"name": "Redesign website",
"position": 1,
"cost_type": "fixed",
"recurring_type": null,
"per_type": null,
"quantity": null,
"updated_at": "2017-11-24T10:30:40.282Z",
"created_at": "2017-11-24T10:30:40.282Z",
"currency": "GBP",
"amount_in_cents": 150000,
"amount_formatted": "£1,500.00",
"total_in_cents": 150000,
"total_formatted": "£1,500.00"
}
},
{...}
]
}
This endpoint retrieves all line items from a given section. This response doesn't support pagination.
HTTP Request
GET https://app.nusii.com/api/v2/sections/100/line_items
Create a line item
curl -X POST \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"line_item": {"name": "Development Costs"}}' \
"https://app.nusii.com/api/v2/sections/100/line_items"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::LineItem.create(
section_id: 100,
name: 'Development Costs'
)
The above command returns JSON structured like this:
{
"data": {
"id": "157",
"type": "line_items",
"attributes": {
"section_id": 458,
"name": "",
"position": 2,
"cost_type": "fixed",
"recurring_type": null,
"per_type": null,
"quantity": null,
"updated_at": "2017-11-27T10:45:09.919Z",
"created_at": "2017-11-27T10:45:09.919Z",
"currency": "GBP",
"amount_in_cents": null,
"amount_formatted": "£0.00",
"total_in_cents": 0,
"total_formatted": "£0.00"
}
}
}
This will return 201 Created and the current JSON representation of the line item if the creation was a success.
HTTP Request
POST https://app.nusii.com/api/v2/sections/100/line_items
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
name | no | Text | Body of the line item |
cost_type | no | String | Default fixed . Possible values are fixed , recurring or per |
recurring_type | no | String | Possible values are yearly , semiannually , trimester , monthly , weekly , daily or hourly |
per_type | no | String | Possible values are year , month , week , day , hour , item or unit |
position | no | Integer | Position of the line item within the section |
quantity | no | Integer | If cost_type is per then total of the line item is calculated by quantity multiplied by amount |
amount | no | Integer | Amount in cents |
Update a line item
curl -X PUT \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"line_item": {"amount": 10000}}' \
"https://app.nusii.com/api/v2/line_items/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
line_item = Nusii::LineItem.get(100)
line_item.amount = 10000
line_item.save
The above command returns JSON structured like this:
{
"data": {
"id": "157",
"type": "line_items",
"attributes": {
"section_id": 458,
"name": "",
"position": 2,
"cost_type": "fixed",
"recurring_type": null,
"per_type": null,
"quantity": null,
"updated_at": "2017-11-27T10:45:09.919Z",
"created_at": "2017-11-27T10:45:09.919Z",
"currency": "GBP",
"amount_in_cents": 10000,
"amount_formatted": "£100.00",
"total_in_cents": 10000,
"total_formatted": "£100.00"
}
}
}
This will return 200 OK and the current JSON representation of the line item if the creation was a success.
HTTP Request
PUT https://app.nusii.com/api/v2/line_items/:id
or
PUT https://app.nusii.com/api/v2/sections/458/line_items/:id
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
name | no | Text | Body of the line item |
cost_type | no | String | Default fixed . Possible values are fixed , recurring or per |
recurring_type | no | String | Possible values are yearly , semiannually , trimester , monthly , weekly , daily or hourly |
per_type | no | String | Possible values are year , month , week , day , hour , item or unit |
position | no | Integer | Position of the line item within the section |
quantity | no | Integer | If cost_type is per then total of the line item is calculated by quantity multiplied by amount |
amount | no | Integer | Amount in cents |
Delete a line item
curl -X DELETE \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/line_items/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
line_item = Nusii::LineItem.get(100)
line_item.destroy
The above command returns JSON structured like this:
{
"data": {
"id": "157",
"type": "line_items",
"attributes": {
"section_id": 458,
"name": "",
"position": 2,
"cost_type": "fixed",
"recurring_type": null,
"per_type": null,
"quantity": null,
"updated_at": "2017-11-27T10:45:09.919Z",
"created_at": "2017-11-27T10:45:09.919Z",
"currency": "GBP",
"amount_in_cents": 10000,
"amount_formatted": "£100.00",
"total_in_cents": 10000,
"total_formatted": "£100.00"
}
}
}
This endpoint deletes a specific line item.
HTTP Request
DELETE https://app.nusii.com/api/v2/line_items/:id
Proposals
Get all Proposals
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposals"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Proposal.list(page: 1, status: 'draft', archived: false)
The above command returns JSON structured like this:
{
"data": [
{
"id": "126",
"type": "proposals",
"attributes": {
"title": "Webdesign yourwebsite.com",
"account_id": 3,
"status": "draft",
"public_id": "-NqDAkiqpiFLuuw",
"prepared_by_id": 3,
"client_id": 5,
"sender_id": null,
"currency": "USD"
},
"relationships": {
"sections": {
"data": [
{
"id": "414",
"type": "sections"
}
]
}
}
}
],
"meta": {
"current_page": 2,
"next_page": 3,
"prev_page": 1,
"total_pages": 4,
"total_count": 89
}
}
This endpoint retrieves all proposals.
HTTP Request
GET https://app.nusii.com/api/v2/proposals
Query Parameters
Parameter | Default | Description |
---|---|---|
status | null | If not set retrieves all proposals, Possible states are draft , pending , accepted , rejected , or clarification |
archived | false | If set to true, the result will only include archived proposals. |
Get a proposal
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposals/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Proposal.get(100)
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "proposals",
"attributes": {
"title": "Webdesign yourwebsite.com",
"account_id": 3,
"status": "draft",
"public_id": "-NqDAkiqpiFLuuw",
"prepared_by_id": 3,
"client_id": 5,
"sender_id": null,
"currency": "USD"
},
"relationships": {
"sections": {
"data": [
{
"id": "414",
"type": "sections"
}
]
}
}
}
}
This endpoint retrieves a single proposal
HTTP Request
GET https://app.nusii.com/api/v2/proposals/:id
Create a proposal
curl -X POST \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"proposal": {"client_id": 100, "title": "Webdesign yourwebsite.com"}}' \
"https://app.nusii.com/api/v2/proposals"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Proposal.create(
title: 'Webdesign yourwebsite.com',
client_id: 100
)
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "proposals",
"attributes": {
"title": "Webdesign yourwebsite.com",
"account_id": 3,
"status": "draft",
"public_id": "-NqDAkiqpiFLuuw",
"prepared_by_id": 3,
"client_id": 5,
"sender_id": null,
"currency": "USD"
},
"relationships": {
"sections": {
"data": [
{
"id": "414",
"type": "sections"
}
]
}
}
}
}
This will return 201 Created and the current JSON representation of the proposal if the creation was a success.
HTTP Request
POST https://app.nusii.com/api/v2/proposals
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
title | no | String | Title of the proposal |
client_id | no | ID | Client ID |
client_email | no | String | Fetches the client associated with that email. It creates a new client if there is no client with that email. This is ignored when client_id is set. |
template_id | no | ID | If set, all the sections are copied over from the template |
document_section_title | no | String | Title of the documents section. Default: Documents |
prepared_by_id | no | ID | Prepared by user |
expires_at | no | DateTime | Date the proposal expires |
display_date | no | DateTime | By Default the date displayed on the proposal is the sent date. This can be overwritten with the display_date |
report | no | Boolean | This turns the proposal into a report. Default: false |
exclude_total | no | Boolean | This excludes the total from the proposal. Default: false |
exclude_total_in_pdf | no | Boolean | This excludes the total from the proposal. Default: false |
theme | no | String | Theme of the proposal. Default: 'clean' |
Update a proposal
curl -X PUT \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"title": "Webdesign yourwebsite.com"}' \
"https://app.nusii.com/api/v2/proposals/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
proposal = Nusii::Proposal.get(100)
proposal.title = 'Webdesign yourwebsite.com'
proposal.save
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "proposals",
"attributes": {
"title": "Webdesign yourwebsite.com",
"account_id": 3,
"status": "draft",
"public_id": "-NqDAkiqpiFLuuw",
"prepared_by_id": 3,
"client_id": 5,
"sender_id": null,
"currency": "USD"
},
"relationships": {
"sections": {
"data": [
{
"id": "414",
"type": "sections"
}
]
}
}
}
}
This will return 200 OK and the current JSON representation of the proposal if the update was a success.
HTTP Request
PUT https://app.nusii.com/api/v2/proposals/:id
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
title | no | String | Title of the proposal |
client_id | no | ID | Client ID |
client_email | no | String | Fetches the client associated with that email. It creates a new client if there is no client with that email. This is ignored when client_id is set. |
document_section_title | no | String | Title of the documents section. Default: Documents |
prepared_by_id | no | ID | Prepared by user |
expires_at | no | DateTime | Date the proposal expires |
display_date | no | DateTime | By Default the date displayed on the proposal is the sent date. This can be overwritten with the display_date |
report | no | Boolean | This turns the proposal into a report. Default: false |
exclude_total | no | Boolean | This excludes the total from the proposal. Default: false |
exclude_total_in_pdf | no | Boolean | This excludes the total from the proposal. Default: false |
theme | no | String | Theme of the proposal. Default: 'clean' |
Delete a proposal
curl -X DELETE \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposals/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
proposal = Nusii::Proposal.get(100)
proposal.destroy
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "proposals",
"attributes": {
"title": "Webdesign yourwebsite.com",
"account_id": 3,
"status": "draft",
"public_id": "-NqDAkiqpiFLuuw",
"prepared_by_id": 3,
"client_id": 5,
"sender_id": null,
"currency": "USD"
}
}
}
This endpoint deletes a specific proposal.
HTTP Request
DELETE https://app.nusii.com/api/v2/proposals/:id
Archive a proposal
curl -X PUT \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposals/:id/archive"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
# TODO not implemented yet
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "proposals",
"attributes": {
"title": "Webdesign yourwebsite.com",
"account_id": 3,
"status": "draft",
"public_id": "-NqDAkiqpiFLuuw",
"prepared_by_id": 3,
"client_id": 5,
"sender_id": null,
"currency": "USD",
"archived_at": "2019-01-01T10:00:00.000Z"
}
}
}
This endpoint deletes a specific proposal.
HTTP Request
DELETE https://app.nusii.com/api/v2/proposals/:id
Send a proposal
curl -X PUT \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"email": "your_client@email.com", "subject": "Your Proposal"}' \
"https://app.nusii.com/api/v2/proposals/:id/send_proposal"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
# TODO not implemented yet
The above command returns JSON structured like this:
{
"status": "pending",
"sent_at": "2020-11-17T09:18:32.770Z",
"sent_at_in_ms": 1605604712000,
"sender_id": null,
"sender_name": null
}
This will return 200 OK and the current JSON representation.
HTTP Request
PUT https://app.nusii.com/api/v2/proposals/:id/send_proposal
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
yes | String | Email of the client | |
cc | no | String | CC Email receipients. Need to be comma separated if contains multiple emails. |
bcc | no | String | BCC Email receipients. Need to be comma separated if contains multiple emails. |
subject | no | String | Subject of the email |
message | no | String | Body of the email |
save_email_template | no | Boolean | Overwrite email template. Default: false |
sender_id | no | ID | ID of the sender |
sender_email | no | String | Fetches the Sender associated with that email. This is ignored when sender_id is set. |
Proposal Activities
Get all proposal activities
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposal_activities"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
activities = Nusii::ProposalActivity.list(
page: 1,
proposal_id: 100
)
The above command returns JSON structured like this:
{
"data": [
{
"id": "259",
"type": "proposal_activities",
"attributes": {
"activity_type": "user_send_proposal",
"ip_address": "127.0.0.1",
"additional_fields": {
"to": "john@doe.com",
"cc": "joh+cc@doe.com",
"from": "your@email.com",
"reply_to": "your@email.com",
"subject": "You've received your proposal!"
},
"proposal_title": "Webdevelopment",
"proposal_created_at": "2017-11-24T10:30:40.113Z",
"proposal_sent_at": null,
"proposal_status": "draft",
"proposal_public_id": "FYp1S4oBLxbNpQ",
"proposal_expires_at": null,
"client_name": "John",
"client_email": "john@doe.com",
"client_surname": "Doe",
"client_full_name": "John Doe",
"client_business": "Company Name",
"client_telephone": "1234567890",
"client_locale": "en",
"client_address": "Street Address",
"client_postcode": "28017",
"client_country": "Spain",
"client_city": "Madrid",
"client_state": "Madrid",
"client_web": "example.com"
}
},
{...}
],
"meta": {
"current_page": 1,
"next_page": 2,
"prev_page": null,
"total_pages": 9,
"total_count": 206
}
}
This endpoint retrieves all proposal activities.
HTTP Request
GET https://app.nusii.com/api/v2/proposal_activities
Query Parameters
Parameter | Default | Description |
---|---|---|
proposal_id | null | Only get activities from a specific proposal |
client_id | null | Only get activities from a specific client |
Get a Proposal Activity
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/proposal_activities/44"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
activity = Nusii::ProposalActivity.get(44)
The above command returns JSON structured like this:
{
"data": {
"id": "44",
"type": "proposal_activities",
"attributes": {
"activity_type": "user_send_proposal",
"ip_address": "127.0.0.1",
"additional_fields": {
"to": "john@doe.com",
"cc": "joh+cc@doe.com",
"from": "your@email.com",
"reply_to": "your@email.com",
"subject": "You've received your proposal!",
"bounce_type": "HardBounce",
"bounced_email": "john@doe.com",
"bounce_description": "The server was unable to deliver your message (ex: unknown user, mailbox not found)."
},
"proposal_title": "Design for clientwebsite.com",
"proposal_created_at": "2016-11-28T15:00:58.794Z",
"proposal_sent_at": "2017-01-12T12:46:33.396Z",
"proposal_status": "draft",
"proposal_public_id": "smaBXa7wa1Jv",
"proposal_expires_at": null,
"client_name": "John",
"client_email": "john@doe.com",
"client_surname": "Doe",
"client_full_name": "John Doe",
"client_business": "John Doe's Business",
"client_telephone": "1234567890",
"client_locale": "en",
"client_address": "Street Address 29",
"client_postcode": "28017",
"client_country": "Spain",
"client_city": "Madrid",
"client_state": "Madrid",
"client_web": "www.clientwebsite.com"
}
}
}
This endpoint retrieves a single proposal activity
HTTP Request
GET https://app.nusii.com/api/v2/proposal_activities/:id
Parameter | Type | Description |
---|---|---|
activty_type | String | Type of activity. Possible values are: client_view_proposal , client_view_pdf , user_create_proposal , user_view_proposal , user_send_proposal , user_manual_change_status_proposal , client_rejected_proposal , client_clarification_proposal , client_accepted_proposal , client_email_bounced , client_email_opened , and api_created_proposal |
ip_address | String | Ip address of the person that does the activity |
additional_fields | Hash | An hash with additional information. Possible values are: to (email address where the proposal is sent), cc (cc email address where proposal is sent), from (email address where proposal is sent from), reply_to (reply to email address), subject (subject of email), message (the body of the email sent, or the reason of a proposal state change), bounce_type (set if email bounced), bounce_description (description why email bounced) |
proposal_attributes | ... | Look at Proposal for information |
client_attributes | ... | Look at Client for information |
Sections
Get all sections
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/sections"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Section.list(page: 1)
The above command returns JSON structured like this:
{
"data": [
{
"id": "164",
"type": "sections",
"attributes": {
"currency": "GBP",
"account_id": 3,
"proposal_id": 124,
"template_id": null,
"title": "Introduction",
"name": null,
"body": "Lorem ipsum",
"position": 0,
"reusable": false,
"section_type": "cost",
"created_at": "2017-03-03T12:23:37.686Z",
"updated_at": "2017-03-03T12:23:45.828Z",
"page_break": false,
"optional": false,
"selected": false,
"include_total": false,
"total_in_cents": 50000,
"total_formatted": "£500.00"
},
"relationships": {
"line_items": {
"data": [
{
"id": "76",
"type": "line_items"
}
]
}
}
},
{...}
],
"meta": {
"current_page": 1,
"next_page": 2,
"prev_page": null,
"total_pages": 2,
"total_count": 48
}
}
This endpoint retrieves all sections.
HTTP Request
GET https://app.nusii.com/api/v2/sections
Query Parameters
Parameter | Default | Description |
---|---|---|
proposal_id | null | If set retrieves all sections of the proposal. |
template_id | null | If set retrieves all sections of the template. |
include_line_items | false | If set to true, the result will have all the data of the line items in the "included" parameter. |
Get a section
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/sections/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Section.get(100)
The above command returns JSON structured like this:
{
"data": {
"id": "164",
"type": "sections",
"attributes": {
"currency": "GBP",
"account_id": 3,
"proposal_id": 126,
"template_id": null,
"title": "Introduction",
"name": null,
"body": "<p>Hello {{ clientFirstName }}</p>",
"position": 0,
"reusable": false,
"section_type": "cost",
"created_at": "2017-03-03T12:23:37.686Z",
"updated_at": "2017-03-03T12:23:45.828Z",
"page_break": false,
"optional": false,
"selected": false,
"include_total": false,
"total_in_cents": 50000,
"total_formatted": "£500.00"
},
"relationships": {
"line_items": {
"data": [
{
"id": "76",
"type": "line_items"
}
]
}
}
}
}
This endpoint retrieves a single section
HTTP Request
GET https://app.nusii.com/api/v2/sections/:id
Create a section
curl -X POST \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"section": {"title": "Introduction"}}' \
"https://app.nusii.com/api/v2/sections"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::Section.create(
title: 'Introduction'
)
The above command returns JSON structured like this:
{
"data": {
"id": "164",
"type": "sections",
"attributes": {
"currency": "GBP",
"account_id": 3,
"proposal_id": 126,
"template_id": null,
"title": "Introduction",
"name": null,
"body": null,
"position": 0,
"reusable": false,
"section_type": "cost",
"created_at": "2017-03-03T12:23:37.686Z",
"updated_at": "2017-03-03T12:23:45.828Z",
"page_break": false,
"optional": false,
"selected": false,
"include_total": false,
"total_in_cents": 50000,
"total_formatted": "£500.00"
},
"relationships": {
"line_items": {
"data": [
{
"id": "76",
"type": "line_items"
}
]
}
}
}
}
This will return 201 Created and the current JSON representation of the section if the creation was a success.
HTTP Request
POST https://app.nusii.com/api/v2/sections
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
proposal_id | no | ID | ID of the proposal |
template_id | no | ID | ID of the template |
title | no | String | Title of the section |
body | no | Text | Body of the section |
name | no | String | Internal name of the section |
position | no | Integer | Position in the proposal or template. |
reusable | no | Boolean | Default false . Reusable sections can be reused to any template / proposal you want. |
section_type | no | String | Default text . Can be text or cost . A text section is just a section with a body. A cost section can have line items and has a total. |
page_break | no | Boolean | Default false . PDF page break |
optional | no | Boolean | Default false . Client can choose the price package when true . Price is fixed when false |
include_total | no | Boolean | Default false . Include a subtotal within the section. Not just the end of the proposal. |
Update a section
curl -X PUT \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
-d '{"section": {"title": "Introduction"}}' \
"https://app.nusii.com/api/v2/sections/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
section = Nusii::Section.get(100)
section.title = 'Introduction'
section.save
The above command returns JSON structured like this:
{
"data": {
"id": "126",
"type": "sections",
"attributes": {
"currency": "GBP",
"account_id": 3,
"proposal_id": 126,
"template_id": null,
"title": "Introduction",
"name": null,
"body": null,
"position": 0,
"reusable": false,
"section_type": "cost",
"created_at": "2017-03-03T12:23:37.686Z",
"updated_at": "2017-03-03T12:23:45.828Z",
"page_break": false,
"optional": false,
"selected": false,
"include_total": false,
"total_in_cents": 50000,
"total_formatted": "£500.00"
}
}
}
This will return 200 OK and the current JSON representation of the section if the update was a success.
HTTP Request
PUT https://app.nusii.com/api/v2/sections/:id
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
proposal_id | no | ID | ID of the proposal |
template_id | no | ID | ID of the template |
title | no | String | Title of the section |
body | no | Text | Body of the section |
name | no | String | Internal name of the section |
position | no | Integer | Position in the proposal or template. |
reusable | no | Boolean | Default false . Reusable sections can be reused to any template / proposal you want. |
section_type | no | String | Default text . Can be text or cost . A text section is just a section with a body. A cost section can have line items and has a total. |
page_break | no | Boolean | Default false . PDF page break |
optional | no | Boolean | Default false . Client can choose the price package when true . Price is fixed when false |
include_total | no | Boolean | Default false . Include a subtotal within the section. Not just the end of the proposal. |
Delete a section
curl -X DELETE \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/sections/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
section = Nusii::Section.get(100)
section.destroy
The above command returns JSON structured like this:
{
"data": {
"id": "164",
"type": "sections",
"attributes": {
"currency": "GBP",
"account_id": 3,
"proposal_id": 126,
"template_id": null,
"title": "Introduction",
"name": null,
"body": null,
"position": 0,
"reusable": false,
"section_type": "cost",
"created_at": "2017-03-03T12:23:37.686Z",
"updated_at": "2017-03-03T12:23:45.828Z",
"page_break": false,
"optional": false,
"selected": false,
"include_total": false,
"total_in_cents": 50000,
"total_formatted": "£500.00"
}
}
}
This endpoint deletes a specific section.
HTTP Request
DELETE https://app.nusii.com/api/v2/sections/:id
Themes
Get all Themes
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/themes"
The above command returns JSON structured like this:
{
"id": "clean",
"name": "Modern Theme"
}, {
"id": "classic",
"name": "Classic Theme"
}
}
This endpoint retrieves all available themes.
HTTP Request
GET https://app.nusii.com/api/v2/themes
Users
Get all Users
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/users"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::User.list(page: 1)
The above command returns JSON structured like this:
"data": [
{
"id": "12",
"type": "users",
"attributes": {
"email": "support@nusii.com",
"name": "Michael",
}
}
],
"meta": {
"current-page": 2,
"next-page": 3,
"prev-page": 1,
"total-pages": 4,
"total-count": 52
}
}
This endpoint retrieves all users.
HTTP Request
GET https://app.nusii.com/api/v2/users
Webhooks
With Nusii webhooks we can send your application requests when something interesting happens, like Proposal Accepted
, Proposal Viewed
etc.
Webhook endpoint format
Every webhook uses the same structure. It will always be in a standard POST
request with the object in the body.
The target url needs to be able to accept Content Type
: application/json
and POST
requests. Everything other than a 2xx request will be concidered an error and we will try will retry 25 times. If we receive a 410 GONE
response, we will delete the webhook entirely.
Parameter | Description |
---|---|
event_name | The name of the event. proposal_created , client_updated etc. |
The object | An hash that represents the object. The key is always the name of the object. "proposal", "client" etc |
{
"event_name": "proposal_created",
"proposal": {
"id": 30,
"title": "Webdevelopment",
...
}
}
Webhook endpoint errors
We concider all responses with 2xx
as successful. Other than that we concider it as an error and we will retry the request 24 times. If we receive a 410 GONE
, the enpoint will get removed from our database.
Available webhooks
Event | Description |
---|---|
proposal_created | Sends when a proposal is created |
proposal_updated | Sends when a proposal is updated |
proposal_destroyed | Sends when a proposal is deleted |
proposal_accepted | Sends when a proposal is accepted |
proposal_rejected | Sends when a proposal is rejected |
proposal_sent | Sends when a proposal is sent |
proposal_activity_client_viewed_proposal | Sends when your client views a proposal |
client_created | Sends when client is created |
client_updated | Sends when client is updated |
client_destroyed | Sends when client is deleted |
Get all webhook endpoints
curl -X GET \
-H 'User-Agent: Your App Name (www.yourapp.com)' \
-H 'Content-Type: application/json' \
-H "Authorization: Token token=YOUR_API_KEY" \
"https://app.nusii.com/api/v2/webhook_endpoints"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::WebhookEndpoint.list(page: 1)
The above command returns JSON structured like this:
{
"data": [
{
"id": "26",
"type": "webhook_endpoints",
"attributes": {
"events": [
"proposal_created",
"client_updated"
], "target_url": "http://example.com/webhooks"
},
},
{...}
],
"meta": {
"current-page": 2,
"next-page": 3,
"prev-page": 1,
"total-pages": 4,
"total-count": 89
}
}
This endpoint retrieves all webhooks endpoints.
HTTP Request
GET https://app.nusii.com/api/v2/webhook_endpoints
Get a webhook endpoint
curl -X GET </span>
-H 'User-Agent: Your App Name (www.yourapp.com)' </span>
-H 'Content-Type: application/json' </span>
-H "Authorization: Token token=YOUR_API_KEY" </span>
"https://app.nusii.com/api/v2/webhook_endpoints/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::WebhookEndpoint.get(100)
The above command returns JSON structured like this:
{
"data": {
"id": "33",
"type": "webhook_endpoints",
"attributes": {
"events": [
"proposal_created",
"client_created"
],
"target_url": "http://example.com/webhooks"
}
}
}
This endpoint retrieves a single webhook endpoint
HTTP Request
GET https://app.nusii.com/api/v2/webhook_endpoints/:id
Create a webhook endpoint
curl -X POST </span>
-H 'User-Agent: Your App Name (www.yourapp.com)' </span>
-H 'Content-Type: application/json' </span>
-H "Authorization: Token token=YOUR_API_KEY" </span>
-d '{"webhook_endpoint":{"target_url": "http://example.com","events": ["proposal_created", "client_created"]}}' </span>
"https://app.nusii.com/api/v2/webhook_endpoints"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
Nusii::WebhookEndpoint.create(
target_url: http://example.com,
events: ['proposal_created', 'client_created']
)
The above command returns JSON structured like this:
{
"data": {
"id": "34",
"type": "webhook_endpoints",
"attributes": {
"events": [
"proposal_created",
"client_created"
],
"target_url": "http://example.com"
}
}
}
This will return 201 Created and the current JSON representation of the webhook endpoint if the creation was a success.
HTTP Request
POST https://app.nusii.com/api/v2/webhook_endpoints
Attributes
Parameter | Mandatory | Type | Description |
---|---|---|---|
target_url | yes | String | Destination url of the webhook request. |
events | yes | String[] | An Array of string that represents the events you want to subscribe to. |
Delete a webhook endpoint
curl -X DELETE </span>
-H 'User-Agent: Your App Name (www.yourapp.com)' </span>
-H 'Content-Type: application/json' </span>
-H "Authorization: Token token=YOUR_API_KEY" </span>
"https://app.nusii.com/api/v2/webhook_endpoints/:id"
require 'nusii-ruby'
Nusii.api_key = 'YOUR_API_KEY'
Nusii.user_agent = 'Your App Name (www.yourapp.com)'
endpoint = Nusii::WebhookEndpoint.get(100)
endpoint.destroy
The above command returns JSON structured like this:
{
"data": {
"id": "34",
"type": "webhook_endpoints",
"attributes": {
"events": [
"proposal_created",
"client_created"
],
"target_url": "http://example.com"
}
}
}
This endpoint deletes a specific webhook_endpoint.
HTTP Request
DELETE https://app.nusii.com/api/v2/webhook_endpoints/:id