REST API Reference

Welcome to NiceJob's v2 REST API. Our API accepts JSON-encoded and form-encoded request bodies, returns JSON-encoded responses, uses OAuth2 for authentication, and uses standard HTTP response codes.

The API and this documentation are still very much a work in progress. Please refer to the API CHANGELOG for the latest changes.

The API is currently in alpha, meaning that endpoints, request formats, and response formats remain subject to change. We will notify all API users when breaking changes are going to be made.


Authentication

For authentication, we use OAuth2: a 3-step procedure comprising a user redirect for the obtainment of consent, and two subsequent client-to-NiceJob POST requests. Much has been written about OAuth2. If you are unfamiliar with it, we recommend these resources:

Use the following endpoints for your OAuth2 requests to NiceJob:

Authorization endpoint https://api.nicejob.com/oauth/authorize
Token endpoint https://api.nicejob.com/oauth/token
Revocation endpoint https://api.nicejob.com/oauth/revoke
Introspection endpoint https://api.nicejob.com/oauth/introspect

The 3 steps to obtain an access token are thus:

REDIRECT/oauth/authorize
Get authorization code

Gain the user's consent by redirecting them to the authorization endpoint. We then redirect the user back to your <code>redirect_uri</code>, with the authorization code attached as a query parameter.

POST/oauth/token
Get refresh token
POST/oauth/token
Get access token

With the access token obtained, you are free to query the API. See the requests section of the API for information on how to format your requests.

Access token expiry & refresh

Access tokens are valid for a period of 24 hours. You are free to refresh them at any point beforehand. To refresh an access token, repeat the get access token step above.

Refresh token expiry

Refresh tokens do not expire.

Refresh token revocation

In the case that you or the user would like to end the connection between applications, refresh tokens may (and should) be revoked.

To revoke a refresh token, make a POST request to the revocation endpoint using the format defined in the OAuth2 standard.

Alpha warning: Token revocation is not yet available.

Token introspection

Alpha warning: Token introspection is not yet available.

Authentication for webhooks

Note that webhook authentication – given that it is developer-scoped via a client_credentials grant type and not company-scoped – follows a different authentication protocol. See the Webhook authentication section below for more.

Scopes

Your app's credentials – and all access tokens derived from them – are restricted to work within an array of provided scopes. You can view your app's permitted scopes by signing in and checking your app's credentials. The scope(s) required to access each endpoint are provided in the endpoint documentation below.


Requests

The NiceJob API expects incoming requests to be in JSON format, with a Content-Type: application/json header.


Responses & Errors

Status codes

We return 200 status codes for all properly processed requests. Requests with malformed input data will return a 400, while unauthorized requests – including those with an expired access token – will return a 401. Server errors from our side will return a ≥500.

Errors

There are cases however where successfully formatted and authenticated requests do not produce their intended action – e.g. a creation request with a duplicated unique key. Such cases will return a 200 status code but output an error message in the response's error field.

Response format

Any successful API request (status 200) will receive, in response, a JSON object with the following fields:

type: DEFAULT_RESPONSESee live API documentation for full schema details.

Changelog

See the API Changelog for the latest changes to this API.

During the API's alpha stage, we will be providing the time of last update in the documentation sidebar.

Booking

A Booking represents a job that a user Company has arranged with one of their customers (known as a Person herein). The Booking entity can be created at the time of scheduling. Upon completion, the Booking is to be updated as complete. Booking completion will normally trigger a CampaignEnrollment, depending on the Company's Campaign settings.

If your software supports job grouping, you may want to consider creating one Booking with subordinate Visits. See the Visit entity description for more information.

The Booking entity

Properties

type: JobSee live API documentation for full schema details.

List Bookings

Retrieve a paginated list of Booking entities.

GET/v2/bookings

Response data

Returns an array of Booking entities, up to 20 items long.

Scopes required

bookings


Get a Booking

Retrieve an individual Booking entity.

GET/v2/bookings/:id

Response data

Returns the Booking entity if found. Returns a null result otherwise.

Scopes required

bookings


Create a Booking

POST/v2/bookings

Response data

Returns the new Booking entity.

Scopes required

bookings


Update a Booking

Updates a Booking entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/bookings/:id

Response data

Returns the updated Booking entity, if found. Returns a null result otherwise.

Scopes required

bookings

Case

A Case represents a legal case that a user Company has arranged with one of their customers (known as a Person herein). Upon completion, the Case is to be updated as complete. Case completion will normally trigger a CampaignEnrollment, depending on the Company's Campaign settings.

The Case entity

Properties

type: CaseSee live API documentation for full schema details.

List Cases

Retrieve a paginated list of Case entities.

GET/v2/cases

Response data

Returns an array of Case entities, up to 20 items long.

Scopes required

cases


Get a Case

Retrieve an individual Case entity.

GET/v2/cases/:id

Response data

Returns the Case entity if found. Returns a null result otherwise.

Scopes required

cases


Create a Case

POST/v2/cases

Response data

Returns the new Case entity.

Scopes required

cases


Update a Case

Updates a Case entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/cases/:id

Response data

Returns the updated Case entity, if found. Returns a null result otherwise.

Scopes required

cases

Campaign

Campaigns are the heart of NiceJob: they're the primary vehicle through which we provide value for our users. Campaigns consist of a sequence of messages between Company and Person (client), through which the company makes a request of the client.

NiceJob provides a series of campaigns, though the only one currently accessible through the API is the Get Reviews campaign.

For a Person to start receiving campaign messages, they must be enrolled.

The Campaign entity

Properties

type: CampaignSee live API documentation for full schema details.

List Campaigns

Retrieve a list of Campaign entities.

GET/v2/campaigns

Response data

Returns an array of Campaign entities.

Scopes required

campaigns

CampaignEnrollment

Campaign enrollments can be created in one of two ways: indirectly or directly. Indirect enrollment

Indirect enrollment occurs in response to Booking completion (wherein the Booking created with complete: true, or the complete field is updated to true), and is subject to the user's NiceJob settings. This is the recommended mode of enrollment: create the Booking entity, and let NiceJob take care of the rest. Direct enrollment

In some cases however, we permit direct enrollment of a Person into a campaign via the API. This is conveyed through the enrollments scope. Enrollment is conditional

Campaigns have rules that prevent multiple enrollments of the same Person. Therefore direct enrollment requests may not result in the creation of a CampaignEnrollment entity. Such requests will still return a 200 status code, but will have a null data field and an error message in the error field.

Direct enrollments will also fail where insufficient Person information is provided. Either an email address or a phone number is requred.

The CampaignEnrollment entity

Properties

type: CampaignEnrollmentSee live API documentation for full schema details.

Enroll a Person in a Campaign

Attempts to enroll a Person into a given campaign, defaulting to the Company's Get Reviews campaign.

Alpha warning: Currently, the Person entity must be created prior to the enrollment request. Soon we will enable an upsert + enroll functionality in this endpoint.

POST/v2/campaign_enrollments

Response data

Returns the new CampaignEnrollment entity, if successfully created.

Scopes required

enrollments

Company

The Company is the foundational entity in NiceJob. All other entity types fall within the company namespace. Access tokens are not tied to the authenticating user's user data but rather to the data of one of their companies.

The Company entity

Properties

type: CompanySee live API documentation for full schema details.

Get the Company

Retrieve the access token-bound Company entity.

GET/v2/company

Response data

Returns the Company entity to which the access token is bound.

Scopes required

company

Employee

An Employee represents an employee of the Company. Given that the Company manages the NiceJob account, the employee may also be a NiceJob User. Employees are often attached to Bookings.

Employee is referred to as Team member in app.

The Employee entity

Properties

type: EmployeeSee live API documentation for full schema details.

List Employees

Retrieve a paginated list of Employee entities.

GET/v2/employees

Response data

Returns an array of Employee entities, up to 20 items long.

Scopes required

employees


Get an Employee

Retrieve an individual Employee entity.

GET/v2/employees/:id

Response data

Returns the Employee entity if found. Returns a null result otherwise.

Scopes required

employees


Create an Employee

POST/v2/employees

Request body

input: CreateEmployeeInputSee live API documentation for full schema details.

Response data

Returns the new Employee entity.

Scopes required

employees


Update an Employee

Updates an Employee entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/employees/:id

Response data

Returns the updated Employee entity, if found. Returns a null result otherwise.

Scopes required

employees

Invoice

The Invoice entity

Properties

type: InvoiceSee live API documentation for full schema details.

List Invoices

Retrieve a paginated list of Invoice entities.

GET/v2/invoices

Response data

Returns an array of Invoice entities, up to 20 items long.

Scopes required

invoices


Get an Invoice

Retrieve an individual Invoice entity.

GET/v2/invoices/:id

Response data

Returns the Invoice entity if found. Returns a null result otherwise.

Scopes required

invoices


Create an Invoice

POST/v2/invoices

Response data

Returns the new Invoice entity.

Scopes required

invoices


Update an Invoice

Updates an Invoice entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/invoices/:id

Response data

Returns the updated Invoice entity, if found. Returns a null result otherwise.

Scopes required

invoices

Payment

The Payment entity

Properties

type: PaymentSee live API documentation for full schema details.

List Payments

Retrieve a paginated list of Payment entities.

GET/v2/payments

Response data

Returns an array of Payment entities, up to 20 items long.

Scopes required

payments


Get a Payment

Retrieve an individual Payment entity.

GET/v2/payments/:id

Response data

Returns the Payment entity if found. Returns a null result otherwise.

Scopes required

payments


Create an Payment

POST/v2/payments

Response data

Returns the new Payment entity.

Scopes required

payments


Update an Payment

Updates an Payment entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/payments/:id

Response data

Returns the updated Payment entity, if found. Returns a null result otherwise.

Scopes required

payments

Person

A Person represents a company client, or customer.

The Person entity

Properties

type: PersonSee live API documentation for full schema details.

List People

Retrieve a paginated list of Person entities.

GET/v2/people

Response data

Returns an array of Person entities, up to 20 items long.

Scopes required

people


Get a Person

Retrieve an individual Person entity.

GET/v2/people/:id

Response data

Returns the Person entity if found. Returns a null result otherwise.

Scopes required

people


Create a Person

POST/v2/people

Response data

Returns the new Person entity.

Scopes required

people


Update a Person

Updates a Person entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/people/:id

Response data

Returns the updated Person entity, if found. Returns a null result otherwise.

Scopes required

people

Review

A Review represents a company review on a particular network.

The Review entity

Properties

type: ReviewResponseExternalSee live API documentation for full schema details.

List Reviews

Retrieve a paginated list of Review entities.

GET/v2/reviews

Response data

Returns an array of Review entities, up to 20 items long.

Scopes required

reviews


Get a Review

Retrieve an individual Review entity.

GET/v2/reviews/:id

Response data

Returns the Review entity if found. Returns a null result otherwise.

Scopes required

reviews

ReviewInsights

The ReviewInsights entity provides an aggregate summary of a company's online reviews.

The ReviewInsights entity

Properties

type: ReviewInsightsResponseSee live API documentation for full schema details.

Get ReviewInsights

Retrieve the ReviewInsights entity.

GET/v2/review_insights

Response data

Returns the ReviewInsights entity.

Scopes required

review_insights

Visit

Many job management softwares will distinguish between a job and its constituent parts – the visits, or segments, that comprise it. We provide the same functionality here: a Visit entity is the child entity of a Booking.

A Visit has a required booking_id property – therefore the Booking must be created before the Visit. A Booking, meanwhile, does not necessarily have to include Visits.

Note that – unlike with Bookings – a NiceJob user will have to update their Company's Campaign settings should they want a Visit completion to trigger the creation of a CampaignEnrollment. Campaign settings cannot be updated through the API.

If you wish to have a Visit trigger a CampaignEnrollment, consider just using Bookings instead, or notify your users of the necessity to update their NiceJob Campaign settings.

Upon completion, a Visit is to be updated as complete.

The Visit entity

Properties

type: VisitSee live API documentation for full schema details.

List Visits

Retrieve a paginated list of Visit entities.

GET/v2/visits

Response data

Returns an array of Visit entities, up to 20 items long.

Scopes required

bookings


Get a Visit

Retrieve an individual Visit entity.

GET/v2/visits/:id

Response data

Returns the Visit entity if found. Returns a null result otherwise.

Scopes required

bookings


Create a Visit

POST/v2/visits

Response data

Returns the new Visit entity.

Scopes required

bookings


Update a Visit

Updates a Visit entity. The values you provide will overwrite any previously-existing values on the entity.

POST/v2/visits/:id

Response data

Returns the updated Visit entity, if found. Returns a null result otherwise.

Scopes required

bookings

Webhook

NiceJob webhooks allow you to receive a notification whenever a change occurs to a company's data. The process for creating a webhook is as follows:

  1. Create an endpoint on your server which is accessible from our servers.
  2. Create a webhook entity through the NiceJob API where the endpoint_url is the fully-qualified URL of your new endpoint, and specify one or more entity types (subscriptions) with which this webhook is associated. See the subscriptions list below.
  3. Test the webhook using our webhook testing endpoint described below.

A single webhook endpoint can receive one or many subscription types.

A NiceJob webhook is company-independent. Instead, it is linked to your developer account. This means that you only need to establish a single webhook endpoint for all company connections, and not one endpoint for each company connection. This approach makes it much easier to manage your webhooks: for example when changing your webhook subscriptions, or changing a webhook endpoint. An example workflow is as follows:

  1. A Person-related event is published within NiceJob.
  2. NiceJob checks all registered webhooks for those subscribed to the Person entity.
  3. NiceJob then checks that the owner of each subscribed webhook has a valid access token for the affected company with the Person entity in-scope.
  4. For all registered and subscribed and authorized webhooks, a message is published to the registered endpoint.

Webhook authentication

The webhook endpoint is linked to your developer account, and as such does not require OAuth2 user authorization to manage (as defined in the Authentication section above). Thus the webhook endpoint requires an access token provided using the grant_type: "client_credentials" OAuth2 flow as described here.

The access token provided using the client_credentials flow has a limited set of scopes for managing entities associated with your developer account.

POST/oauth/token
Get client_credentials access token

The Webhook Entity

Properties

type: WebhookSee live API documentation for full schema details.

Valid subscriptions values are:


List Webhooks

GET/v2/webhooks

Response data

Returns an array of Webhook entities, up to 20 items long.

Scopes required

webhooks


Get a Webhook

Retrieve an individual Webhook entity.

GET/v2/webhooks/:id

Response data

Returns the Webhook entity if found. Returns a 401 HTTP status code if not found.

Scopes required

webhooks


Create a Webhook

Create a new Webhook entity.

POST/v2/webhooks

Response data

Returns the new Webhook entity.

Scopes required

webhooks


Update a Webhook

Updates a Webhook entity.

The subscriptions property of UpdateWebhookInput is immutable. Therefore for an update, you must provide the whole new subscriptions value which will replace the existing subscriptions value.

POST/v2/webhooks/:id

Response data

Returns the updated Webhook entity.

Scopes required

webhooks


Delete a Webhook

Deletes a Webhook entity.

DELETE/v2/webhooks/:id

Response data

Returns the deleted Webhook entity.

Scopes required

webhooks


Webhook requests

Outbound webhook requests are application/json POST requests, with the body data structured as follows:

type: WebhookMessageSee live API documentation for full schema details.

Note that we only provide the entity_id of the entity affected, as well as the event_code, which will confer the entity type. Use the entity endpoints to retrieve the updated entity information.

Signature validation

On webhook creation, a secret will be generated and returned in the response. This is the only time the secret will be shared.

Each Webhook publication will contain a signature which will be composed of two properties: a timestamp and a signed payload. The timestamp will be Unix-format and be appended to the request immediately prior to dispatch.

The signed payload will be a HMAC using the SHA-256 algorithm. In order to validate the signature, one must:

Verify the message came from NiceJob

  1. Serialize the unsigned payload and then concatenate the timestamp. (see clarification below).
  2. Generate the HMAC using the following parameters:
  1. Compare the generated HMAC for equality against the signed_payload property from the received message

It is critical that the order of attributes in the payload are maintained during serialization. Some serialization libraries do not guarantee this, for example the NodeJS JSON library.

Verify the message was not intercepted

The timestamp is generated immediately prior to dispatch. You should compare the timespan between now and the timestamp to see how much time has elapsed and ensure it is within your security tolerances.

Retries

The failure condition for delivery of a Webhook is that we receive a non-2xx HTTP response. When this happens, NiceJob will retry for up to 3 days with an exponential back off. At this point your webhook endpoint will be disabled and we will attempt to inform you via email. Once you have resolved the issue, you can re-enable your webhook using the Update Webhook endpoint by setting the is_enabled property to true.

When invoking a Webhook delivery through the Test Webhook endpoint, there are no retries and your endpoint will not be disabled.


Testing webhooks

For development purposes, we have provided a method of invoking a mock webhook publication for a specific subscription. If you have a webhook registered for the subscription, we will publish to that endpoint with the mock payload.

POST/v2/rpc/test-webhook

Request body

type: TestWebhookInputSee live API documentation for full schema details.

Response data

Returns a HTTP status code where a 200 indicates a webhook has been found for the provided subscription and it has been successfully queued for publishing.

Scopes required

webhooks