General Request Format
Base URL: https://api.wearehearken.com/api/v1/
Only HTTPS connections are allowed.
Authentication
You must obtain an API key. At present there is no self-service process. Please contact support@wearehearken.com to request an API key.
The preferred method of authentication is to send your API key in an authorization header within your request
Header Format: Authorization: Bearer <api-key>
Getting an API Key
API Keys are scoped to the permissions of the EMS user that owns the key. In the future it will be possible to further constrain these permissions.
Errors
The following Error codes may be returned from the API
401 Not Authorized - when request does not have valid credentials
403 Forbidden - when user is not allowed to perform the requested action
400 Bad Request - when there is an error with the client request
404 Not Found - when client requests a resource that does not exist
5xx - internal server errors
The content type of an error response is always application/json and returns an object that contains an error
key, with some description of the error.
Request Parameters
Request parameters should be sent as query string parameters. Some common request parameters:
_limit
- Limit number of results returned to client with each request.
_offset
- Skip this many results before returning results to client.
_select
- Limit response to the given top-level fields (see "Responses" below)
Response Format
Example Response Collection
{
"_type": "collection",
"total_objects": 229,
"offset": 0,
"data": [
// list of items here...
],
"limit": 30,
"next_page": "https://api.wearehearken.com/api/v1/questions?_limit=30&_offset=30"
}
The total_objects
key contains total number of objects, that match the given query, regardless of whether _offset
or _limit
have been specified.
The offset
and limit
keys are provided to make it easy to calculate pagination interfaces
The data
key contains an array of result items (See below for individual formats)
Timestamps are in UTC, given as milliseconds since midnight on January 1st, 1970.
Questions
Listing
Endpoint: https://api.wearehearken.com/api/v1/questions
Method: GET
Question Request Parameters
organization_id
- Limit results to the given comma-separated list of organization IDs. By default, questions from all accessible organizations will be returned
list_id
- limit results to the given comma-separated list of question list ids. By default, questions will not be filtered by list
source
- limit results to the given source. Example: source=prompt_embed:123
would return questions that were submitted from an embed with the ID 123
quarantined
- (boolean) - limit results to or exclude quarantined questions. User must have the proper privileges to search by quarantined=true
created_at
- filter by creation time, given as milliseconds since midnight on January 1st, 1970. Ranges and inequalities may be specified by providing one or more of the following keys:
created_at_gte - created_at is greater than or equal to given value
created_at_lte - created_at is less than or equal to given value
created_at_gt - created_at is greater than given value
created_at_lt - created_at is less than given value
Format of Individual Question Response
{
"id": 12345678,
"prompt": "What do you wonder about running for Congress that you'd like Jenny to cover on the podcast? ",
"embed_name": "API Demonstration Embed",
"name": "Jane",
"email": "jane.doe@example.com",
"opt_in_response": true,
"anonymous": false,
"display_text": "I wonder what the stats are on beating an incumbent based on age of population? ",
"original_text": "I wonder what the stats are on beating an incumbent based on age of population? ",
"approved": false,
"deleted": false,
"quarantined": false,
"hidden": false,
"source_url": "https://www.wearehearken.com/faq",
"reporter": "Codey M.",
"notes": "Review this question at next planning meeting",
"organization": {
"id": 2,
"name": "API Example",
"slug": "api-example",
"_type": "organization",
"created_at": 1429064494000,
"updated_at": 1509740787769
},
"question_status": {
"id": 123,
"name": "New",
"_type": "question_status",
"created_at": 1468430366771,
"updated_at": 1468430366771
},
"lists": {
"_type": "collection",
"total_objects": 1,
"offset": 0,
"data": [
{
"id": 1234,
"name": "API Example List",
"question_count": 1,
"_type": "list",
"created_at": 1570451318186,
"updated_at": 1570451318186
}
],
"limit": 10
},
"postcode": "98121",
"source": "prompt_embed:123",
"custom_fields": [
{
"name": "Postal Code",
"value": "98121",
"type": "postal_code",
"required": true
}
],
"organization_audience_member": {
"id": 12345,
"email": "jane.doe@example.com",
"_type": "organization_audience_member",
},
"created_at": 1572561753652,
"updated_at": 1572561753652,
"_type": "question"
}
Updating
Endpoint: https://api.wearehearken.com/api/v1/questions/<id>
Method: PATCH
Allowed Request body parameters
Only send the fields that you need to update. The user associated with the API key must have appropriate permissions.
quarantined
- Boolean. Whether or not this question should be considered quarantined.
deleted
- Boolean. Whether or not this question should be considered deleted.
approved
- Boolean. When moderation is in effect, setting to true
will approve this question.
Response
On success, the API will return a 200
status along with the serialized output of the updated record.
Audience Members
Endpoint: https://api.wearehearken.com/api/v1/organizations/<organization_id>/audience_members
Method: GET
Audience Member Request Parameters
organization_id
- REQUIRED. Limit results to the given organization ID.
opt_in_list_id
- limit results to audience members given opt-in list ID. Only single values allowed.
Sorting
Sorting is available on any combination of the following fields, by passing comma-separated field names in the _sort
query parameter.
created_at
, first_activity_at
, last_activity_at
, question_count
, vote_count
, opt_in_list_membership_count
Sorting is ascending by default. Descending sort on a column is available by prepending a -
to the column name.
Example: Retrieve audience members sorted by decreasing question count, then by earliest activity: ?_sort=-question_count,first_activity_at
Timestamps
Filter by timestamps, given as milliseconds since midnight on January 1st, 1970. Ranges and inequalities may be specified by providing one or more of the following keys:
<name> (no suffix) - <name> is equal to the given value
<name>_gte - <name> is greater than or equal to given value
<name>_lte - <name> is less than or equal to given value
<name>_gt - <name> is greater than given value
<name>_lt - <name> is less than given value
The following timestamp fields are recognized:
created_at - creation date
first_activity_at - time of first activity by this audience member, within the restrictions of the current query
last_activity_at - time of last activity by this audience member, within the restrictions of the current query
Counts
Filter by counts, given as an integer. Ranges and inequalities may be specified by providing one or more of the following keys:
<name> (no suffix) - <name> is equal to the given value
<name>_gte - <name> is greater than or equal to given value
<name>_lte - <name> is less than or equal to given value
<name>_gt - <name> is greater than given value
<name>_lt - <name> is less than given value
The following count fields are recognized:
question_count - count of questions asked by this audience member
vote_count - count of votes cast by this audience member
opt_in_list_membership_count - count of opt-in list memberships
Format of Individual Audience Member Response
{
"id": 12345,
"email": "jane.doe@example.com",
"question_count": 3,
"vote_count": 2,
"opt_in_list_membership_count": 1,
"first_activity_at": 1520358715522,
"last_activity_at": 1572561753652,
"organization": {
"id": 2,
"name": "API Example",
"slug": "api-example",
"_type": "organization",
"created_at": 1429064494000,
"updated_at": 1509740787769
},
"first_activity": "March 6, 2018",
"last_activity": "October 31, 2019",
"earliest_activity_at": 1520358715522,
"latest_activity_at": 1572561753652,
"opt_in_lists": [
{
"id": 1,
"name": "All newsletter opt-ins",
"metadata": "External CRM ID 12",
"earliest_opt_in_at": 1520358715522,
"latest_opt_in_at": 1572561753652,
"latest_opt_in_text": "Sign me up for your newsletter!",
"_type": "opt_in_list_membership"
}
],
"_type": "organization_audience_member",
"created_at": 1520358715522,
"updated_at": 1572561753652
},
Quarantine Settings
Quarantine Settings are per-EMS settings that can be applied to text
(submission text), ip
(client IP address), and email
(submitter's email address) fields.
Listing
Endpoint: /api/v1/organizations/<organization_id>/quarantine_settings
Method: GET
Response Format:
{
"_type": "collection",
"total_objects": 3,
"offset": 0,
"limit": 10,
"data": [
{
"_type": "organization_quarantine_setting",
"organization": {
"_type": "organization",
"created_at": 1580831134772,
"updated_at": 1581459626449,
"id": 1,
"name": "Demo Website",
"slug": "demo-website"
},
"words": [
"new",
"text",
"words"
],
"use_list": "custom",
"id": "text",
"enabled": true
},
{
"_type": "organization_quarantine_setting",
"organization": {
"_type": "organization",
"created_at": 1580831134772,
"updated_at": 1581459626449,
"id": 1,
"name": "Demo Website",
"slug": "demo-website"
},
"words": [],
"use_list": "default",
"id": "ip",
"enabled": false
},
{
"_type": "organization_quarantine_setting",
"organization": {
"_type": "organization",
"created_at": 1580831134772,
"updated_at": 1581459626449,
"id": 1,
"name": "Demo Website",
"slug": "demo-website"
},
"words": [],
"use_list": "default",
"id": "email",
"enabled": false
}
]
}
Updating
Endpoint: /api/v1/organizations/<organization_id>/quarantine_settings/<id>
Method: PATCH
Note: The id
field for a quarantine setting is a string, such as ip
, text
, email
, not a numeric id.
The following fields may be specified in the request body:
words
- a list of words to look for in the given field(s) that will mark the submission as quarantined
use_list
- one of default
or custom
. Specifying default
will undo any custom word list you have provided and fall back to the system default.
enabled
- whether to enable or disable matching for the field refernced by id
. If words
is not specified, does not update the word list.
Example: incoming submissions with any of the words spam, href, and http will be marked quarantined
PATCH /api/v1/organizations/12345/quarantine_settings/text
{ "enabled": true, "words": ["spam", "href", "http"], "use_list":"custom" }
Example: use the default/system email address matchlist for incoming submissions
PATCH /api/v1/organizations/12345/quarantine_settings/email
{ "use_list":"default" }
Example: turn off matching for ip addresses on incoming submissions
PATCH /api/v1/organizations/12345/quarantine_settings/ip
{ "enabled": false }
Response
Upon successful update, a 200
status will be returned, along with the updated record. Otherwise, an error will be returned.