The CareHQ API is RESTful, uses predictable resource-oriented URLs, accepts URL-encoded form data request bodies, returns JSON-encoded responses and uses standard HTTP status codes, authentication and verbs (GET, PUT, PATCH and DELETE).
We recommend creating an API key on your sandbox account for development to avoid modifying live data.
There are a number of other useful recommendations for working with the API in the Integrating your website's enquiry form with CareHQ help article.
https://api.carehq.dev/v1/
https://api.carehq.co.uk/v1/
pip install carehq
composer require carehq/carehq-php
gem install carehq
dotnet add package CareHQ.APIClient
The CareHQ API uses API keys to authenticate requests. You can view and manage your API keys under Account > API keys. You must have the account owner role to manage API keys.
To authenticate requests you make to the API you will need your account Id, an API key and API secret. API keys grant access to your data which may include sensitive and personally identifiable information - keep your API credentials safe! Don't share API credentials in publicly accessible code such as client-side JavaScript or public GitHub repositories.
When you create an API key you will be able to grant it a set of permissions for each resource; typically create, read (list & retrieve), update and delete. By only granting an API key the permissions it needs you can limit the risks associated with another application or service accessing your data.
All API requests must be made over HTTPS and optionally may be restricted to a known list of IP addresses associated with the API key.
Authentication values are sent in request headers. These include a timestamp for the request and a signature generated by hashing the request's URL-encoded form values, timestamp and your API secret. These header values are automatically generated and attached to each request by the SDK client. Your API secret must never be sent with a request.
import carehq
api_client = carehq.APIClient(
account_id=MY_ACCOUNT_ID,
api_key=MY_API_KEY,
api_secret=MY_API_SECRET
)
care_enquiries = api_client('GET', 'care-enquiries')
<?php
require_once('vendor/autoload.php');
$api_client = new CareHQ\APIClient(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
);
$care_enquiries = $api_client->request('GET', 'care-enquiries');
require 'carehq'
api_client = APIClient.new(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
)
care_enquiries = api_client.request('GET', 'care-enquiries')
using CareHQ;
using System.Net.Http;
using System.Text.Json;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
ApiClient apiClient = new ApiClient(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
);
var absences = apiClient.Request(
HttpMethod.Get,
"absences",
new MultiValueDict()
.Add(
"attributes",
"ends",
"notes",
"reason_for_absence",
"starts"
)
);
}
}
}
The CareHQ API enforces a rate limit of 10 requests per second per API key. We use rate limits to help ensure the API is stable and responsive at all times.
If you exceed the rate limit your SDK client will raise an RateLimitExceeded exception based on a 429 HTTP status code being returned from the server.
Each HTTP response from the API includes additional headers that provide;
This information can be accessed via the SDK client and used to determine if you need to wait before making the next request. If multiple clients will be using the same API key concurrently then you will still need to handle RateLimitExceeded exceptions.
import carehq
import time
api_client = carehq.APIClient(
account_id=MY_ACCOUNT_ID,
api_key=MY_API_KEY,
api_secret=MY_API_SECRET
)
def call_api(*args, **kwargs):
"""
Call the API and handle rate limits by waiting until the limit resets.
"""
if api_client.rate_limit_remaining is not None:
if not api_client.rate_limit_remaining:
time.sleep(api_client.rate_limit_reset - time.time())
try:
response = api_client(*args, **kwargs)
except RateLimitExceeded as error:
response = call_api(*args, **kwargs)
return response
care_enquiries = call_api('GET', 'care-enquiries')
<?php
require_once('vendor/autoload.php');
$api_client = new CareHQ\APIClient(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
);
/**
* Call the API and handle rate limits by waiting until the
* limit resets.
*/
function call_api(
$api_client,
$method,
$path,
$params=NULL,
$data=NULL
) {
if ($api_client->rate_limit_remaining === 0) {
sleep($api_client->rate_limit_reset - time());
}
try {
$response = $api_client->request(
$method,
$path,
$params,
$data
);
} catch (CareHQ\Exception\RateLimitExceeded $error) {
$response = call_api(
$api_client,
$method,
$path,
$params,
$data
);
}
return $response;
}
$care_enquiries = call_api($api_client, 'GET', 'care-enquiries');
require 'carehq'
require 'carehq/exceptions'
api_client = APIClient.new(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
)
def call_api(api_client, method, path, params: nil, data: nil)
# Call the API and handle rate limits by waiting until the limit resets.
if not api_client.rate_limit_remaining.nil?
if (api_client.rate_limit_remaining or 0) <= 0
sleep(api_client.rate_limit_reset - Time.now.to_f)
end
end
begin
response = api_client.request(method, path, params: params, data: data)
rescue RateLimitExceeded => error
response = call_api(method, path, params: params, data: data)
end
return response
end
care_enquiries = call_api(api_client, 'GET', 'care-enquiries')
using CareHQ;
using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
ApiClient apiClient = new ApiClient(
"MY_ACCOUNT_ID",
"MY_API_KEY",
"MY_API_SECRET",
);
JsonDocument absences = CallApi(
apiClient,
HttpMethod.Get,
"care-enquiries"
);
if (absences != null)
Console.WriteLine(absences.RootElement.ToString());
}
/// <summary>
/// Call the API and handle rate limits by waiting until the limit resets
/// </summary>
/// <returns>Returns a JsonDocument</returns>
private static JsonDocument CallApi(
ApiClient apiClient,
HttpMethod method,
string path,
MultiValueDict parameters = null,
MultiValueDict data = null
)
{
JsonDocument response = null;
if (apiClient.RateLimitRemaining == 0)
Thread.Sleep((int)(apiClient.RateLimitReset - DateTimeOffset.UtcNow.ToUnixTimeSeconds()) * 1000);
try
{
response = apiClient.Request(
method,
path,
parameters,
data
);
}
catch (CareHQ.Exception.RateLimitExceeded ex)
{
response = CallApi(
apiClient,
method,
path,
parameters,
data
);
}
return response;
}
}
}
The API accepts URL-encoded form data.
The API returns JSON data.
HTTP responses from the API with a status code in the 4xx range represent an error with the request (e.g. a requested resource does not exist, or a required parameter is missing). A status code in the 5xx range indicates an error with the CareHQ API.
Errors are typically handled by capturing them as exceptions raised when calling the API.
A descriptive hint as to the reason for the error.
When applicable the arg_errors attribute will be present and provide a dictionary of invalid parameters (as the keys) and validation errors (a list of strings) for each parameter (as the values).
import carehq
api_client = carehq.APIClient(
account_id=MY_ACCOUNT_ID,
api_key=MY_API_KEY,
api_secret=MY_API_SECRET
)
try:
api_client('GET', 'care-enquiries')
except carehq.exceptions.APIException as error:
print(error)
<?php
require_once('vendor/autoload.php');
$api_client = new CareHQ\APIClient(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
);
try {
$response = $api_client->request('GET', 'care-enquiries');
} catch (CareHQ\Exception\APIException $error) {
echo($error);
}
require 'carehq'
require 'carehq/exceptions'
api_client = APIClient.new(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
)
begin
client.request('GET', 'care-enquiries')
rescue APIException => error
print(error)
end
using CareHQ;
using System;
using System.Net.Http;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
ApiClient apiClient = new ApiClient(
MY_ACCOUNT_ID,
MY_API_KEY,
MY_API_SECRET
);
try
{
apiClient.Request(
HttpMethod.Get,
"care-enquiries"
);
}
catch (CareHQ.Exception.APIException error)
{
Console.WriteLine(error);
}
}
}
}
All resources can be fetched in bulk using a resource's list API method. Resources fetched using the list action are paginated returning one page per request.
By default pages contain a maximum of 10 resources, but this number can be increased to 100.
API methods that return paginated results share a common interface that supports the following parameters:
['_id']
1
10