Hi, nice to see you!

This is the developer guide for the HQ API, which allows developers access to a wide range of entities and business logic of the HQ.

Introduction

The HQ API allows access to your data. To do so, it follows the OData 4.0 standard for retrieving, creating, updating and deleting entities through RESTful HTTP requests.

Base URL: https://api.hellohq.io

Before you get started, you need to register your client application in the HQ admin panel.

Authentication

The HQ API uses OAuth 2.0 for authentication.

Getting Started

OAuth 2.0 is an authentication framework used for secure user authentication. With the typical OAuth 2.0 authentication flows, third-party applications do not receive the user's password but only a token which is valid for a limited time.

To uniquely identify the client, each client application needs to be registered first. The client receives an App Id and App Secret which they use to authenticate against the API.

When a user wants to use the client application, the user should be redirected to our login page to provide username and password. After a successful login, the client application receives an Access Token and Refresh Token. These can be used to authenticate against the API. From then on, the user is no longer involved in the authentication process.

Client Application

A client application needs to be registered in your HQ. To do so, go to the administration panel and add a new client application. You will be asked to provide a unique name, and a display name for your client.

App Id

The App Id used for OAuth 2.0 consists of your HQ customer id as well as the id of the client application you created in the HQ: {customer-id}-{client-id}. For example, 12345-clientapp, where 12345 is your customer id and clientapp is the id of the client. After you registered a client application in your HQ, you can find the App Id in the list in the administration panel.

App Secret

The App Secret is generated in the administration section of your HQ. It is located next to the App Id in the administration panel list. The secret will be used to authenticate your client application when requesting a token.

Scopes

The OAuth 2.0 authentication flow uses scopes to define which rights are granted to the application by the user. The HQ API currently supports the following scopes:

Access Token

The Access Token is used to authenticate against the API resources. It needs to be included in every request to the API. Each user must use their own unique Access Token, since such tokens are only valid for the associated user. The toke is usually valid for a few days only.

Refresh Token

The Refresh Token is used to get a new Access Token, once it has expired. A Refresh Token only expires when the user manually revokes access for the client application.

OAuth Endpoints

The OAuth endpoints are required to get an Access Token and exchange a Refresh Token for a new Access Token:

Authorization Flow

The OAuth 2.0 Authorization Code Grant is the default authorization flow and mainly used by client applications. It is described here in detail:

Authorization Request

The client constructs the request URI by adding the following parameters to the query string of the authorization endpoint URI using the application/x-www-form-urlencoded format. Then, the client directs the user to the constructed URI using a browser window. The user is asked to log in, provides their username and password, and grants the requested permissions to your client application.

Parameter:

Example:

GET https://api.hqlabs.de/Account/Authorize
                                ?response_type=code
                                &client_id=1234-testapp
                                &state=xyz
                                &redirect_uri=https://client.example.com/cb
                                &scope=read_all write_all
                        

Note: the generated URL needs to be opened in a browser window so that the user can log in and authorize the application.

All query parameters (especially the RedirectUri) should be properly URL-encoded.

If the user is already granted the same scopes to the client application, the UI will not be rendered and the redirect with the authorization code happens automatically.

User Authentication

The user logs in, and grants or revokes the access request.

Authorization Response

If the user grants the access request, the authorization server issues an authorization code and delivers it to the client by adding the following parameters to the query string of the redirection URI using the application/x-www-form-urlencoded format.

Parameter:

Example:

302 Found

https://client.example.com/cb?code=MWG5HTnFn9n8HJ&state=xyz
                        

Access Token Request

The client makes a request to the token endpoint by sending the following parameters in the request body using the application/x-www-form-urlencoded format.

Parameter:

Note: To construct a proper HTTP Authorization header for Basic Access Authentication, you need to encode your App Id and App Secret using Base64, and add it to the Authorization header as follows: Authorization: Basic Base64({AppId}:{AppSecret})

Example:

Url:

POST https://api.hqlabs.de/Token

Header:

Content-Type=application/x-www-form-urlencoded

Body:

redirect_uri=https://client.example.com/cb

grant_type=authorization_code

code=MWG5HTnFn9n8HJ => 'Code from authorize call'

client_id=1234-testapp =>'From hellHQ UI'

client_secret=fkgjqoer9tfiealdkcmakwhdf =>'From hellHQ UI'

scope=read_all write_all

Note: All query parameters (especially the RedirectUri) should be properly URL-encoded.

Access Token Response

If the access token request is valid and authorized, the authorization server issues an Access Token and Refresh Token. If the request failed or is invalid, the authorization server returns an error response.

Parameter:

Example:

{
                           "access_token": "FGDoJBgK96Z...",  // the Access Token for authorization
                           "token_type": "bearer",            // the token type, usually bearer
                           "expires_in": 1199,                // the expiration timespan, in seconds
                           "refresh_token": "K8vma4VohMb...", // the Refresh Token to request a new Access Token
                           "user_id": 12,                     // the Id of the user these tokens are valid for
                           "user_name": "test.user"           // the username of the user these tokens are valid for
                        }
                        

After receiving the Access Token, you can use it to request resources from the API.

Resource Request

To retrieve resources from the API, add the Access Token to the Authorization header in the following form: Bearer {AccessToken}

Example:

Authorization: Bearer FGDoJBgK96Z...
                        

Access Tokens expire and need to be refreshed with the Refresh Token.

Refresh Token Request

Every Access Token expires after a time, usually after 30 days. You can use the Refresh Token to retrieve a new Access Token. The Refresh Token only expires when the user revokes the token.

Parameter:

Example:

POST https://api.hqlabs.de/Token

grant_type=refresh_token&refresh_token=K8vma4VohMb...
                        

Example:

{
                           "access_token": "ADFoJBgK96c...",  // the new Access Token for authorization
                           "token_type": "bearer",            // the token type, usually bearer
                           "expires_in": 1199,                // the expiration timespan, in seconds
                           "refresh_token": "Gtv6a4VohaB...", // the new Refresh Token to request a new Access Token
                           "user_id": 12,                     // the Id of the user these tokens are valid for
                           "user_name": "test.user"           // the username of the user these tokens are valid for
                        }
                        

For further questions, please contact us at [email protected].

Expand

Expands can be used to retrieve more data in one query. They allow to get related entities and navigation properties from an entity.

In the URL, add the following to the $expand= parameter.

Here, some examples for using the expand option are shown.

Expand one property

/v1/Companies?$expand=DefaultAddress
                        

Expand multiple properties

/v1/Companies?$expand=DefaultAddress,CompanyTypes
                        

Expand multiple levels

/v1/Invoices?$expand=Positions($expand=CustomFields)
                        

Filter

Filter are useful to construct queries against our API. This way, you don't need to retrieve all data and filter on the client.

In the URL, add the following to the $filter= parameter.

If you want to filter on a sub-entity, make sure to expand the entity first.

Here, some examples for using the filter option are shown.

Filter by date and time

/v1/Companies?$filter=UpdatedOn ge 2018-01-26
                        
/v1/Companies?$filter=UpdatedOn gt 2018-01-26T18:15:00+01:00
                        
/v1/Invoices?$filter=InvoiceDate ge 2018-03-01 and InvoiceDate lt 2018-04-01
                        

Filter by CompanyType

/v1/Companies?$expand=CompanyTypes&$filter=CompanyTypes/any(companyType: companyType/Id eq 4002)
                        
/v1/Companies?$expand=CompanyTypes&$filter=CompanyTypes/any(companyType: companyType/Name eq 'Lieferant')
                        

HTTP Conventions

Response Types

Generally, all API responses, as well as the POST and PUT bodies, are in JSON and follow the OData 4 definition.

The OData response wraps the actual data in the data field and adds additional metadata.

However, there are some cases where the API provides access to binary data, like PDFs and images.

Every document, for example invoices and quotations, can be retrieved as a generated PDF file. The PDF is generated on the fly when the document is in a draft state. After the document was sent, the PDF is archived and the archived PDF is returned in the API.

You can access the metadata of the document file like this: /v1/Invoices(id)/DocumentFile

You can access the binary stream (PDF) of the document file like this: /v1/Invoices(id)/DocumentFile/$value

For further questions, please contact us at [email protected].

HTTP Codes

Each response to an API request indicates the success with its status code.

Success Status Codes


                        GET           200 (OK)     
                        POST          201 (Created)     
                        PUT           200 (OK)     
                        DELETE        204 (No content)     
                        do.Action()   200 (OK)            If base entity was changed
                        do.Action()   201 (Created)       If new entity was created
                        

The body of the reponse with status code 200 and 201 contain the changed/created object. Responses with code 204 always return an empty body.

Failure Status Codes


                        GET / PUT / DELETE / do.Action()   404 (Not Found)     No object found / Invalid Id
                        POST / PUT / do.Action()           400 (Bad request)   Missing request body
                        POST / PUT / do.Action()           400 (Bad request)   Missing request argument
                        POST / PUT / do.Action()           400 (Bad request)   Validation failed
                        

Dates and Times

The date and time information is generally in UTC. The client is responsible for converting the date and time information to user time. The user object contains the selected timezone of the user. Date and time properties in UTC end on ...On, for example StartOn or CreatedOn.

There are, however, a few exceptions, where only the date is relevant. In these cases, the date information is represented without a timezone and should not be converted. Date properties end on ...Date, for example StartDate or ShownDate.

Actions

Actions are POST operations performed on specific API objects. Sometimes actions need specific parameters for the performed operation but this is not necessary every one of them. An action is mostly a more complex operations handled on the server which usually perform different data manipulations and object creations. Remember that an action should not be invoked too frequently on the same object because of the data manipulation. One call is sufficient to get the certain outcome.

When new objects are created during an action, in most cases the newly generated action is beeing returned. The return value can be seen in the action description iteself.

Further References

Please refer to the following pages and guides to learn how to use our API.