Hi, nice to see you!

This is the developer guide for the helloHQ API, which provides developers with access to a broad range of entities and business logic within helloHQ.

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

Introduction

The helloHQ API is currently available in two versions, each with significant differences as they utilize different standards and technologies. For detailed information, please refer to the individual sections below.

v1

The initial release of our API is based on the OData 4.0 standard, offering comprehensive access to most features of the helloHQ platform.
This version includes all entities available in helloHQ 1.9, ensuring broad compatibility and functionality.

Note: This version does not support the new finance processes.

v2

The second version of our API follows the REST standard, without utilizing OData.
This version allows you to manage all operations related to the new finance processes.

Note: This version powers the new helloHQ 2.0 API and is currently under active development, with new endpoints being continuously added.

Before you begin, please register your client application in the helloHQ admin panel.

Depending on the version you use, you will find them in different places.

Further References

For more information on how to use our API, please refer to the following resources:

API V1

Authentication

The HQ API uses OAuth 2.0 for authentication.

Getting Started

OAuth 2.0 is a framework designed for secure user authentication. In typical OAuth 2.0 flows, third-party applications don't handle the user's password but instead receive a token that is valid for a limited time.

To uniquely identify a client, each application must first be registered. Upon registration, the client is provided with an App Id and App Secret, which are used to authenticate with the API.

When a user wants to access the client application, they are redirected to our login page to enter their username and password. After a successful login, the client application is issued an Access Token and a Refresh Token, which can be used to authenticate with the API. From that point, the user is no longer required to be part of the authentication process.

Client Application

To register a client application, navigate to the administration panel in your HQ. There, you can add a new client application by providing a unique name and a display name for the client.

App Id

The App Id used for OAuth 2.0 includes both your HQ customer ID and the client application ID you created: {customer-id}-{client-id}. For instance, 12345-clientapp, where 12345 represents your customer ID, and clientapp is the ID of the client. After registering a client application, you can find the App Id in the administration panel's list.

App Secret

The App Secret is generated within your HQ's administration panel. It is displayed next to the App Id in the list and is used to authenticate the client application when requesting a token.

Scopes

OAuth 2.0 uses scopes to specify the permissions granted to the application by the user. The HQ API currently supports the following scopes:

Access Token

The Access Token is used to authenticate API requests. It must be included in every API request. Each user has their own unique Access Token, which is only valid for that user and typically expires after a few days.

Refresh Token

The Refresh Token is used to obtain a new Access Token once the original one expires. A Refresh Token remains valid until the user manually revokes access for the client application.

OAuth Endpoints

The following OAuth endpoints are used to obtain an Access Token or exchange a Refresh Token for a new Access Token:

Authorization Flow

The default authorization flow is OAuth 2.0's Code Grant, primarily used by client applications. It is described in detail below:

Authorization Request

The client constructs a request URI by appending the following parameters to the query string of the authorization endpoint URI, using the application/x-www-form-urlencoded format. The client then directs the user to this URI using a browser window, where the user logs in, provides their credentials, and grants the requested permissions to the client application.

Parameters:

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 must be opened in a browser window for the user to log in and authorize the application.

Ensure that all query parameters, particularly the RedirectUri, are properly URL-encoded.

If the user has already granted the same scopes to the client application, the authorization UI will not be displayed, and the redirection with the authorization code will occur automatically.

User Authentication

The user logs in and either grants or denies the access request.

Authorization Response

If the user grants access, the authorization server provides an authorization code to the client by appending the following parameters to the query string of the redirection URI, using the application/x-www-form-urlencoded format.

Parameters:

Example:

302 Found

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

Access Token Request

The client requests an access token by sending the following parameters in the request body, formatted as application/x-www-form-urlencoded.

Parameters:

Note: To create a valid HTTP Authorization header for Basic Access Authentication, encode your App Id and App Secret using Base64 and include them in the Authorization header like this: Authorization: Basic Base64({AppId}:{AppSecret})

Example:

URL:

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

Header:

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

Body:

POST https://api.hqlabs.de/Token?grant_type=authorization_code
                                &code=MWG5HTnFn9n8HJ => 'Code from authorize call'
                                &client_id=1234-testapp  =>'From helloHQ UI'
                                &client_secret=fkgjqoer9tfiealdkcmakwhdf  =>'From helloHQ UI'
                                &scope=read_all write_all

Note: Ensure all query parameters, particularly RedirectUri, are properly URL-encoded.

Access Token Response

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

Parameters:

Example:

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

Once you have received the Access Token, you can use it to request resources from the API.

Resource Request

To retrieve resources from the API, include the Access Token in the Authorization header as follows: Bearer {AccessToken}.

Example:

Authorization: Bearer FGDoJBgK96Z...

Note that Access Tokens expire and must be refreshed using the Refresh Token.

Refresh Token Request

Access Tokens expire, typically after 30 days. You can use the Refresh Token to obtain a new Access Token. The Refresh Token remains valid until the user revokes it.

Parameters:

Example:

POST https://api.hqlabs.de/Token?grant_type=refresh_token&refresh_token=K8vma4VohMb...

Example:

{
  "access_token": "FGDoJBgK96Z...", // The new Access Token
  "token_type": "bearer", // Token type, usually "bearer"
  "expires_in": 1199, // Expiration timespan in seconds
  "refresh_token": "K8vma4VohMb...", // The new Refresh Token
  "user_id": 12, // ID of the user for whom these tokens are valid
  "user_name": "test.user" // The username
}

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

Expand

Using the expand feature allows you to retrieve additional data in a single query. It enables you to access related entities and navigation properties associated with an entity.

To use this feature, include the $expand= parameter in your URL.

Here are some examples demonstrating how to utilize the $expand option.

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

Filters help you construct efficient queries against our API, allowing you to avoid retrieving unnecessary data and filtering on the client side.

To apply a filter, add the $filter= parameter in the URL.

If you want to filter based on a sub-entity, ensure you expand the entity first.

Here are some examples illustrating how to use the filter option.

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

All API responses, along with the bodies of POST and PUT requests, are typically in JSON format and adhere to the OData 4 specification.

In the OData response, the actual data is wrapped in the data field, accompanied by additional metadata.

There are instances where the API provides access to binary data, such as PDFs and images.

For example, documents like invoices and quotations can be retrieved as generated PDF files. When the document is in a draft state, the PDF is created on the fly. Once the document has been sent, the PDF is archived, and the archived version is returned through the API.

You can access the document file's metadata using the following endpoint: /v1/Invoices(id)/DocumentFile

To access the binary stream (PDF) of the document file, use this endpoint: /v1/Invoices(id)/DocumentFile/$value

If you have further questions, please reach out to us at [email protected].

HTTP Codes

Each API request response indicates success through its status code.

Success Status Codes

GET 200 (OK)
POST 201 (Created)
PUT 200 (OK)
DELETE 204 (No Content)
do.Action() 200 (OK) if the base entity was changed
do>.Action() 201 (Created) if a new entity was created

The body of responses with status codes 200 and 201 contains the modified or created object, while responses with a 204 status code always have 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

Date and time information is generally provided in UTC. It is the client's responsibility to convert this information into the user's local time. The user object includes the selected timezone for the user. Properties that contain date and time information in UTC typically end with ...On, such as StartOn or CreatedOn.

However, there are a few exceptions where only the date is relevant. In such cases, date information is provided without a timezone and should not be converted. Date properties end with ...Date, for example, StartDate or ShownDate.

Actions

Actions represent POST operations performed on specific API objects. Some actions may require specific parameters, but not all do. Generally, an action is a more complex operation handled on the server, often involving various data manipulations and object creations. It's important to avoid invoking an action too frequently on the same object due to data manipulation; typically, one call is sufficient to achieve the desired outcome.

When new objects are created during an action, the newly generated object is usually returned. You can find the return value described in the action documentation.

API V2

Authentication

To access the functions of the helloHQ API, authentication is mandatory. You need to authenticate using a valid access token, which verifies your identity and ensures you have the necessary permissions to access the requested resources.

Currently, you can generate an Access Token within helloHQ for API use. In the future, we plan to implement an OAuth flow for authentication.

Access Token

To obtain an access token, log into your helloHQ system.
Under Admin => Settings => API-Clients, you can create and manage your access tokens.


Click the green plus button to create a new token:

In the overview, you can see all the tokens associated with your system. Using the three-dot menu on the right side, you can easily copy or delete a token.

The token contains a wealth of information about both the client and the user. You can specify various options when creating a new token.

Permissions

Permission management is crucial for every API.

In helloHQ, you can choose between two types of access tokens: a sync token and a user-related token.

Sync Token

The sync token is utilized to access the API without a user context. It is used to synchronize data between helloHQ and your application.
This means the token has access to all data within the system.

User Token

The user token provides access to the API within a user context. In this case, the token includes information about the user.
With this token, you will only retrieve data that the user has access to. Additionally, when data is created, it will be created in the subsystem to which the user belongs. This is particularly relevant if you are using subsystems in helloHQ.

Filtering

The helloHQ API supports a wide range of filters that can be applied across all our API controllers.

General information

Please ensure that you encode the URLs you use:

filter=name eq 'hello %26 hq' <- correct
filter=name eq 'hello & hq'   <- incorrect

We use both date-only and date-time properties. All date-time properties are in UTC and end with "On", for example, "StartOn". If the property ends with "Date", it represents a date in the user's local time, typically with the time component set to 00:00:00.000.

Operator

We offer a variety of operations to filter your data precisely according to your needs.

Operator Description Example
eq Equal filter=name eq 'hellohq'
ne Not equal name ne 'hellohq'
gt Greater than price gt 18
ge Greater than or equal price ge 18
lt Less than price lt 18
le Less than or equal price le 18
and Logical AND price ge 18 and price le 30
or Logical OR price lt 18 or price gt 30
not Logical negation not price eq 18

Data Types

Data Type Example
String name eq 'hellohq'
Boolean isActive eq true
Integer price eq 18
Decimal price eq 18.5
DateTime createdOn eq datetime'2021-01-01T12:00:00Z'

Ordering

In some cases, you may want to order the result set of your query. This can be done using the orderby parameter.
For example, you can order the results by the UpdatedOn property to display the most recently updated items first:
orderby=updatedOn desc

Here are some additional examples:

The following statement orders the users by the LastName property in ascending order. If no specific order (ascending asc or descending desc) is defined, ascending order is the default:
/users?orderby=LastName asc

You can also add multiple order statements by listing the properties, separated by commas. Note that spaces before or after the commas are not allowed.
The following URL filters by LastName in ascending order first, and then by FirstName in descending order:
/users?orderby=LastName,FirstName desc

If you want to order by a nested property, separate the properties with a slash:
/projects?orderby=ProjectStatus/Type desc

Pagination

When fetching data from an API, the response can result in a large dataset.
This may lead to slow response times and high data usage. To mitigate this, we have implemented a pagination system.
By default, we limit the results to 1000 items per page. You can adjust this limit by adding the top parameter to the URL, but you cannot exceed the 1000 items per page limit.
To retrieve the next page of results, use the skip parameter, which skips the first n items in the result set.

Example: /v2/Companies?top=1000&skip=1000

To enhance the pagination experience, we have included two headers in the response:

Rate Limit

The number of requests to the API is limited by a rate limit mechanism.
The rate limit is set to 1000 requests per minute.

If the rate limit is exceeded, the API responds with a 429 Too Many Requests status code.

We recommend that developers of client applications read these header values and implement a back-off strategy to fail gracefully and wait for the limit to reset before continuing to make requests.

Endpoints