Aha! provides a REST API that can be accessed directly from another web application or from within a Javascript single page application. The API can be used from any programming language.

This API should be used if you want to create new data in Aha! or extract data from Aha!. If you want to integrate Aha! with another system then you should first consider our guide.

Please email support@aha.io if you have questions or need help while using the API.


All API access is over HTTPS. HTTP requests will be redirected to HTTPS. The API must be accessed using the account specific domain <yourcompany>.aha.io.


All API requests must be appropriately authenticated. Three authentication methods are supported. If you have a choice, OAuth2 is the preferred technique since it avoids the need to provide your Aha! credentials to an external application. If you are building service that calls Aha! outside the context of a user interaction, then an API key is the best approach.

OAuth2 token

Before using an OAuth2 token to authenticate an API call the external application must be registered and the user must authorize the external application to access their account.

Once the user has authorized the application, the OAuth2 access token can be included in the header of the API request:

curl -H "Authorization: Bearer 1111111111" https://company.aha.io/api/v1/features/APP-1

API key

API keys can be generated through the Aha! user interface.

Each API key is specific to a user and an account and will grant access to that account with the permissions of the user that generated it. One user can have multiple API keys and they can be revoked independently.

An API key will continue to work even if the user changes their password.

The API key is used in exactly the same way as an OAuth token in the headers (1111111111 is the API key in this example):

curl -H "Authorization: Bearer 1111111111" https://company.aha.io/api/v1/features/APP-1

HTTP basic authentication

Basic authentication was previously supported. It is not longer recommended since it will be significantly slower than using an API key.


If a request returns multiple items then the result will be paginated. The response includes pagination fields which describe how many records exist in the collection, and which page has been returned, e.g.

  "pagination": [
      "total_records": 2,
      "total_pages": 1,
      "current_page": 1
  "features": [
      "reference_num": "APP-1",
      "name": "Add buttons everywhere",
      "id": "5938362174479841842"
      "reference_num": "APP-2",
      "name": "Second feature",
      "id": "5938399016717176704"

To request a specific page of results, include the page parameter in the URL. Pagination is 1-indexed -- in other words, the first page is page 1, not page 0.

curl https://company.aha.io/api/v1/releases/APP-R-1/features?page=2

The per_page parameter can optionally be used to change the number of records returned in each page, up to a maximum of 200. The default is 30 records per page if the parameter is not set.

curl https://company.aha.io/api/v1/releases/APP-R-1/features?page=2&per_page=100


Possible error status codes are:

  • 403 - the authentication information is incorrect.

  • 400 - there is an error in the construction of the request. The body of the response will contain more detail of the problem.

  • 404 - the requested record could not be found. This may also occur if the user does not have access to the requested record.

  • 429 - the request exceeded the rate limit.

  • 500 - something went wrong on the server. This error should not occur. If it does please report the problem to support@aha.io.

  • 504 - the request timed out as a result of requesting too much data. Try paging the request or limiting the number of fields.

Rate limiting

Calls to the API are rate limited to ensure that one user cannot consume excessive resources. The limits should only affect scripts that are malfunctioning, or attempting to make too many requests in parallel.

Up to 300 requests are allowed per minute, and up to 20 requests per second. If either limit is exceeded in its respective period then subsequent requests will fail with a 429 HTTP status code. The rate limit is applied per source IP address, so multiple API users from the same IP address will contribute to the limit.

If the request is rate limited then additional headers in the response provide information about the rate limit:

X-Ratelimit-Limit: 300
X-Ratelimit-Remaining: 0
X-Ratelimit-Reset: 1498005537

X-Ratelimit-Reset is the UTC unix time when the rate limit will expire and the request can safely be retried.

Response Customization

It is possible to customize which fields will be included in the JSON returned for all API requests. This can be useful to include more fields in a list of records, or to reduce the information returned so that the API result is returned faster. The most common use case is to request additional fields in a list result to avoid the need to make a subsequent request for information about each record in the list.

To specify the desired fields include a query parameter with the namefields and a value corresponding to a list of the desired fields separated by commas. For example this parameter


will include only the name, reference number and status in the returned result.

All fields can be requested using the query parameter:


This is not recommended in a production application because it can significantly slow down API responses. It can be useful during development to see all available fields.

Generally the value to use in the fields parameter is the name of the JSON attribute that you want to have included.

Including a fields parameter will override the default fields that are included in the result and only the requested fields will be returned.

User agent

Each request should contain a customized User-Agent header that includes a method of contacting the developer. We will use this if we observe any problems with your API client.

User-Agent: Test data generation script (fred@aha.io)

Custom Fields

Custom fields are returned (by default, only when requesting a specific record) as an object under the "custom_fields"attribute. They can be manipulated by submitting new data as the payload of a PUT request under the same "custom_fields" attribute, on any record that supports custom fields. This is demonstrated for both scalar and tag-like fields under the documentation for features— but the principle applies to custom fields on all resources.

Notification Email Suppression

Creation of many records in Aha! will trigger email notifications to be sent. This may be undesirable if you are using the API to import records from other systems. Many email notifications can be disabled by includingdisable_mailers=true in the request parameters.