Request Configuration
URLs
Test
https://apitest.choicely.com/dev
Production
https://api.choicely.com/dev
Headers
Name | Description |
---|---|
choicely-brand | ID of brand |
choicely-key | Predefined developer secret key |
Common objects
Style
Example JSON in a response:
"style": {
"padding": {
"top": 32,
"right": 16,
"bottom": 32,
"left": 16,
},
"margin": {
"top": 32,
"right": 16,
"bottom": 32,
"left": 16,
},
"corner_radiuses": {
"top_left": 3,
"top_right": 3,
"bottom_right": 3,
"bottom_left": 3,
},
"width": 100,
"height": 100,
"scale": 1.777,
"size": 3,
"text_size": 18,
"elevation": 0,
"text_font": "some_supported_font",
"text_style": "",
"text_color": "#000000",
"icon_tint": "#000000",
"background_color": "#000000",
"image_style": "circle",
"primary_color": "#000000",
"secondary_color": "#000000",
"gravity": "center",
"modifier": "normal",
"image_crop": "center_crop"
}
Article
Article
Request JSON (get):
{
"type": "normal",
"title": "Article title",
"description": "Article description",
"navigation": { }, // navigation item
"image_id": "<image_id>",
"fields": [
{
"field_id": "any_str",
"type": "text",
"text": "",
"full_screen": false,
"scrollable": false,
"link": "https://choicely.com",
"follow": {
"topic": "<topic>",
"follow_text": "Follow please",
"unfollow_text": "Unfollow sorry",
"style": { }
},
"from_template_key": "<template_key>",
"navigation": { }, // navigation item
"contest_key": "<contest_key>",
"image_id": "<image_id>",
"participant_keys": ["<participant_key>"],
"survey_key": "<survey_key>",
"video_id": "<video_id>",
"web_data_key": "<web_data_key>",
"simple_web_data": { }
}
],
"draft": {
"title": "This is a DRAFT",
"...": "..."
},
"style": { }
}
Response JSON (create/update):
{
"article_key": "<article_key>",
"type": "normal",
"title": "Article title",
"description": "Article description",
"is_draft": false,
"draft": {
"title": "This is an article draft",
"is_draft": true
},
"navigation": { }, // navigation item
"image": { },
"style": { },
"is_published": true,
"custom_data": { },
"updated": "2020-01-01T00:00:00Z",
"created": "2020-01-01T00:00:00Z",
"thumbnail_fields": [ ],
"fields": [
{
"field_id": "0000",
"type": "text",
"text": "",
"full_screen": false,
"link": "https://choicely.com",
"scrollable": false,
"from_template_key": "<template_key>",
"follow": {
"topic": "<topic>",
"follow_text": "Follow please",
"unfollow_text": "Unfollow sorry",
"style": { }
},
"subfields": [{}, {}],
"ad": { },
"contest": { },
"image": { },
"participants": [{}, {}],
"navigation": { }, // navigation item
"style": { },
"survey": { },
"video": { },
"web_data": { },
"simple_web_data": { }
}
]
}
Get all
GET /v2/articles
Optional query params | Default | Notes |
---|---|---|
scheduled | false | If true, is_template and type will be ignored |
is_template | false | Can be used with type |
type | Possible values: content_only, header, normal, splash, thumbnail | |
next | Token to fetch another page |
Create
POST /v2/articles
Get one
GET /v2/articles/<article_key>
Update
POST /v2/articles/<article_key>
Delete
DELETE /v2/articles/<article_key>
Contests
Get Contest
{
"contest_id": "1111-1111",
"contest_type": "voteonly",
"phase": "running",
"brand": {
"brand_id": "2222-2222",
"brand_name": "choicely",
"image_id": "3333-3333"
},
"total_vote_count": 4000,
"unique_voter_count": 3500,
"participant_count": 10,
"unique_participant_count": 1,
"countries": ["fin", "swe", "nor"],
"categories": [,
{
"category": "danger"
},
{
"category": "games"
}
],
"published": true,
"update_widget": false,
"contest_config": {
"participant_order": "participated",
"is_vote_removal_allowed": true,
"contest_visibility": "not_listed",
"vote_visibility": "hidden_until_end",
"limit_result_amount": -1,
"randomize_locally": false,
"show_video_play_button": false,
"participant_visibility": "shown",
"participant_default_status": "approved",
"anonymous_voting": true,
"ip_restriction_per_participant": 10
},
"free_vote_config": {
"max_free_votes_per_participant": 1,
"max_free_votes_in_contest": -1
},
"star_vote_config": {
"max_star_votes_in_contest": -1,
"max_star_votes_per_participant": -1
},
"start": "2016-01-01T00:00:00Z",
"end": "2016-01-07T00:00:00Z",
"created": "2016-01-01T00:00:00Z",
"participants": [
{
"participant_key": "<participant_key>",
"contest_id": "1111-1111",
"brand": {
"brand_id": "2222-2222",
"brand_name": "choicely",
"image_id": "3333-3333"
},
"title": "",
"story": "",
"vote_count": 0,
"participated": "2016-01-01T00:00:00Z",
"data": {
"data_of_own_choice": "in_json_format"
},
"image": {
"image_id": "4444-4444",
"brand": {
"brand_id": "2222-2222",
"brand_name": "choicely",
"image_id": "3333-3333"
},
"title": "",
"story": "",
"ratio": 1.333,
"love_count": 0,
"message_count": 0,
"tags": [],
"created": "2016-01-01T00:00:00Z"
}
}
]
}
GET /contests/<contest_id>
Response
Status | Description |
---|---|
200 | [ JSON ] |
400 | Contest not found |
400 | No permission to contest |
Get Contests of Brand
{
"contests": [
{
"contest_id": "1111-1111",
"...": "...",
"...": "..."
},
{
"contest_id": "2222-2222",
"...": "...",
"...": "..."
}
],
"next": "<very long token if more contests>"
}
Maximum of 20 contests are returned. Use next token to get more contests.
GET /brands/<brand_id>/contests?next=<token>
Response
Status | Description |
---|---|
200 | [ See example JSON of a single contest ] |
400 | Brand not found or no permission |
Create Contest
POST /contests
Possible phases of contest:
- setup When
published=false
. Only admin can see - announced When
published=true
and start datetime is in the future - running When
published=true
and current time is between start and end datetimes. Voting is possible - finished When
published=true
and end datetime is in the past
Minimum requirements to create running contest:
- start set to some past datetime
- end set to some future datetime
- published set to true
POST parameters
Parameter | Type | Default | Description and restrictions |
---|---|---|---|
title | String | ||
text | Text | ||
image_id | String | ||
contest_type | String | participation | Possible values: participation, voteonly |
published | Boolean | false | |
publish | RFC3339 | (e.g. 2014-05-05T00:00:00Z) | |
start | RFC3339 | (e.g. 2014-05-05T00:00:00Z) | |
end | RFC3339 | (e.g. 2014-06-05T00:00:00Z) | |
contest_visibility | String | listed | Possible values: listed, not_listed. Listed contests are shown on Choicely web page and clients |
vote_visibility | String | shown | Possible values: shown, hidden_until_vote, hidden_until_end, hidden |
participant_visibility | String | shown | Possible values: shown, owner_only |
participant_order | String | participated | Possible values: participated, running_number, vote_count |
participant_default_status | String | approved | Possible values: approved, pending, rejected |
randomize_locally | Boolean | false | Should client randomize participants |
max_free_votes_in_contest | Int | -1 | -1 indicates unlimited |
max_free_votes_per_participant | Int | 1 | -1 indicates unlimited |
max_star_votes_in_contest | Int | 0 | -1 indicates unlimited |
max_star_votes_per_participant | Int | 0 | -1 indicates unlimited |
max_silver_votes_in_contest | Int | 0 | -1 indicates unlimited |
max_silver_votes_per_participant | Int | 0 | -1 indicates unlimited |
is_vote_removal_allowed | Boolean | true | |
ip_restriction_per_participant | Int | 10 | -1 indicates unlimited. Cannot be set to 0 |
limit_result_amount | Integer | -1 | -1 indicates unlimited |
add_participants | Array | No error is returned, even if array is invalid or no permission to image | |
tags | Array | ||
custom_data | JSON | Optional JSON data |
Response
Status | Description |
---|---|
200 | [ See example JSON ] |
400 | [ Invalid value errors ] |
Update Contest
POST /contests/<contest_id>
POST parameters
Response
Status | Description |
---|---|
200 | [ See example JSON ] |
400 | Contest not found |
400 | No permission to contest |
400 | Invalid value errors |
Delete Contest
DELETE /contests/<contest_id>
Response
Status | Description |
---|---|
204 | |
400 | Contest not found |
400 | No permission to contest |
Convention
Convention
Response JSON (get)
{
"convention_key": "<convention_key>",
"title": "Autogenerated Convention",
"start": "2022-01-01T00:00:00Z",
"end": "2022-01-03T00:00:00Z",
"days": [
{
"id": "d1",
"title": "Day 1",
"top_text": "Top1",
"bottom_text": "Bottom1",
"start": "2022-01-01T00:00:00Z",
"end": "2022-01-02T00:00:00Z"
},
{
"id": "d2",
"title": "Day 2",
"top_text": "Top2",
"bottom_text": "Bottom2",
"start": "2022-01-02T00:00:00Z",
"end": "2022-01-03T00:00:00Z"
}
],
"venues": [
{
"id": "v1",
"title": "Venue 1",
"description": "Description",
"position": 1,
"article_key": "<article_key>",
"navigation": { }
}
],
"search_helps": [
{
"term": "Alfa",
"icon": { }
},
{
"term": "Beta"
}
],
"updated": "2022-01-01T00:00:00Z",
"created": "2022-01-01T00:00:00Z",
}
Request JSON (create/update)
{
"title": "Title",
"start": "2022-01-01T00:00:00Z", // required
"end": "2022-01-03T00:00:00Z", // required
"days": [
{
"id": "d1", // required
"title": "Day 1",
"top_text": "Top",
"bottom_text": "Bottom",
"start": "2022-01-01T00:00:00Z",
"end": "2022-01-02T00:00:00Z"
},
{
"id": "d2", // required
"title": "Day 2",
"start": "2022-01-02T00:00:00Z",
"end": "2022-01-03T00:00:00Z"
}
],
"venues": [
{
"id": "<id>", // required
"title": "Venue 1",
"description": "Description",
"position": 1,
"article_key": "<article_key>",
"navigation": {}
}
],
"search_helps": [
{
"term": "Alfa",
"icon_id": "<image_id>"
},
{
"term": "Beta"
}
]
}
GET all
GET /dev/v2/conventions
CREATE
POST /dev/v2/conventions
GET one
GET /dev/v2/conventions/<convention_key>
UPDATE
POST /dev/v2/conventions/<convention_key>
DELETE
DELETE /dev/v2/conventions/<convention_key>
Timeslot
Response JSON (get)
{
"timeslot_key": "<timeslot_key>",
"title": "Title",
"description": "Description",
"day_id": "d1",
"venue_id": "v1",
"time_text": "12-14",
"start": "2022-01-01T00:00:00Z",
"end": "2022-01-03T00:00:00Z",
"convention_key": "<convension_key>",
"article_key": "<article_key>",
"image": { },
"search_helps": [
{
"structured_id": "0000-0000",
"term": "Time 1",
"icon": { }
},
{
"structured_id": "1111-1111",
"term": "Time 2"
}
],
"navigation": { },
"updated": "2020-01-01T00:00:00Z",
"created": "2020-01-01T00:00:00Z"
}
Request JSON (create/update)
{
"title": "Title",
"description": "Description",
"day_id": "d1",
"venue_id": "v1",
"time_text": "12-14",
"start": "2022-01-01T00:00:00Z", // required
"end": "2022-01-03T00:00:00Z", // required
"article_key": "<article_key>",
"image_id": "<image_id>",
"search_helps": [
{
"term": "Time 1",
"icon_id": "<image_id>"
},
{
"term": "Time 2"
}
],
"navigation": { }
}
GET all by Convention
GET /dev/v2/conventions/<convention_key>/timeslots?next=<next>
CREATE for Convention
POST /dev/v2/conventions/<convention_key>/timeslots
GET one
GET /dev/v2/timeslots/<timeslot_key>
UPDATE
POST /dev/v2/timeslots/<timeslot_key>
DELETE
DELETE /dev/v2/timeslots/<timeslot_key>
Timeslots multi create/update
{
"timeslots": [
{
"timeslot_key": "<timeslot_key>", // when updating
"...": "...",
"...": "...",
"...": "...",
"start": "2020-01-01T00:00:00Z", // required
"end": "2020-01-01T00:00:00Z" // required
}
]
}
Create and update multiple Timeslots in one go.
POST /v2/conventions/<convention_key>/timeslots/multi
CREATE
A new Timeslot will be created when:
- timeslot_key isn't included
- Timeslot with the timeslot_key doesn't exist
UPDATE
Update existing Timeslots by providing timeslot_key.
If the current brand doesn't have write permission to Timeslot, error will be raised.
Feed
ArticleFeed
Response JSON (get):
{
"feed_key": "<feed_key>",
"title": "Title",
"is_followable": false,
"is_push_enabled": true,
"divider_height": -1,
"header_article": { },
"footer_article": { },
"total_pages": 1,
"total_count": 1,
"first_page": {
"page_key": "<page_key>",
"feed_key": "<feed_key>",
"page_number": 0,
"articles": [ ],
"updated": "2020-01-01T00:00:00Z",
"created": "2020-01-01T00:00:00Z"
},
"app_keys": [
"<app_key>"
],
"sups": [ ],
"style": { },
"custom_data": {
"optional": "data"
},
"updated": "2020-01-01T00:00:00Z",
"created": "2020-01-01T00:00:00Z"
}
Request JSON (create/update):
{
"title": "Title",
"is_followable": false,
"is_push_enabled": true,
"divider_height": -1,
"header_article_key": "${article_key}",
"footer_article_key": "${article_key}",
"topic_key": "${topic_key}",
"style": { },
"custom_data": {
"optional": "data"
}
}
Get all
GET /dev/v2/articlefeeds
Create
POST /dev/v2/articlefeeds
Get one
GET /dev/v2/articlefeeds/<feed_key>
Update
POST /dev/v2/articlefeeds/<feed_key>
Delete
DELETE /dev/v2/articlefeeds/<feed_key>
Add Article to Feed
POST /v2/articlefeeds/<feed_key>/articles/<article_key>
Remove Article from Feed
Remove item from page by using feed_item_id
DELETE /v2/feedpages/items/<feed_item_id>
FeedPage
Move Item on FeedPage
Request JSON:
{
"index": 0
}
Move inside a page
Move item to given index position. It has to be 0 or more
POST /v2/feedpages/<from_page_key>/items/<feed_item_id>/move_to
Move to next or previous page
to_page_key has to be next_page_key or previous_page_key of current FeedPage (from_page_key). Use index to determine the position where the item is wanted to be moved
POST /v2/feedpages/<from_page_key>/items/<feed_item_id>/move_to/<to_page_key>
Images
Get Image
{
"image_id": "0000-0000",
"title": "",
"image_text": "",
"brand": {
"brand_id": "1111-1111",
"brand_name": "mybrand",
"image_id": "2222-2222"
},
"ratio": 1.333,
"is_icon": true,
"public_use": false,
"tags": [ ],
"created": "2018-01-01T00:00:00Z"
}
GET /images/<image_id>
Response
Status | Description |
---|---|
200 | [ JSON ] |
400 | Image not found |
400 | No permission to image |
Create/Upload Image
Note: Use POST form body
Image data can be uploaded by sending image file in src field or giving url to image (use %20
as space etc.) (do not use backslashes \
).
Upload jpg or png only. Note that maximum size is 10.0 MB
POST /images
POST parameters
Parameter | Type | Default | Description and restrictions |
---|---|---|---|
title | String | ||
image_text | String | ||
public_use | Boolean | false | Allow image to be used by other users/brands |
url | String | url where image will be fetched | |
src | File | Maximum file size is 10.0 MB. This field is not available when updating image | |
is_icon | Boolean | false | If uploaded image is png, it can be made also an icon by setting this true. This field is not available when updating image |
Response
Status | Description |
---|---|
200 | [ See example JSON ] |
400 | [ Invalid value errors ] |
Update Image
POST /images/<image_id>
POST parameters
Response
Status | Description |
---|---|
200 | [ See example JSON ] |
400 | Image not found |
400 | No permission to image |
400 | [ Invalid value errors ] |
Delete Image
DELETE /images/<image_id>
Response
Status | Description |
---|---|
204 | |
400 | Image not found |
400 | No permission to image |
Serve Image
Media service is used to serve image data
GET https://media.choicely.com/image/<image_id>?size=<size>
URL Parameters
Parameter | Default | _ |
---|---|---|
size | default | Possible sizes: thumb, default, large |
Response
Status | Description |
---|---|
200 | [ Image data ] |
Participants
Get Participant
{
"participant_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0cjcLEgVCcmFuZBgBDAsSB0NvbnRlc3QYgICAgICAmAkMCxILUGFydGljaXBhbnQYgICAgICAuAoM",
"title": "",
"story": "",
"vote_count": 0,
"rater_count": 0,
"message_count": 0,
"status": "approved",
"contest_id": "0000-0000",
"contest_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0ch8LEgVCcmFuZBgBDAsSB0NvbnRlc3QYgICAgICAmAkM",
"number_string": "A",
"running_number": 1538484763,
"participated": "2018-01-01T00:00:00Z",
"user": {
"user_id": "0000-0000",
"user_name": "kristian1",
"image_id": "1111-1111"
},
"image": {
"image_id": "0000-0000",
"title": "",
"image_text": "",
"user": {
"user_id": "kri1",
"user_name": "kristian1",
"image_id": ""
},
"ratio": 1.836,
"is_icon": true,
"public_use": false,
"tags": [ ],
"created": "2018-01-01T00:00:00Z"
},
"video": {
"video_id": 1111,
"...": "..."
},
"info_fields": [
{
"field_id": "0000-0000",
"title": "",
"value": "",
"icon": {
"image_id": "1111-1111",
"...": "..."
}
}
],
"subrating_averages": [ ],
"data": {"purpose": "optional JSON data which is returned always"},
"metadata": {"purpose": "optional JSON data which is returned only to owner of contest"}
}
GET /participants/<participant_key>
Response
Status | Description |
---|---|
200 | [ JSON ] |
400 | Invalid key |
400 | Participant not found |
400 | No permission to participant |
Create Participant to Contest
POST /contests/<contest_id>/participants
POST parameters
Parameter | Type | Default | Description and restrictions |
---|---|---|---|
image_id | String | Not available when updating participant | |
title | String | ||
story | String | ||
running_number | Integer | (Unix timestamp) | |
number_string | String | A string which can be used to overwrite order number of participant. Can be any length but client should allow max three character long. Examples: "5", "A", "1.2", "👌😊☕", "日本" |
|
alt_image_ids | Array | no | Permission to images are required |
data | JSON | Optional public JSON data | |
metadata | JSON | Optional private JSON data visible only for owner of contest |
Response
Status | Description |
---|---|
200 | [ See example JSON ] |
400 | No permission to contest |
Update Participant
POST /participants/<participant_key>
POST parameters
Same as Create Participant to Contest
Response
Status | Description |
---|---|
200 | [ See example JSON ] |
400 | Invalid key |
400 | Participant not found |
400 | No permission to participant |
Delete Participant
DELETE /participants/<participant_key>
Response
Status | Description |
---|---|
204 | No Content |
400 | Invalid key |
400 | Participant not found |
400 | No permission to participant |
Shop, Purchase and Subscription
Get User's Purchases in Shop
/v2/shops/<shop_key>/get_purchases?user_id=<id>
/v2/shops/<shop_key>/get_purchases?provider_user_id=<id>
Get User's Subscription in Shop
{
"shop_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0cgoLEgRTaG9wGAIM",
"shop_type": "subscriptions",
"user_id": "",
"provider_user_id": "",
"purchase": {
"purchase_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0chkLEgxTaG9wUHVyY2hhc2UYgICAgICAwAkM",
"package_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0cg0LEgdQYWNrYWdlGAMM",
"type": "subscription",
"platform": "android",
"sub_months": 1,
"is_auto_renew": false,
"status": "active",
"start_datetime": "2020-01-01T00:00:00Z",
"expiry_datetime": "2020-02-01T00:00:00Z"
}
}
/v2/shops/<shop_key>/get_subscription?user_id=<id>
/v2/shops/<shop_key>/get_subscription?provider_user_id=<id>
Subscription Webhook
{
"shop_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0cgoLEgRTaG9wGAIM",
"shop_type": "subscriptions",
"action": "new", // new, updated, restore
"user_id": "",
"provider_user_id": "",
"purchase": {
"purchase_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0chkLEgxTaG9wUHVyY2hhc2UYgICAgICAwAkM",
"package_key": "ahBkZXZ-bG92ZW50ZWR0ZXN0cg0LEgdQYWNrYWdlGAMM",
"type": "subscription",
"platform": "android", // android, free, ios, stripe
"sub_months": 1,
"price": 0,
"is_auto_renew": false,
"status": "active", // active, grace_period, expired
"start_datetime": "2020-01-01T00:00:00Z",
"expiry_datetime": "2020-02-01T00:00:00Z",
"grace_end": "2020-02-01T00:00:00Z" // May not be included
}
}
JSON data is sent to webhook url which is defined in Shop.request_config. The webhook request is dispatched when a new subscription is created, it is updated, or moved to another user (action)
Notes:
- package_key is not unique
- sub_months is a rouch value. It should not be used to calculate anything
- grace_end may not be included
Topic and TopicPush
Topic
Response JSON (get)
{
"topic_key": "<topic_key>",
"topic": "0000-0000",
"title": "Title",
"description": "Description",
"app_keys": [ ],
"image": { }
}
Request JSON (create/update)
{
"topic": "",
"title": "Title",
"description": "Description",
"image_id": "<image_id>"
}
topic is optional; if not provided, random uuid will be generated. topic value is trimmed and whitespaces will be changed to underscores.
GET all
GET /dev/v2/topics/<topic_key>
Get params: ?next=<next_token>
CREATE
POST /dev/v2/topics
GET one
GET /dev/v2/topics/<topic_key>
UPDATE
POST /dev/v2/topics/<topic_key>
DELETE
Topic with TopicPushes cannot be delete.
DELETE /dev/v2/topics/<topic_key>
TopicPush
Response JSON for GET ALL:
{
"scheduled": [ ],
"sent": [ ],
"next": "<next_token for sent>"
}
Response JSON (get)
{
"topic_push_key": "<topic_push_key>",
"data": {
"title": "Title",
"body": "Body",
"internal_url": "choicely://contest/unlimited-free-votes",
"image_id": "<image_id>"
},
"apsn": {
"payload": {
"aps": {
"alert": {
"title": "Title",
"body": "Body"
},
"mutable-content": 1,
"sound": "default"
}
},
"headers": {
"apns-priority": "10"
}
},
"is_linked_to_publisher": false,
"is_sent": true,
"scheduled": "2020-01-01T00:00:00Z",
"sent": "2020-01-01T00:00:00Z",
"push_results": [
{
"status_code": 200,
"success": true,
"app_key": "<app_key>",
"has_firebase_project": true,
"firebase_project": {
"firebase_project_key": "<firebase_project_key>"
}
}
],
"updated": "2020-01-01T00:00:00Z",
"created": "2020-01-01T00:00:00Z"
}
Request JSON (create/update):
{
"data": {
"title": "Title",
"body": "Body",
"internal_url": "choicely://contest/<contest_id>",
"image_id": "<image_id>"
},
"scheduled": "2020-01-01T00:00:00Z"
}
GET all
next token is for fetching more sent pushes.
All scheduled pushes are included in response when next token is not provided in request.
GET /dev/v2/topics/<topic_key>/topicpushes
Get params: ?next=<next_token>
CREATE
data (json) and body (string) are required values.
If scheduled is not provided or it's in the past, the push will be sent immediately. IMPORTANT: scheduled can be set maximum of 30 days forward from current time.
Note that because pushes are send in a task after create request, this endpoint will always show "is_sent": false
.
Note: Remember to include full list of app_keys if app_keys are included in the request.
POST /dev/v2/topics/<topic_key>/topicpushes
GET one
GET /dev/v2/topicpushes/<topic_push_key>
UPDATE
Updating is not possible if push has been sent "is_sent": true
POST /dev/v2/topicpushes/<topic_push_key>
DELETE
Deleting is not possible if push has been sent "is_sent": true
DELETE /dev/v2/topicpushes/<topic_push_key>