Introduction
Welcome to the HOALife API Documentation. HOALife's API is intended to be consumed by programmers to consume or generate data with the HOALife system.
While this documentation is comprehensive, access to some endpoints may not be included in all Customer Agreements. Contact sales@hoalife.com to learn more.
The API provides scoped Read, Write, Update, and Destroy actions for most resources.
JSON is the only currently supported response format, following the JSON:API spec. All responses will have the application/vnd.api+json
content type. Any POST
or PUT
requests must specify the application/vnd.api+json
Content-Type
header.
API Clients
This API is completely accessible without an API Client, however, we do provide some API Clients to allow you to leverage this API without worrying about implementation details.
Ruby
The hoalife
Ruby gem will seamlessly take care of this API's authentication, signature verification, rate limiting, pagination, and error handling.
$ gem install hoalife
View the README for usage details and examples.
Authentication
via HTTP Header
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl https://api.hoalife.com/api/ \
-H "Authorization: Token sk_SUPERSECRET"
Make sure to replace
sk_SUPERSECRET
with your API key.
HOALife expects for the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Token sk_SUPERSECRET
via Basic Authentication
To authorize, use this code:
# cURL will encode the username and password in the header for you. YMMV with other libraries.
curl https://sk_SUPERSECRET:sk_SUPERSECRET@api.hoalife.com/api/
Make sure to replace
sk_SUPERSECRET
with your API key.
When using Basic Authentication, enter your API key for both the username and password. cURL will Base64 and encode these for you, sending the Authorization
header as follows:
Authorization: Basic c2tfU1VQRVJTRUNSRVQ6c2tfU1VQRVJTRUNSRVQ=
via URL Parameter
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl https://api.hoalife.com/api/?api_key=sk_SUPERSECRET
Make sure to replace
sk_SUPERSECRET
with your API key.
Passing your API key via URL parameter is also possible. This is helpful when testing requests via a web browser.
Rate Limit
To ensure a consistent and reliable service, this API limits the number of requests per API key within a given time frame. The default limit is 1 requests
per 2 seconds
. The rate limit is enforced as a GCRA "Leaky Bucket". Higher volume rate limits are available per the Customer Agreement. Contact sales@hoalife.com to learn more.
Every request has HTTP headers to help you stay within limits and be a well-behaving API client. Exceeding these limits will result in a 429
. Continued requests after a 429
may result in requests from your IP being blocked.
HTTP Header Name | Description |
---|---|
X-RateLimit-Limit | The maximum number of requests per period |
X-RateLimit-Period | The period, in seconds, that the limit is enforced |
X-RateLimit-Used | The number of consumed requests within the period |
X-RateLimit-Remaining | The number of remaining requests within the period |
Accommodating the rate limit could be as simple as this pseudo-code sleep 2sec if X-RateLimit-Remaining < 1
.
Verify Authenticity
Paranoid? No problem. All responses provided by this API are signed via HMAC SHA256
.
A signature is created by generating an HMAC of the raw response body with a SHA256
digest, using the shared Signing Secret. You'll find this signature in the HTTP header X-Signature
.
def verified?
digest = OpenSSL::Digest.new("sha256")
OpenSSL::HMAC.hexdigest(digest, "ss_SUPERSECRET", response.body) == response.headers["X-Signature"]
end
Make sure to replace
ss_SUPERSECRET
with your provided Signing Secret.
Querying, Ordering, and Pagination
Querying
Most attributes of a resource are query-able so that you can filter resource collections based on an attribute. Include the attribute as a query parameter in the URL external_id=EXT42
.
By default, exact matching will be used. If you'd like to craft an approximate query, you can specify the operator as part of the parameter value.
Operator | Example | SQL equivalent |
---|---|---|
default | foo=4 |
foo = 4 |
gt |
foo=gt,4 |
foo > 4 |
gte |
foo=gte,4 |
foo >= 4 |
lt |
foo=lt,4 |
foo < 4 |
lte |
foo=lte,4 |
foo <= 4 |
ilike |
bar=ilike,%25BAZ%25 |
bar ILIKE %BAZ% |
!= |
foo=!=,4 |
foo != 4 |
Ordering
You can specify the order of a resource collection by passing the order
URL query parameter order=foo
.
By default, the resource will be ordered by the created_at
attribute in ascending order. You can specify the direction of the order clause by specifying asc
or desc
as part of the parameter value.
Operator | Example | SQL equivalent |
---|---|---|
default | order=foo |
ORDER BY foo ASC |
asc |
order=foo&order_dir=asc |
ORDER BY foo ASC |
desc |
order=foo&order_dir=desc |
ORDER BY foo DESC |
Pagination
Recourse collections are paginated, with 25 resources per page. Traversing pages can be done via the page=X
URL query parameter.
There are a number of helpful attributes in a collection response to help you traverse pages. If you have specified order or query attributes, they will be reflected in the pagination links.
"meta": {
"total": 167,
"total_pages": 7
},
"links": {
"self": "/api/accounts/1/properties?page=1",
"next": "/api/accounts/1/properties?page=2",
"prev": "/api/accounts/1/properties"
}
Accounts
Accounts represent both Associations which are managed, and Management companies.
Get All Accounts
curl "https://api.hoalife.com/api/accounts" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "account",
"attributes": {
"id": 1,
"parent_id": null,
"name": "XYZ HOA Management",
"repeat_violation_strategy": "six_month_rolling_window",
"escalation_threshold": 3,
"violation_lookback_period": "two_months",
"mailing_street_1": "123 HOALife Way",
"mailing_street_2": null,
"mailing_city": "Sun Valley",
"mailing_state": "ID",
"mailing_postal_code": "83313",
"organizational": true,
"external_id": null,
"created_at": "2019-07-30T21:16:44.624Z",
"updated_at": "2019-08-01T14:49:17.016Z"
},
"relationships": {}
},
{
"id": "2",
"type": "account",
"attributes": {
"id": 2,
"parent_id": 1,
"name": "Goodview HOA",
"repeat_violation_strategy": "six_month_rolling_window",
"escalation_threshold": null,
"violation_lookback_period": null,
"mailing_street_1": "123 Goodview Dr",
"mailing_street_2": null,
"mailing_city": "Ketchum",
"mailing_state": "ID",
"mailing_postal_code": "83340",
"organizational": false,
"external_id": null,
"created_at": "2019-07-30T21:16:44.640Z",
"updated_at": "2019-07-31T15:44:01.644Z"
},
"relationships": {}
},
{
"id": "3",
"type": "account",
"attributes": {
"id": 3,
"parent_id": 1,
"name": "Sleepyville HOA",
"repeat_violation_strategy": "six_month_rolling_window",
"escalation_threshold": null,
"violation_lookback_period": null,
"mailing_street_1": "123 Sleepy Ct",
"mailing_street_2": null,
"mailing_city": "Sun Valley",
"mailing_state": "ID",
"mailing_postal_code": "83353",
"organizational": false,
"external_id": null,
"created_at": "2019-08-01T14:37:15.287Z",
"updated_at": "2019-08-01T14:37:15.287Z"
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 3,
"total_pages": 1
},
"links": {
"self": "/api/accounts?page=1",
"next": "/api/accounts",
"prev": "/api/accounts"
}
}
This endpoint retrieves all Accounts accessible by the API key.
HTTP Request
GET https://api.hoalife.com/api/accounts
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of an Account |
parent_id | Integer | Unique identifier of parent organizational Account |
name | String | Name of an Account |
escalation_threshold | Integer | Number of repeat Violations which trigger the creation of an Escalation |
mailing_street_1 | String | Mailing street address used on violation notices |
mailing_street_2 | String | Mailing street address used on violation notices |
mailing_city | String | Mailing city address used on violation notices |
mailing_state | String | Mailing state address used on violation notices |
mailing_postal_code | String | Mailing postal code address used on violation notices |
repeat_violation_strategy | String | Strategy for calculating repeat Violations |
violation_lookback_period | Integer | Number of days to warn about prior Violations |
external_id | String | A unique identifier from an external system used to map the record |
organizational | Boolean | Indicates if the Account is organizational (Management Company) or not (Association) |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
parent_id | false | false |
name | true | true |
escalation_threshold | true | true |
mailing_street_1 | true | true |
mailing_street_2 | true | true |
mailing_city | true | true |
mailing_state | true | true |
mailing_postal_code | true | true |
repeat_violation_strategy | false | false |
violation_lookback_period | false | false |
external_id | true | false |
organizational | false | false |
Create Account
curl "https://api.hoalife.com/api/accounts" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "account",
"attributes": {
"name": "Foo Bar22",
"external_id": "123",
"organizational": false
},
"relationships": {
"parent": {
"data": {
"type": "account",
"id": 5
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "731",
"type": "account",
"attributes": {
"id": 42,
"name": "Foo Bar",
"organizational": false,
"created_at": "2019-08-12T23:53:04.537Z",
"updated_at": "2019-08-12T23:53:04.537Z",
"repeat_violation_strategy": "six_month_rolling_window",
"external_id": "123",
"parent_id": 5,
"violation_lookback_period": 0,
"escalation_threshold": null,
"mailing_street_2": null,
"mailing_street_1": null,
"mailing_city": null,
"mailing_state": null,
"mailing_postal_code": null
},
"relationships": {}
}
}
This endpoint creates a new Account.
HTTP Request
POST https://api.hoalife.com/api/accounts
Account Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
parent_id | Integer | Unique identifier of parent organizational Account | true |
name | String | Name of an Account | true |
external_id | String | A unique identifier from an external system used to map the record | true |
escalation_threshold | Integer | Number of repeat Violations which trigger the creation of an Escalation | false |
mailing_street_1 | String | Mailing street address used on violation notices | false |
mailing_street_2 | String | Mailing street address used on violation notices | false |
mailing_city | String | Mailing city address used on violation notices | false |
mailing_state | String | Mailing state address used on violation notices | false |
mailing_postal_code | String | Mailing postal code address used on violation notices | false |
repeat_violation_strategy | String | Strategy for calculating repeat Violations | false |
violation_lookback_period | Integer | Number of days to warn about prior Violations | false |
organizational | Boolean | Indicates if the Account is organizational (Management Company) or not (Association) | false |
Writable Attribute Requirements
Some attributes have strict requirements.
Parameter | Options | Default |
---|---|---|
repeat_violation_strategy | consecutive , one_month_rolling_window , three_month_rolling_window , six_month_rolling_window , one_year_rolling_window |
six_month_rolling_window |
violation_lookback_period | 0 , 30 , 60 , 90 , 120 , 150 , 180 , 365 |
0 |
Update Account
curl "https://api.hoalife.com/api/accounts/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "account",
"attributes": {
"name": "Foo Bar22"
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing Account.
HTTP Request
PUT https://api.hoalife.com/api/accounts/:account_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:account_id | Integer | Unique identifier of the Account the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The parent Account cannot be changed.
Destroy Account
curl "https://api.hoalife.com/api/accounts/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Account. Because Account objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the Account even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/accounts/:account_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:account_id | Integer | Unique identifier of the Account the request is being made for |
Users
Users with access to the given Account
and any child accounts.
Get All Users
curl "https://api.hoalife.com/api/users" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "user",
"attributes": {
"id": 1,
"email": "admin@example.com",
"first_name": "Bob",
"last_name": "Admin",
"timezone": "Mountain Time (US & Canada)",
"authorizations": [
{
"id": 444,
"account_id": 1,
"role": "administrator"
}
]
}
},
{
"id": "2",
"type": "user",
"attributes": {
"id": 2,
"email": "sub-account-manager@example.com",
"first_name": "Jane",
"last_name": "SubAccountManger",
"timezone": "Pacific Time (US & Canada)",
"authorizations": [
{
"id": 555,
"account_id": 2,
"role": "manager"
},
{
"id": 556,
"account_id": 3,
"role": "manager"
}
]
}
},
{
"id": "3",
"type": "user",
"attributes": {
"id": 3,
"email": "inspector@example.com",
"first_name": "Sally",
"last_name": "Inspector",
"timezone": "Eastern Time (US & Canada)",
"authorizations": [
{
"id": 777,
"account_id": 4,
"role": "inspector"
}
]
}
}
],
"meta": {
"current_page": 1,
"total": 3,
"total_pages": 1
},
"links": {
"self": "/api/users?page=1",
"next": "/api/users",
"prev": "/api/users"
}
}
This endpoint retrieves all Users accessible by the API key. If the API key has access to multiple Accounts, all Users for all those accounts will be returned. Scope Users to a specific Account by adding an account_id
query parameter. Users may have many authorizations to many different accounts.
HTTP Request
GET https://api.hoalife.com/api/users
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the User |
String | Email address of the User | |
first_name | String | User's first name |
last_name | String | User's last name |
timezone | String | String representing a user's timezone |
authorizations | Array[Object] | Accounts which the user has been authorized to access with a given role |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
true | true | |
first_name | true | true |
last_name | true | true |
account_id | true | false |
role | true | false |
User Authorizations
User Authorizations to the given Account
and any child accounts.
Get All User Authorizations
curl "https://api.hoalife.com/api/users/authorizations" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "111",
"type": "authorization",
"attributes": {
"id": 111,
"role": "staff",
"account_id": 1,
"user": {
"id": 1,
"email": "bob@example.com",
"first_name": "Bob",
"last_name": "Smith",
"timezone": "Mountain Time (US & Canada)"
}
},
"relationships": {}
},
{
"id": "222",
"type": "authorization",
"attributes": {
"id": 222,
"role": "read_only",
"account_id": 1,
"user": {
"id": 2,
"email": "boardmember@example.com",
"first_name": "Board",
"last_name": "Member",
"timezone": "Mountain Time (US & Canada)"
}
},
"relationships": {}
},
],
"meta": {
"current_page": 1,
"total": 2,
"total_pages": 1
},
"links": {
"self": "/api/users/authorizations?page=1",
"next": "/api/users/authorizations",
"prev": "/api/users/authorizations"
}
}
This endpoint retrieves all User Authorizations accessible by the API key. If the API key has access to multiple Accounts, all User Authorizations for all those accounts will be returned. Scope User Authorizations to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/users/authorizations
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the User Authorization |
role | String | The authorization level for the User |
account_id | Integer | Unique identifier of the Account the Authorization is for |
user | Object | Information about the User the Authorization is for |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
role | true | true |
true | false | |
first_name | true | false |
last_name | true | false |
Create User Authorization
When creating a User Authorization, passing the user's information is recommended. If a User does not exist for a given email address, a user will be created. If the User does exist, the record will be looked up by the email
attribute.
Alternatively, if the User already exists and you know the User's id
, you can pass the id
via a relationship. The former method is preferred to avoid an additional API request.
Only one Authorization per User per Account is possible. Per Account hierarchy branch User Authorizations are encouraged to scope a User's access. Multiple User Authorizations throughout the same Account hierarchy branch is possible, but not recommended.
Available roles are administrator
, manager
, staff
, inspector
, and read_only
.
curl "https://api.hoalife.com/api/users/authorizations" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "authorization",
"attributes": {
"role": "read_only",
"send_invitation_email": false,
"user": {
"first_name": "Bob",
"last_name": "Smith",
"email": "bob@example.com"
}
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": 5
}
}
}
}
}
'
# OR
curl "https://api.hoalife.com/api/users/authorizations" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "authorization",
"attributes": {
"role": "read_only",
"send_invitation_email": false
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": 5
}
},
"user": {
"data": {
"type": "user",
"id": 2
}
},
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "3333",
"type": "authorization",
"attributes": {
"id": 3333,
"role": "read_only",
"account_id": 5,
"user": {
"id": 1,
"email": "bob@example.com",
"first_name": "Bob",
"last_name": "Smith",
"timezone": "Mountain Time (US & Canada)"
}
}
},
"relationships": {}
}
}
This endpoint creates a User Authorization.
HTTP Request
POST https://api.hoalife.com/api/users/authorizations
User Authorization Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
role | String | The authorization level for the User | true |
account_id | Integer | Unique identifier of the Account the Authorization is for | true |
User[first_name] | String | User's first name | true |
User[last_name] | String | User's last name | true |
User[email_name] | String | User's email | true |
Update User Authorization
curl "https://api.hoalife.com/api/users/authorization/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "authorization",
"attributes": {
"role": "read_only"
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing User Authorization.
HTTP Request
PUT https://api.hoalife.com/api/users/authorization/:user_authorization_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:user_authorization_id | Integer | Unique identifier of the User Authorization the request is being made for |
Editable Attributes
Only the role
attribute is editable for a User Authorization.
Destroy User Authorization
curl "https://api.hoalife.com/api/users/authorization/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing User Authorization.
HTTP Request
DELETE https://api.hoalife.com/api/user_authorization/:user_authorization_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:user_authorization_id | Integer | Unique identifier of the User Authorization the request is being made for |
Properties
Properties represent a property or unit in an Association.
Get All Properties
curl "https://api.hoalife.com/api/properties" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "property",
"attributes": {
"id": 1,
"account_id": 2,
"formatted_id": "PRP-1",
"street_1": "944 Awesome Street",
"street_2": null,
"city": "Sun Valley",
"state": "ID",
"postal_code": "83353",
"override_geocoding": false,
"latitude": "37.233333",
"longitude": "-115.808333",
"route_leg": null,
"route": "Awesome Street",
"emails": [
"johnAndJudySmithOnFacebook@aol.com"
],
"phone_numbers": [],
"created_at": "2019-07-30T21:16:45.265Z",
"updated_at": "2019-07-30T21:16:45.265Z",
"mailing_name": "John and Judy Smith",
"mailing_street_1": "944 Awesome Street",
"mailing_street_2": null,
"mailing_city": "Sun Valley",
"mailing_state": "ID",
"mailing_postal_code": "83353",
"notes": [
{
"body_text": "Neighbor has complained about poor lawn hygiene.",
"author": "John Owner",
"pinned": true,
"created_at": "2019-08-05T03:26:02.917Z"
}
],
"tags":[{"title":"Board Member","id":1,"color":"#6fa7ce"}],
"external_id": null
},
"relationships": {}
},
...
{
"id": "25",
"type": "property",
"attributes": {
"id": 25,
"account_id": 2,
"formatted_id": "PRP-25",
"street_1": "4242 Cowbell Drive",
"street_2": null,
"city": "Sun Valley",
"state": "ID",
"postal_code": "83353",
"override_geocoding": false,
"latitude": "37.233333",
"longitude": "-115.808333",
"route_leg": null,
"route": "Cowbell Drive",
"emails": [
"earl-larae@cowbelldrive.com", "earl-larae@yahsnooze.com"
],
"phone_numbers": [
"+132155512345", "+132155512346"
],
"created_at": "2019-07-30T21:16:45.460Z",
"updated_at": "2019-07-30T21:16:45.460Z",
"mailing_name": "Earl LaRae",
"mailing_street_1": "PO BOX 42424242",
"mailing_street_2": null,
"mailing_city": "Sun Valley",
"mailing_state": "ID",
"mailing_postal_code": "83353",
"notes": [],
"tags": [],
"external_id": null
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 858,
"total_pages": 35
},
"links": {
"self": "/api/properties?page=1",
"next": "/api/properties?page=2",
"prev": "/api/properties"
}
}
This endpoint retrieves all Properties accessible by the API key. If the API key has access to multiple Accounts, all Properties for all those accounts will be returned. Scope Properties to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/properties
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Property |
account_id | Integer | Unique identifier of Account the Property belongs to |
formatted_id | String | Humanized unique identifier |
street_1 | String | Street address of the property |
street_2 | String | Street address of the property |
city | String | City of the property |
state | String | State of the property |
postal_code | String | Postal code of the property |
override_geocoding | Boolean | Manually specified latitude and longitude or attempt to geocode the property's address. |
latitude | String | GPS Latitude coordinate |
longitude | String | GPS Longitude coordinate |
route_leg | String | Leg of a given route |
route | String | Inspection route |
emails | Array[String] | Array of strings of the property owner's email addresses |
phone_numbers | Array[String] | Array of strings of the property owner's phone numbers |
mailing_name | String | Mailing name of the property |
mailing_street_1 | String | Mailing street address of the property |
mailing_street_2 | String | Mailing street address of the property |
mailing_city | String | Mailing city address of the property |
mailing_state | String | Mailing state address of the property |
mailing_postal_code | String | Mailing postal code address of the property |
notes | Array[Object] | Property notes |
tags | Array[Object] | Property tags |
external_id | String | A unique identifier from an external system used to map the record |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
formatted_id | true | true |
street_1 | true | true |
street_2 | true | true |
city | true | true |
state | true | true |
postal_code | true | true |
override_geocoding | true | true |
latitude | true | true |
longitude | true | true |
route_leg | true | true |
route | true | true |
emails | false | false |
phone_numbers | false | false |
mailing_name | true | true |
mailing_street_1 | true | true |
mailing_street_2 | true | true |
mailing_city | true | true |
mailing_state | true | true |
mailing_postal_code | true | true |
notes | false | false |
tags | false | false |
external_id | true | true |
Create Property
curl "https://api.hoalife.com/api/properties" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "property",
"attributes": {
"street_1": "4242 Cowbell Drive",
"city": "Sun Valley",
"state": "ID",
"postal_code": "83353",
"external_id": "123"
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": 5
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "25",
"type": "property",
"attributes": {
"id": 25,
"account_id": 5,
"formatted_id": "PRP-25",
"street_1": "4242 Cowbell Drive",
"street_2": null,
"city": "Sun Valley",
"state": "ID",
"postal_code": "83353",
"override_geocoding": false,
"latitude": "37.233333",
"longitude": "-115.808333",
"route_leg": null,
"route": "Cowbell Drive",
"emails": [
"earl-larae@cowbelldrive.com", "earl-larae@yahsnooze.com"
],
"phone_numbers": [
"+132155512345", "+132155512346"
],
"created_at": "2019-07-30T21:16:45.460Z",
"updated_at": "2019-07-30T21:16:45.460Z",
"mailing_name": "Earl LaRae",
"mailing_street_1": "PO BOX 42424242",
"mailing_street_2": null,
"mailing_city": "Sun Valley",
"mailing_state": "ID",
"mailing_postal_code": "83353",
"notes": [],
"external_id": "123"
},
},
"relationships": {}
}
}
This endpoint creates a new Property.
HTTP Request
POST https://api.hoalife.com/api/properties
Property Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
account_id | Integer | Unique identifier of Account the Property belongs to | true |
street_1 | String | Street address of the property | true |
street_2 | String | Street address of the property | false |
city | String | City of the property | true |
state | String | State of the property | true |
postal_code | String | Postal code of the property | true |
override_geocoding | Boolean | Use the supplied latitude and longitude or automatically geocode the property's address. Default false. | false |
latitude | Float | GPS Latitude coordinate of the Property | false |
longitude | Float | GPS Longitude coordinate of the Property | false |
route | String | Inspection route property belongs to, such as the property street name. May be overridden if override_geocoding is false. |
false |
route_leg | String | Inspection sub-route property belongs to, such as 'odd' or 'A'. May be overridden if override_geocoding is false. |
false |
emails | Array[String] | Array of strings of the property owner's email addresses | false |
phone_numbers | Array[String] | Array of strings of the property owner's phone numbers | false |
mailing_name | String | Mailing street address of the property | false* |
mailing_street_1 | String | Mailing street address of the property | false |
mailing_street_2 | String | Mailing street address of the property | false |
mailing_city | String | Mailing city address of the property | false* |
mailing_state | String | Mailing state address of the property | false* |
mailing_postal_code | String | Mailing postal code address of the property | false* |
tags | Array[String] | Array of strings representing the tag ids or titles | false |
external_id | String | A unique identifier from an external system used to map the record | false |
- Required if
mailing_street_1
is not blank.
Update Property
curl "https://api.hoalife.com/api/properties/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "property",
"attributes": {
"street_1": "123 Updated St",
"tags": ["1", "Board Member"]
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing Property.
HTTP Request
PUT https://api.hoalife.com/api/properties/:property_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:property_id | Integer | Unique identifier of the Property the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The associated Account cannot be changed.
Destroy Property
curl "https://api.hoalife.com/api/properties/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Property. Because Property objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the Property even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/properties/:property_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:property_id | Integer | Unique identifier of the Property the request is being made for |
Property Supplemental Mailing Addresses
Supplemental mailing addresses for properties. The primary property mailing address should be provided as Property data.
Get All Property Supplemental Mailing Addresses
curl "https://api.hoalife.com/api/properties/supplemental_mailing_addressses" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"data": [
{
"id": "1",
"type": "supplemental_mailing_address",
"attributes": {
"id": 1,
"property_id": 42,
"send_notices": true,
"mailing_name": "John Smith",
"mailing_street_1": "1234 Tall Oak Court",
"mailing_street_2": "",
"mailing_city": "Low Point",
"mailing_state": "NC",
"mailing_postal_code": "23365",
"external_id": "abc-123"
},
"relationships": {}
},
{
"id": "2",
"type": "supplemental_mailing_address",
"attributes": {
"id": 2,
"property_id": 42,
"send_notices": false,
"mailing_name": "Jane Smith",
"mailing_street_1": "22558 Casa Grande Drive",
"mailing_street_2": "",
"mailing_city": "Cookersfield",
"mailing_state": "IA",
"mailing_postal_code": "91106",
"external_id": "abc-122"
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 2,
"total_pages": 1
"self": "/api/properties/supplemental_mailing_addresses?page=1",
"next": "/api/properties/supplemental_mailing_addresses?page=2",
"prev": "/api/properties/supplemental_mailing_addresses"
}
}
This endpoint retrieves all Property Supplemental Mailing Addresses for the given Property ID.
This endpoint retrieves all Property Supplemental Mailing Addresses accessible by the API key. If the API key has access to multiple Accounts, all Properties for all those accounts will be returned. Scope Property Supplemental Mailing Addresses to a specific Property by adding an property_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/properties/supplemental_mailing_addresses
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Property |
property_id | Integer | Unique identifier of the Property belongs to the Supplemental Mailing Address belongs to |
mailing_name | String | Mailing name |
mailing_street_1 | String | Mailing street address |
mailing_street_2 | String | Mailing street address |
mailing_city | String | Mailing city address |
mailing_state | String | Mailing state address |
mailing_postal_code | String | Mailing postal code address |
external_id | String | A unique identifier from an external system used to map the record |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
property_id | true | true |
mailing_name | true | true |
mailing_street_1 | true | true |
mailing_street_2 | true | true |
mailing_city | true | true |
mailing_state | true | true |
mailing_postal_code | true | true |
external_id | true | true |
Create Property Supplemental Mailing Address
curl "https://api.hoalife.com/api/properties/supplemental_mailing_address" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "supplemental_mailing_address",
"attributes": {
"mailing_name": "Jane Smith",
"mailing_street_1": "22558 Casa Grande Drive",
"mailing_city": "Cookersfield",
"mailing_state": "IA",
"mailing_postal_code": "91106",
"send_notices": true,
"external_id": "abc-123"
},
"relationships": {
"property": {
"data": {
"type": "property",
"id": 42
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "25",
"type": "supplemental_mailing_address",
"attributes": {
"id": 2,
"property_id": 42,
"send_notices": true,
"mailing_name": "Jane Smith",
"mailing_street_1": "22558 Casa Grande Drive",
"mailing_street_2": "",
"mailing_city": "Cookersfield",
"mailing_state": "IA",
"mailing_postal_code": "91106",
"external_id": "abc-123"
},
},
"relationships": {}
}
}
This endpoint creates a new Property Supplemental Mailing Address.
HTTP Request
POST https://api.hoalife.com/api/properties/supplemental_mailing_address
Property Supplemental Mailing Address Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
property_id | Integer | Unique identifier of the Property the Supplemental Mailing Address belongs to | true |
mailing_name | String | Mailing street address | true |
mailing_street_1 | String | Mailing street address | true |
mailing_street_2 | String | Mailing street address | false |
mailing_city | String | Mailing city address | true |
mailing_state | String | Mailing state address | true |
mailing_postal_code | String | Mailing postal code address | true |
send_notices | Boolean | Notices be sent to this address | false |
external_id | String | A unique identifier from an external system used to map the record | false |
Update Property Supplemental Mailing Address
curl "https://api.hoalife.com/api/properties/supplemental_mailing_addresses/25" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "supplemental_mailing_address",
"attributes": {
"mailing_name": "Josh Carunner",
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing Property Supplemental Mailing Address.
HTTP Request
PUT https://api.hoalife.com/api/properties/supplemental_mailing_addresses/:supplemental_mailing_addresses_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:supplemental_mailing_addresses_id | Integer | Unique identifier of the Property Supplemental Mailing Address the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The associated Property cannot be changed.
Destroy Property
curl "https://api.hoalife.com/api/properties/supplemental_mailing_addresses/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Property Supplemental Mailing Address.
HTTP Request
DELETE https://api.hoalife.com/api/properties/supplemental_mailing_addresses/:supplemental_mailing_addresses_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:supplemental_mailing_addresses_id | Integer | Unique identifier of the Property Supplemental Mailing Address the request is being made for |
Assets
Assets represent a asset or common area in an association.
Get All Assets
curl "https://api.hoalife.com/api/assets" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "asset",
"attributes": {
"id": 1,
"account_id": 2,
"formatted_id": "AST-1",
"description": "Pool",
"latitude": "37.233333",
"longitude": "-115.808333",
"created_at": "2019-07-30T21:16:45.460Z",
"updated_at": "2019-07-30T21:16:45.460Z",
"external_id": null
},
"relationships": {}
},
...
{
"id": "25",
"type": "asset",
"attributes": {
"id": 25,
"account_id": 2,
"formatted_id": "AST-25",
"description": "West Entrence Common Area",
"latitude": "37.233333",
"longitude": "-115.808333",
"created_at": "2019-07-30T21:16:45.460Z",
"updated_at": "2019-07-30T21:16:45.460Z",
"external_id": null
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 858,
"total_pages": 35
},
"links": {
"self": "/api/assets?page=1",
"next": "/api/assets?page=2",
"prev": "/api/assets"
}
}
This endpoint retrieves all Assets accessible by the API key. If the API key has access to multiple Accounts, all Assets for all those accounts will be returned. Scope Assets to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/assets
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Asset |
account_id | Integer | Unique identifier of Account the Asset belongs to |
formatted_id | String | Humanized unique identifier |
description | String | Description of the asset |
latitude | String | GPS Latitude coordinate |
longitude | String | GPS Longitude coordinate |
external_id | String | A unique identifier from an external system used to map the record |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
formatted_id | true | true |
description | true | true |
latitude | true | true |
longitude | true | true |
external_id | true | true |
Create Asset
curl "https://api.hoalife.com/api/assets" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "asset",
"attributes": {
"description": "4242 Cowbell Drive",
"latitude": "37.233333",
"longitude": "-115.808333",
"external_id": "123"
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": 5
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "25",
"type": "asset",
"attributes": {
"id": 25,
"account_id": 5,
"formatted_id": "AST-25",
"latitude": "37.233333",
"longitude": "-115.808333",
"created_at": "2019-07-30T21:16:45.460Z",
"updated_at": "2019-07-30T21:16:45.460Z",
"external_id": "123"
},
},
"relationships": {}
}
}
This endpoint creates a new Asset.
HTTP Request
POST https://api.hoalife.com/api/assets
Asset Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
account_id | Integer | Unique identifier of Account the Asset belongs to | true |
description | String | Description the Asset | true |
latitude | Float | GPS Latitude coordinate of the Asset | false |
longitude | Float | GPS Longitude coordinate of the Asset | false |
external_id | String | A unique identifier from an external system used to map the record | false |
Update Asset
curl "https://api.hoalife.com/api/assets/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "asset",
"attributes": {
"description": "Common aread West entrance"
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing Asset.
HTTP Request
PUT https://api.hoalife.com/api/assets/:asset_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:asset_id | Integer | Unique identifier of the Asset the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The associated Account cannot be changed.
Destroy Asset
curl "https://api.hoalife.com/api/assets/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Asset. Because Asset objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the Asset even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/assets/:asset_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:asset_id | Integer | Unique identifier of the Asset the request is being made for |
CCR Articles
CCR Articles represent a group of similar Violation Types an Association enforces.
Get All CCR Articles
curl "https://api.hoalife.com/api/ccr_articles" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "ccr_article",
"attributes": {
"id": 1,
"article": "5.14.a",
"title": "Lot Maintenance",
"description": "As stated in Article 5.14(a) - Each Owner of a Lot shall maintain all Improvements located thereon in good and sufficient repair and shall keep the improvements thereon painted or stained, lawn cut, shrubbery trimmed, windows glazed, rubbish and debris removed, weeds cut and otherwise maintain the same in a neat and aesthetically pleasing condition.",
"created_at": "2019-07-30T21:16:47.540Z",
"updated_at": "2019-07-31T15:44:01.646Z",
"account_id": 2,
"external_id": null
},
"relationships": {}
},
...
{
"id": "4",
"type": "ccr_article",
"attributes": {
"id": 4,
"article": "5.24.c",
"title": "Fences and Walls",
"description": "As stated in Article 5.24(c) - All fences and walls shall be constructed and installed and maintained in good appearance and condition at the expense of the Owner of the Lot on which they are located and all damaged fencing and walls shall be repainted or replaced to original design, materials, and color within a reasonable time after said damage occurs.",
"created_at": "2019-07-30T21:16:48.006Z",
"updated_at": "2019-07-30T21:16:48.009Z",
"account_id": 2,
"external_id": null
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 4,
"total_pages": 1
},
"links": {
"self": "/api/ccr_articles?page=1",
"next": "/api/ccr_articles",
"prev": "/api/ccr_articles"
}
}
This endpoint retrieves all CCR Articles accessible by the API key. If the API key has access to multiple Accounts, all CCR Articles for all those accounts will be returned. Scope CCR Articles to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/ccr_articles
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the CCR Article |
account_id | Integer | Unique identifier of Account the CCR Article belongs to |
article | String | Article of CCRs, used for ordering and nesting |
title | String | Title of the CCR Article |
description | String | Description of the CCR Article |
external_id | String | A unique identifier from an external system used to map the record |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
article | true | true |
title | true | true |
description | true | true |
external_id | true | true |
Create CCR Article
curl "https://api.hoalife.com/api/ccr_articles" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "ccr_article",
"attributes": {
"article": "5.24.c",
"title": "Fences and Walls",
"description": "As stated in Article 5.24(c) - All fences and walls shall be constructed and installed and maintained in good appearance and condition at the expense of the Owner of the Lot on which they are located and all damaged fencing and walls shall be repainted or replaced to original design, materials, and color within a reasonable time after said damage occurs.",
"external_id": "123"
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": 5
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "4",
"type": "ccr_article",
"attributes": {
"id": 4,
"article": "5.24.c",
"title": "Fences and Walls",
"description": "As stated in Article 5.24(c) - All fences and walls shall be constructed and installed and maintained in good appearance and condition at the expense of the Owner of the Lot on which they are located and all damaged fencing and walls shall be repainted or replaced to original design, materials, and color within a reasonable time after said damage occurs.",
"created_at": "2019-07-30T21:16:48.006Z",
"updated_at": "2019-07-30T21:16:48.009Z",
"account_id": 2,
"external_id": null
}
},
"relationships": {}
}
}
This endpoint creates a new CCR Article.
HTTP Request
POST https://api.hoalife.com/api/ccr_articles
CCR Article Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
account_id | Integer | Unique identifier of Account the CCR Article belongs to | true |
article | String | Article of CCRs, used for ordering and nesting | false |
title | String | Title of the CCR Article | true |
description | String | Description of the CCR Article | true |
external_id | String | A unique identifier from an external system used to map the record | false |
Update CCR Article
curl "https://api.hoalife.com/api/ccr_articles/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "property",
"attributes": {
"title": "Fences and Walls and Doors"
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing CCR Article.
HTTP Request
PUT https://api.hoalife.com/api/ccr_articles/:ccr_article_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:ccr_article_id | Integer | Unique identifier of the CCR Article the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The associated Account cannot be changed.
Destroy CCR Article
curl "https://api.hoalife.com/api/ccr_articles/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing CCR Article. Because CCR Article objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the CCR Article even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/ccr_articles/:ccr_article_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:ccr_article_id | Integer | Unique identifier of the CCR Article the request is being made for |
CCR Violation Types
CCR Violation Types represent a rule that the Association enforces and records violations for.
Get All CCR Violation Types
curl "https://api.hoalife.com/api/ccr_violation_types" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "ccr_violation_type",
"attributes": {
"id": 1,
"title": "Broadleaf and/or weeds in turf",
"resolution_step": "Apply broadleaf/week mitigation",
"days_to_cure": 20,
"created_at": "2019-07-30T21:16:47.707Z",
"updated_at": "2019-07-31T15:44:01.640Z",
"ccr_article_id": 1,
"external_id": null
},
"relationships": {}
},
...
{
"id": "4",
"type": "ccr_violation_type",
"attributes": {
"id": 4,
"title": "Dead tree(s) needs to be removed/replaced",
"resolution_step": "Remove dead tree(s)",
"days_to_cure": 20,
"created_at": "2019-07-30T21:16:47.712Z",
"updated_at": "2019-07-30T21:16:47.712Z",
"ccr_article_id": 1,
"external_id": null
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 4,
"total_pages": 1
},
"links": {
"self": "/api/ccr_violation_types?page=1",
"next": "/api/ccr_violation_types",
"prev": "/api/ccr_violation_types"
}
}
This endpoint retrieves all CCR Violation Types accessible by the API key. If the API key has access to multiple Accounts or CCR Violation Types, all Violation Types for all those accounts will be returned. Scope CCR Violation Types to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/ccr_violation_types
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the CCR Violation Type |
account_id | Integer | Unique identifier of Account the CCR Violation Type belongs to |
ccr_article_id | Integer | Unique identifier of CCR Article the CCR Violation Type belongs to |
title | String | Title of the CCR Violation Type |
resolution_step | String | Suggested step for resolution of the Violation |
days_to_cure | Integer | Days after the Violation was recorded that a Cure Reminder Notification will be sent |
external_id | String | A unique identifier from an external system used to map the record |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
ccr_article_id | true | true |
article | true | true |
title | true | true |
resolution_step | true | true |
days_to_cure | true | true |
external_id | true | true |
Create CCR Violation Type
curl "https://api.hoalife.com/api/ccr_violation_types" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "ccr_violation_type",
"attributes": {
"title": "Dead tree(s) needs to be removed/replaced",
"resolution_step": "Remove dead tree(s)",
"days_to_cure": 20,
"external_id": "123"
},
"relationships": {
"ccr_article": {
"data": {
"type": "ccr_article",
"id": 1
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "4",
"type": "ccr_violation_type",
"attributes": {
"id": 4,
"title": "Dead tree(s) needs to be removed/replaced",
"resolution_step": "Remove dead tree(s)",
"days_to_cure": 20,
"created_at": "2019-07-30T21:16:47.712Z",
"updated_at": "2019-07-30T21:16:47.712Z",
"ccr_article_id": 1,
"external_id": "123"
},
},
"relationships": {}
}
}
This endpoint creates a new CCR Violation Type.
HTTP Request
POST https://api.hoalife.com/api/ccr_violation_types
CCR Violation Type Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
ccr_article_id | Integer | Unique identifier of CCR Article the CCR Violation Type belongs to | true |
title | String | Title of the CCR Violation Type | true |
resolution_step | String | Suggested step for resolution of the Violation | false |
days_to_cure | Integer | Days after the Violation was recorded that a Cure Reminder Notification will be sent | false |
external_id | String | A unique identifier from an external system used to map the record | false |
Update CCR Violation Type
curl "https://api.hoalife.com/api/ccr_violation_types/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "ccr_violation_type",
"attributes": {
"title": "Dead tree(s) needs to be replaced"
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing CCR Violation Type.
HTTP Request
PUT https://api.hoalife.com/api/ccr_violation_types/:ccr_violation_type_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:ccr_violation_type_id | Integer | Unique identifier of the CCR Violation Type the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The associated CCR Article cannot be changed.
Destroy CCR Violation Type
curl "https://api.hoalife.com/api/ccr_violation_types/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing CCR Violation Type. Because CCR Violation Type objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the CCR Violation Type even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/ccr_violation_types/:ccr_violation_type_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:ccr_violation_type_id | Integer | Unique identifier of the CCR Violation Type the request is being made for |
Inspections
Inspections represent an inspection of the entire Association for Violations.
Get All Inspections
curl "https://api.hoalife.com/api/accounts/inspections" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "inspection",
"attributes": {
"id": 1,
"account_id": 2,
"state": "completed",
"completed_at": "2019-07-30T21:16:49.510Z",
"duration": 7488,
"created_at": "2019-07-30T21:16:49.194Z",
"updated_at": "2019-07-31T15:44:01.575Z",
"total_violations": 18,
"inspector": {
"name": "John Owner",
"email": "john-owner@hoalife.com"
}
},
"relationships": {}
},
{
"id": "2",
"type": "inspection",
"attributes": {
"id": 2,
"account_id": 3,
"state": "started",
"completed_at": null,
"duration": 0,
"created_at": "2019-08-05T14:45:21.291Z",
"updated_at": "2019-08-05T14:45:21.291Z",
"total_violations": 0,
"inspector": {
"name": "John Owner",
"email": "john-owner@hoalife.com"
}
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 2,
"total_pages": 1
},
"links": {
"self": "/api/inspections?page=1",
"next": "/api/inspections",
"prev": "/api/inspections"
}
}
This endpoint retrieves all Inspections accessible by the API key. If the API key has access to multiple Accounts, all Inspections for all those accounts will be returned. Scope Inspections to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/inspections
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Inspection |
account_id | Integer | Unique identifier of Account the Inspection belongs to |
completed_at | String | Date the Inspection was completed |
duration | Integer | Number of seconds between the Inspection's created_at and completed_at values |
total_violations | Integer | The number of Violations recorded in the Inspection |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
completed_at | true | true |
duration | true | true |
total_violations | false | false |
Violations
Violations represent a recorded infraction of a Violation Type for given Property.
Get All Violations
curl "https://api.hoalife.com/api/violations" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "violation",
"attributes": {
"id": 1,
"ccr_violation_type_id": 5,
"comment": "Very bad stuff, here",
"external_id": null,
"violated_at": "2019-06-15T12:04:16.111Z",
"cure_by": "2019-06-25T12:04:16.111Z",
"created_at": "2019-07-30T21:16:48.873Z",
"updated_at": "2019-07-31T15:44:01.522Z",
"property_id": 56,
"inspection_id": null,
"upload_urls": [],
"consecutive_violation_count": 1,
"inspector": {
"name": "John Owner",
"email": "john-owner@hoalife.com"
}
},
"relationships": {}
},
...
{
"id": "4",
"type": "violation",
"attributes": {
"id": 4,
"ccr_violation_type_id": 1,
"comment": "",
"external_id": null,
"violated_at": "2019-07-30T22:07:17.135Z",
"cure_by": null,
"created_at": "2019-07-30T22:07:17.135Z",
"updated_at": "2019-07-31T15:44:01.634Z",
"property_id": 28,
"inspection_id": null,
"upload_urls": [
{
"url": "https://hoal-subdomain.s3.us-west-2.amazonaws.com/aaff3c01-3753-43c7-bc37-98c092e7ab2c/camper.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJSPPTZMGN7FDW4AQ%2F20190805%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20190805T145317Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=999c66db8f6e182793b921989b8724160a45cc973f706f4f7bc56e5bcc9c08eb",
"url_expiration": "2019-08-06T14:53:17.301Z"
}
],
"consecutive_violation_count": 1,
"inspector": {
"name": "John Owner",
"email": "john-owner@hoalife.com"
}
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 4,
"total_pages": 1
},
"links": {
"self": "/api/violations?page=1",
"next": "/api/violations",
"prev": "/api/violations"
}
}
This endpoint retrieves all Violations accessible by the API key. If the API key has access to multiple Accounts, all Violations for all those accounts will be returned. Scope Violations to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/violations
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Violation |
property_id | Integer | Unique identifier of Property the Violation belongs to |
account_id | Integer | Unique identifier of Account the Violation belongs to |
ccr_violation_type_id | Integer | Unique identifier of CCR Violation Type the Violation belongs to |
inspection_id | Integer | Unique identifier of Inspection the Violation belongs to |
violated_at | String | Date the infraction occured |
cure_by | String | Date the infraction should be resolved by |
comment | String | A comment added by the inspector |
upload_urls | Array[Object] | Image uploads associated with the Violation |
external_id | String | A unique identifier from an external system used to map the record |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
property_id | true | true |
ccr_violation_type_id | true | true |
inspection_id | true | true |
violated_at | true | true |
cure_by | true | true |
comment | true | true |
external_id | true | true |
Create Violation
curl "https://api.hoalife.com/api/violations" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "violation",
"attributes": {
"comment": "",
"external_id": "123",
"violated_at": "2019-07-30T22:07:17.135Z",
"upload_urls": [
"https://foobar.com/image.jpg"
]
},
"relationships": {
"ccr_violation_type": {
"data": {
"type": "ccr_violation_type",
"id": 1
}
},
"property": {
"data": {
"type": "property",
"id": 2
}
},
"inspector": {
"data": {
"type": "user",
"email": "user-with-access@example.com"
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "4",
"type": "violation",
"attributes": {
"id": 4,
"ccr_violation_type_id": 1,
"comment": "",
"external_id": "123",
"violated_at": "2019-07-30T22:07:17.135Z",
"created_at": "2019-07-30T22:07:17.135Z",
"updated_at": "2019-07-31T15:44:01.634Z",
"property_id": 2,
"inspection_id": null,
"upload_urls": [],
"consecutive_violation_count": 1,
"inspector": {
"name": "John User With Access",
"email": "user-with-access@example.com"
}
},
},
"relationships": {}
}
}
This endpoint creates a new Violation.
HTTP Request
POST https://api.hoalife.com/api/violations
Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
property_id | Integer | Unique identifier of Property the Violation belongs to | true |
ccr_violation_type_id | Integer | Unique identifier of CCR Violation Type the Violation belongs to | true |
owner_email | String | Email of a HOALife User who has access to the Property | true |
violated_at | String | Date the infraction occured in ISO8601 format | false |
comment | String | A comment added by the inspector | false |
cure_by | String | Date the violation should be cured by in ISO8601 | false |
external_id | String | A unique identifier from an external system used to map the record | false |
upload_urls | Array[String] | An array of publicly accessible URLs | false |
Note when passing upload_urls
: URLs passed are validated and copied in a background process. The responding JSON may not contain the uploads until this completes. This may take many seconds depending on the amount of data that must be copied.
Update Violation
curl "https://api.hoalife.com/api/violations/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "violation",
"attributes": {
"comment": "Dead tree(s) needs to be replaced",
"upload_urls": [
"https://foobar.com/image.jpg"
]
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing Violation.
HTTP Request
PUT https://api.hoalife.com/api/violations/:violation_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:violation_id | Integer | Unique identifier of the Violation the request is being made for |
Editable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
comment | String | A comment added by the inspector | false |
external_id | String | A unique identifier from an external system used to map the record | false |
cure_by | String | Date the violation should be cured by in ISO8601 | false |
upload_urls | Array[String] | An array of publicly accessible URLs | false |
Note when passing upload_urls
: URLs passed are validated and copied in a background process. The responding JSON may not contain the uploads until this completes. This may take many seconds depending on the amount of data that must be copied.
Destroy Violation
curl "https://api.hoalife.com/api/violations/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Violation. Because Violation objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the Violation even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/violations/:violation_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:violation_id | Integer | Unique identifier of the Violation the request is being made for |
Escalations
Escalations represent a group of Violations which have contributed to exceeding the Account's escalation_threshold
.
Get All Escalations
curl "https://api.hoalife.com/api/escalations" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "escalation",
"attributes": {
"id": 1,
"state": "resolved",
"resolved_at": "2019-08-03T24:16:22.118Z",
"account_id": 2,
"property_id": 56,
"created_at": "2019-07-30T21:16:49.818Z",
"updated_at": "2019-07-31T15:40:39.125Z",
"violations": [
{
"id": 1,
"triggered_escalation": false,
"link": "/api/violations?id=1"
},
{
"id": 2,
"triggered_escalation": false,
"link": "/api/violations?id=2"
},
{
"id": 3,
"triggered_escalation": true,
"link": "/api/violations?id=3"
}
],
"resolver": {
"name": "John Owner",
"email": "john-owner@hoalife.com"
},
"notes": [
{
"body_text": "Confirmed property is currently not compliant \n \nhttps://app.hoalife.com/authenticated_uploads/Pn1YWIZjUghE0+B3cCG+CG8e1b0nPX%2FQAkm2soWSu3f4lDHvZoVck7VU39hp--Jzsz3YIEJ%2Fs2oru1--3+77KoR+M6S96SqFMVD8Tw==",
"author": "John Owner",
"pinned": false,
"created_at": "2019-08-05T16:08:24.542Z"
}
]
},
"relationships": {}
},
{
"id": "2",
"type": "escalation",
"attributes": {
"id":2,
"state": "in_process",
"resolved_at": null,
"account_id": 2,
"property_id": 56,
"created_at": "2019-07-30T21:16:49.818Z",
"updated_at": "2019-07-31T15:40:39.125Z",
"violations": [
{
"id": 4,
"triggered_escalation": false,
"link": "/api/violations?id=4"
},
{
"id": 5,
"triggered_escalation": false,
"link": "/api/violations?id=5"
},
{
"id": 6,
"triggered_escalation": true,
"link": "/api/violations?id=6"
}
],
"resolver": {
"name": null,
"email": null
},
"notes": []
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 2,
"total_pages": 1
},
"links": {
"self": "/api/escalations?page=1",
"next": "/api/escalations",
"prev": "/api/escalations"
}
}
This endpoint retrieves all Escalations accessible by the API key. If the API key has access to multiple Accounts, all Escalations for all those accounts will be returned. Scope Escalations to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/escalations
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Escalation |
account_id | Integer | Unique identifier of Account the Escalation belongs to |
property_id | Integer | Unique identifier of Property the Escalation belongs to |
state | String | State of the Escalation |
resolved_at | String | Date the Escalation was marked as resolved |
violations | Array[Object] | Information pertaining to the violations associated with the Escalation |
resolver | Object | Information pertaining to the user who marked the Escalation as resolved |
notes | Array[Object] | Escalation notes |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
property_id | true | true |
state | true | true |
resolved_at | true | true |
violations | false | false |
resolver | false | false |
notes | false | false |
Deficiencies
Deficiencies represent a recorded flaw for a given Asset.
Get All Deficiencies
curl "https://api.hoalife.com/api/deficiencies" \
-H "Authorization: Token sk_SUPERSECRET"
The above command returns JSON structured like this:
{
"data": [
{
"id": "1",
"type": "deficiency",
"attributes": {
"id": 1,
"description": "Pool circulation pump is non-functional",
"details": "Pool circulation pump does not turn on. No indications of power",
"state": "resolved",
"external_id": null,
"resolved_at": "2019-06-15T12:04:16.111Z",
"created_at": "2019-07-30T21:16:48.873Z",
"updated_at": "2019-07-31T15:44:01.522Z",
"asset_id": 56,
"inspection_id": null,
"upload_urls": [],
"formatted_id": "DEF-1"
},
"relationships": {}
},
...
{
"id": "4",
"type": "deficiency",
"attributes": {
"id": 4,
"description": "Entry light out",
"details": "West entry light is out",
"state": "identified",
"external_id": null,
"resolved_at": null,
"created_at": "2019-07-30T22:07:17.135Z",
"updated_at": "2019-07-31T15:44:01.634Z",
"asset_id": 28,
"inspection_id": 4,
"upload_urls": [
{
"url": "https://hoal-subdomain.s3.us-west-2.amazonaws.com/aaff3c01-3753-43c7-bc37-98c092e7ab2c/camper.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJSPPTZMGN7FDW4AQ%2F20190805%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20190805T145317Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=999c66db8f6e182793b921989b8724160a45cc973f706f4f7bc56e5bcc9c08eb",
"url_expiration": "2019-08-06T14:53:17.301Z"
}
],
"formatted_id": "DEF-4"
},
"relationships": {}
}
],
"meta": {
"current_page": 1,
"total": 4,
"total_pages": 1
},
"links": {
"self": "/api/deficiencies?page=1",
"next": "/api/deficiencies",
"prev": "/api/deficiencies"
}
}
This endpoint retrieves all Deficiencies accessible by the API key. If the API key has access to multiple Accounts, all Deficiencies for all those accounts will be returned. Scope Deficiencies to a specific Account by adding an account_id
query parameter.
HTTP Request
GET https://api.hoalife.com/api/deficiencies
Attributes
Parameter | Type | Description |
---|---|---|
id | Integer | Unique identifier of the Deficiency |
asset_id | Integer | Unique identifier of Asset the Deficiency belongs to |
account_id | Integer | Unique identifier of Account the Deficiency belongs to |
inspection_id | Integer | Unique identifier of Inspection the Deficiency belongs to |
state | String | Current state of the deficiency |
resolved_at | String | Date the infraction occured |
description | String | A short description added by the inspector |
details | String | A long details about the deficiencies added by the inspector |
upload_urls | Array[Object] | Image uploads associated with the Deficiency |
external_id | String | A unique identifier from an external system used to map the record |
formatted_id | String | Humanized unique identifier |
Query Parameters
Parameter | Query By | Order By |
---|---|---|
id | true | true |
account_id | true | true |
state | true | true |
asset_id | true | true |
inspection_id | true | true |
resolved_at | true | true |
description | true | true |
details | true | true |
external_id | true | true |
formatted_id | true | true |
Create Deficiency
curl "https://api.hoalife.com/api/deficiencies" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "deficiency",
"attributes": {
"description": "Foo",
"details": "Bar",
"external_id": "123",
"state": "resolved"
"resolved_at": "2019-07-30T22:07:17.135Z",
},
"relationships": {
"asset": {
"data": {
"type": "asset",
"id": 2
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "4",
"type": "deficiency",
"attributes": {
"id": 4,
"description": "Foo",
"details": "Bar",
"external_id": "123",
"resolved_at": "2019-07-30T22:07:17.135Z",
"created_at": "2019-07-30T22:07:17.135Z",
"updated_at": "2019-07-31T15:44:01.634Z",
"asset_id": 2,
"inspection_id": null,
"upload_urls": [],
},
},
"relationships": {}
}
}
This endpoint creates a new Deficiency.
HTTP Request
POST https://api.hoalife.com/api/deficiencies
Deficiency Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
asset_id | Integer | Unique identifier of Asset the Deficiency belongs to | true |
resolved_at | String | Date the deficiency was resolved | false |
description | String | A short description added by the inspector | true |
details | String | A long details about the deficiencies added by the inspector | true |
external_id | String | A unique identifier from an external system used to map the record | false |
Update Deficiency
curl "https://api.hoalife.com/api/deficiencies/42" \
-X PUT \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "deficiency",
"attributes": {
"details": "Dead tree(s) needs to be replaced"
}
}
}
'
The above command will return updated JSON, just like for the Create action with a successful status code of
201 CREATED
.
This endpoint updates an existing Deficiency.
HTTP Request
PUT https://api.hoalife.com/api/deficiencies/:deficiency_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:deficiency_id | Integer | Unique identifier of the Deficiency the request is being made for |
Editable Attributes
See Writable Attributes for the Create action. The associated Account cannot be changed.
Destroy Deficiency
curl "https://api.hoalife.com/api/deficiencies/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Deficiency. Because Deficiency objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the Deficiency even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/deficiencies/:deficiency_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:deficiency_id | Integer | Unique identifier of the Deficiency the request is being made for |
Notes
Notes are attached to other data objects, including property
, escalation
, and deficiency
.
Create Note
curl "https://api.hoalife.com/api/notes" \
-X POST \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json" \
-d '
{
"data": {
"type": "note",
"attributes": {
"body_text": "This is my very important note",
"pinned": true
},
"relationships": {
"attached_to": {
"data": {
"type": "property",
"id": 1
}
},
"author": {
"data": {
"id": 1
}
}
}
}
}
'
The above command returns JSON structured like this:
{
"data": {
"id": "4",
"type": "note",
"attributes": {
"id": 4,
"pinned": true,
"author_id": 1,
"body_text": "This is my very important note",
"attached_to_type": "property",
"attached_to_id": 1,
"created_at": "2019-07-30T21:16:47.712Z",
"updated_at": "2019-07-30T21:16:47.712Z",
},
},
"relationships": {}
}
}
This endpoint creates a new Note.
HTTP Request
POST https://api.hoalife.com/api/notes
Note Writable Attributes
Parameter | Type | Description | Required |
---|---|---|---|
author_id | Integer | Unique identifier of User who authored the note (defaults to first user in account scope if null) | false |
attached_to_type | String | Type of entity the note is attached to | true |
attached_to_id | String | ID of the entity the note is attached to | true |
body_text | String | The note's text | true |
pinned | Boolean | Denote if the note should be pinned | false |
Destroy Note
curl "https://api.hoalife.com/api/notes/42" \
-X DELETE \
-H "Authorization: Token sk_SUPERSECRET" \
-H "Content-Type: application/vnd.api+json"
The above command will return an empty response successful response with a successful status code of
202 Accepted
.
This endpoint destroys an existing Note. Because Note objects have many dependent resources, the actual deletion of the data is performed in a background process. This means that the API may continue to return data for the Note even after you've requested a it be deleted.
HTTP Request
DELETE https://api.hoalife.com/api/notes/:note_id
URL Parameters
Parameter | Type | Description |
---|---|---|
:note_id | Integer | Unique identifier of the Note the request is being made for |
Errors
{
"data": {
"id": "556629c9-c2ad-494b-82d4-53d9639f7174",
"type": "error",
"attributes": {
"id": "556629c9-c2ad-494b-82d4-53d9639f7174",
"title": "Resource Not Found",
"status": 404,
"detail": "Resource not found with this API key's scope"
}
}
}
Error Code | Meaning |
---|---|
401 | Bad Request -- Request was not sufficient to provide a response. |
401 | Unauthorized -- Provided API key was not valid. |
403 | Forbidden -- Provided API key does not have access to the requested resource. |
404 | Not Found -- Resource does not exist. |
429 | Too Many Requests -- Rate limit exceeded |
500 | Internal Server Error -- An error has occured and we've been notified. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Validation Errors
POST
and PUT
requests to create or update resources may respond with a 400
when not enough data was provided. In this case, reference the detail
object for an explaination.
{
"data": {
"id": "656629c9-c2ad-494b-82d4-53d9639f7174",
"type": "error",
"attributes": {
"id": "656629c9-c2ad-494b-82d4-53d9639f7174",
"title": "Invalid data",
"status": 400,
"detail": {
"name": "can't be blank",
"parent_id": "is invalid"
}
}
}
}
Webhooks
Webhooks allow your application to be notified, in real-time, about changes in HOALife. As a change happens, HOALife will make an HTTP POST with the event's data to your publicly accessible webserver. Contact HOALife to configure a webhook endpoint.
Respond with a 200
status code to confirm receipt of the webhook. Non-2XX
status codes will result in a Retry of the webhook.
{
"event": "property.update",
"date": "2020-04-14T16:40:17.332Z",
"payload": {
"data": {
"id": "25",
"type": "property",
"attributes": {
"id": 25,
"account_id": 5,
"formatted_id": "PRP-25",
"street_1": "4242 Cowbell Drive",
"street_2": null,
"city": "Sun Valley",
"state": "ID",
"postal_code": "83353",
"override_geocoding": false,
"latitude": "37.233333",
"longitude": "-115.808333",
"route_leg": null,
"route": "Cowbell Drive",
"emails": [
"earl-larae@cowbelldrive.com", "earl-larae@yahsnooze.com"
],
"phone_numbers": [
"+132155512345", "+132155512346"
],
"created_at": "2019-07-30T21:16:45.460Z",
"updated_at": "2019-07-30T21:16:45.460Z",
"mailing_name": "Earl LaRae",
"mailing_street_1": "PO BOX 42424242",
"mailing_street_2": null,
"mailing_city": "Sun Valley",
"mailing_state": "ID",
"mailing_postal_code": "83353",
"notes": [],
"external_id": "123"
},
},
"relationships": {}
}
}
Webhook | Description |
---|---|
account.create | New Account Created |
account.update | Account Updated |
account.destroy | Account Destroyed |
ccr.article.create | New CCR Article Created |
ccr.article.update | CCR Article Updated |
ccr.article.destroy | CCR Article Destroyed |
ccr.violation_type.create | New CCR Violation Type Created |
ccr.violation_type.update | CCR Violation Type Updated |
ccr.violation_type.destroy | CCR Violation Type Destroyed |
user_account.create | User Added to Account |
user_account.update | User Permission Updated |
user_account.destroy | User Removed from Account |
inspections.violation.create | Inspection Violation Created |
inspections.violation.cure_reminder | Inspection Violation Cure Reminder |
inspections.violation.individual_create | Individual Inspection Violation Created |
inspections.violation_delivery.create | Inspection Violation Notice Delivery Created |
inspections.violation_delivery.sent | Inspection Violation Notice Sent |
inspections.violation_delivery.failed | Inspection Violation Notice Delivery Failure |
inspections.violation_response.create | Property Owner Violation Response Created |
inspections.violation.tag.added | Inspection Violation Tag Added |
inspections.violation.tag.removed | Inspection Violation Tag Removed |
inspections.violation.closed | Inspection Violation Closed |
inspections.violation.regression | Inspection Violation Reopened |
inspections.violation.update | Inspection Violation Updated |
inspections.violation.destroy | Inspection Violation Destroyed |
inspection.complete | Inspection Completed |
inspection.create | Inspection Created |
inspection.inspection_reminder | Association Due for Inspection |
inspections.escalation.create | Inspection Escalation Created |
inspections.escalation.snoozed | Inspection Escalation Snoozed |
inspections.escalation.snooze_expired | Inspection Escalation Snooze Expired |
inspections.escalation.resolve | Inspection Escalation Resolved |
inspections.escalation.note.create | Inspection Escalation Note Created |
inspections.escalations.letter.create | Inspection Escalation Letter Created |
inspections.suggested_violation.create | Inspection Violation Suggestion Created |
inspections.suggested_deficiency.create | Inspection Deficiency Suggestion Created |
property.create | Property Created |
property.update | Property Updated |
property.destroy | Property Destroyed |
property.note.create | Property Note Created |
property.tag.added | Property Tag Added |
property.tag.removed | Property Tag Removed |
properties.ownership_change_suggested | Property Ownership Change Suggested |
properties.ownership_change | Property Ownership Changed |
inspections.deficiency.create | Asset Deficiency Created |
inspections.deficiency.resolve | Asset Deficiency Resolved |
inspections.deficiency.snoozed | Asset Deficiency Snoozed |
inspections.deficiency.snooze_expired | Asset Deficiency Snooze Expired |
inspections.deficiency.note.create | Asset Deficiency Note Created |
inspections.deficiency.tag.added | Asset Deficiency Tag Added |
inspections.deficiency.tag.removed | Asset Deficiency Tag Removed |
asset.create | Asset Created |
asset.update | Asset Updated |
asset.destroy | Asset Destroyed |
asset.tag.added | Asset Tag Added |
asset.tag.removed | Asset Tag Removed |
violation_cover_letter.create | Violation Cover letter Created |
violation_cover_letter.update | Violation Cover letter Updated |
violation_cover_letter.destroy | Violation Cover letter Destroyed |
letter_templates.escalation.create | Escalation Letter Template Created |
letter_templates.escalation.update | Escalation Letter Template Updated |
letter_templates.escalation.destroy | Escalation Letter Template Destroyed |
letters.letter_delivery.create | Letter Delivery Created |
letters.letter_delivery.sent | Letter Delivery Sent |
letters.letter_delivery.failed | Letter Delivery Failure |
conversation.create | Conversation Started |
conversations.sent_message.create | Conversation Message Sent |
conversations.received_message.create | Conversation Message Received |
Verify Webhook Request Authenticity
Webhook POST requests will include the X-Signature
HTTP header just like our API endpoint responses. See Verify Response Authenticity for details.
Idempotentcy
Webhooks may be retried a later time if a network error is encountered. Ensure your webhook endpoint supports handling of webhooks in an idempotent manner.
Retries
If a 2XX
response code is not provided by your webhook endpoint, the webhook will be resent with an exponential back-off period. This accommodates service outages of your webhook endpoint.
Ordering
Many webhooks may be fired at once in near parallel order. As a result, it is important to consider the expected order of receipt and real-world order of receipt. For example, when an inspection is created, any related inspections.violation.create
webhooks may be triggered shortly afterwards. You might be expecting the inspection.create
webhook to be delivered first, however, this is not a guarantee (network latency or errors may disrupt this expectation).
Utilize your application's shared state (perhaps existence/absence of a database record) and non-2XX
response codes to leverage Retries as a method of enforcing ordering of data. For example, if you require receipt of the inspection.create
webhook before processing any inspections.violation.create
webhooks, you could respond to any inspections.violation.create
webhooks with a 404
until you've received and processed the inspection.create
webhook. The 404
-ed inspections.violation.create
will automatically be retried.
Quick Responses
Webhooks are intended to quickly be fired and receive a response. A strict 4 second timeout is enforced for webhook network requests. Do any time consuming work outside of the network request of the webhook to avoid the request being terminated and the webhook being resent.