curl --request POST \
--url https://tako.com/api/v1/monitors \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"type": "<string>",
"parameters": {},
"name": "",
"fire_once": true,
"channel_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"actions": [
{}
],
"active_from": "2023-11-07T05:31:56Z",
"active_until": "2023-11-07T05:31:56Z"
}
'import requests
url = "https://tako.com/api/v1/monitors"
payload = {
"type": "<string>",
"parameters": {},
"name": "",
"fire_once": True,
"channel_ids": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"],
"actions": [{}],
"active_from": "2023-11-07T05:31:56Z",
"active_until": "2023-11-07T05:31:56Z"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: '<string>',
parameters: {},
name: '',
fire_once: true,
channel_ids: ['3c90c3cc-0d44-4b50-8888-8dd25736052a'],
actions: [{}],
active_from: '2023-11-07T05:31:56Z',
active_until: '2023-11-07T05:31:56Z'
})
};
fetch('https://tako.com/api/v1/monitors', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://tako.com/api/v1/monitors",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => '<string>',
'parameters' => [
],
'name' => '',
'fire_once' => true,
'channel_ids' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'actions' => [
[
]
],
'active_from' => '2023-11-07T05:31:56Z',
'active_until' => '2023-11-07T05:31:56Z'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://tako.com/api/v1/monitors"
payload := strings.NewReader("{\n \"type\": \"<string>\",\n \"parameters\": {},\n \"name\": \"\",\n \"fire_once\": true,\n \"channel_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"actions\": [\n {}\n ],\n \"active_from\": \"2023-11-07T05:31:56Z\",\n \"active_until\": \"2023-11-07T05:31:56Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://tako.com/api/v1/monitors")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"<string>\",\n \"parameters\": {},\n \"name\": \"\",\n \"fire_once\": true,\n \"channel_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"actions\": [\n {}\n ],\n \"active_from\": \"2023-11-07T05:31:56Z\",\n \"active_until\": \"2023-11-07T05:31:56Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://tako.com/api/v1/monitors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"<string>\",\n \"parameters\": {},\n \"name\": \"\",\n \"fire_once\": true,\n \"channel_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"actions\": [\n {}\n ],\n \"active_from\": \"2023-11-07T05:31:56Z\",\n \"active_until\": \"2023-11-07T05:31:56Z\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "<string>",
"parameters": {},
"subject": {},
"fire_once": true,
"status": "active",
"status_reason": "fired_once",
"active_from": "2023-11-07T05:31:56Z",
"active_until": "2023-11-07T05:31:56Z",
"last_evaluated_at": "2023-11-07T05:31:56Z",
"last_evaluation_outcome": "fired",
"channel_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"actions": [
{}
],
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error_message": "<string>",
"error_type": "BAD_REQUEST",
"candidates": [],
"limit": 123
}{
"error_message": "<string>",
"error_type": "BAD_REQUEST"
}{
"error_message": "<string>",
"error_type": "BAD_REQUEST"
}Create a monitor
Create a condition on data that posts to your notification channels when it occurs
curl --request POST \
--url https://tako.com/api/v1/monitors \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"type": "<string>",
"parameters": {},
"name": "",
"fire_once": true,
"channel_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"actions": [
{}
],
"active_from": "2023-11-07T05:31:56Z",
"active_until": "2023-11-07T05:31:56Z"
}
'import requests
url = "https://tako.com/api/v1/monitors"
payload = {
"type": "<string>",
"parameters": {},
"name": "",
"fire_once": True,
"channel_ids": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"],
"actions": [{}],
"active_from": "2023-11-07T05:31:56Z",
"active_until": "2023-11-07T05:31:56Z"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: '<string>',
parameters: {},
name: '',
fire_once: true,
channel_ids: ['3c90c3cc-0d44-4b50-8888-8dd25736052a'],
actions: [{}],
active_from: '2023-11-07T05:31:56Z',
active_until: '2023-11-07T05:31:56Z'
})
};
fetch('https://tako.com/api/v1/monitors', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://tako.com/api/v1/monitors",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => '<string>',
'parameters' => [
],
'name' => '',
'fire_once' => true,
'channel_ids' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'actions' => [
[
]
],
'active_from' => '2023-11-07T05:31:56Z',
'active_until' => '2023-11-07T05:31:56Z'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://tako.com/api/v1/monitors"
payload := strings.NewReader("{\n \"type\": \"<string>\",\n \"parameters\": {},\n \"name\": \"\",\n \"fire_once\": true,\n \"channel_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"actions\": [\n {}\n ],\n \"active_from\": \"2023-11-07T05:31:56Z\",\n \"active_until\": \"2023-11-07T05:31:56Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://tako.com/api/v1/monitors")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"<string>\",\n \"parameters\": {},\n \"name\": \"\",\n \"fire_once\": true,\n \"channel_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"actions\": [\n {}\n ],\n \"active_from\": \"2023-11-07T05:31:56Z\",\n \"active_until\": \"2023-11-07T05:31:56Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://tako.com/api/v1/monitors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"<string>\",\n \"parameters\": {},\n \"name\": \"\",\n \"fire_once\": true,\n \"channel_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"actions\": [\n {}\n ],\n \"active_from\": \"2023-11-07T05:31:56Z\",\n \"active_until\": \"2023-11-07T05:31:56Z\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "<string>",
"parameters": {},
"subject": {},
"fire_once": true,
"status": "active",
"status_reason": "fired_once",
"active_from": "2023-11-07T05:31:56Z",
"active_until": "2023-11-07T05:31:56Z",
"last_evaluated_at": "2023-11-07T05:31:56Z",
"last_evaluation_outcome": "fired",
"channel_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"actions": [
{}
],
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error_message": "<string>",
"error_type": "BAD_REQUEST",
"candidates": [],
"limit": 123
}{
"error_message": "<string>",
"error_type": "BAD_REQUEST"
}{
"error_message": "<string>",
"error_type": "BAD_REQUEST"
}Notes
- To authenticate, you’ll need a Tako API key. It’s best practice to store it as an environment variable to avoid hardcoding sensitive credentials in your code.
typeis the name of a registered monitor type, and Tako validatesparametersagainst that type’s schema. Call List monitor types first, and buildparametersfrom the type’sparameters_schema.- Every
channel_idsentry must be a channel you own, so create the channel before the monitor. An id you don’t own returns404. channel_idsis optional. A monitor with no channels records its firings, and you read them with List a monitor’s firings. To add channels later, call Update a monitor.nameis your own label. Tako never fills one in, and never reads it.fire_oncedefaults totrue, which pauses the monitor after its first firing. To fire on every new occurrence, set it tofalse. A type that reportsfire_once_onlyrejects that.active_fromdefaults to the moment you create the monitor.active_untilmust be in the future and afteractive_from.- You can hold a limited number of active monitors. When you’re at that limit, this endpoint returns
400witherror_type: LIMIT_REACHED. See Handle a rejected create. - When the monitor fires, Tako posts to every channel you listed. For the request body, the headers, and how to verify the signature, see Webhook deliveries.
lookback_seconds in List monitor types says how far back an occurrence may have happened and still fire, and its description says how long its source takes to report one.Check the resolved subject
The response holdssubject: the subject the type matched from your parameters, such as the listing a ticker matched. Read it and confirm the monitor watches what you meant. Tako resolves the subject once, when you create the monitor, and never again. Get a monitor and List monitors return the same subject.
parameters comes back in the form this endpoint accepts, with names as Tako resolved them. A ticker you sent as aapl reads back as AAPL, with the exchange that Tako picked.
Handle a rejected create
A400 returns a MonitorCreateRejected with an error_type:
AMBIGUOUS_SUBJECT: your parameters match more than one subject.candidateslists every one, best first. Narrow the parameters and retry.LIMIT_REACHED: you’re at your active monitor limit.limitis your cap, anderror_messagesays how to free a slot. Pause or delete a monitor you no longer need, or contact support@tako.com about an enterprise limit.BAD_REQUEST: anything else.candidatesis empty andlimitisnull.
active_until doesn’t count against it.Authorizations
Body
A registered monitor type name, domain.subtype, for example stocks.pct_change.
64Tako validates these against the type's parameter schema.
Your label for the monitor. Tako never fills one in, and never reads it.
255Pause the monitor after its first firing. To fire on every new occurrence, set it to false, which a type that reports fire_once_only rejects.
Destinations to post each firing to. Empty means no delivery: the firings are still recorded and readable through listMonitorFirings.
20What Tako does after the monitor fires, in order. Each entry is an object with kind, that kind's parameters, and optionally channel_ids. channel_ids sets where the action's output goes: leave it out to use the monitor's channels, list channels you own to use those, or send an empty list to keep the output in Tako. Actions aren't available yet, so a non-empty list returns 400.
5Ignore occurrences before this time. Null means from the moment you create the monitor.
Pause the monitor as expired after this time. Null means the monitor has no end. The value must be in the future and after active_from.
Response
The new monitor, in the same shape every later read returns
The parameters in the form createMonitor accepts, as this type's parameters_schema describes them. The ids Tako resolved them to never appear here. The names come back as Tako resolved them rather than as you typed them, so a stock monitor created with ticker aapl reads back ticker AAPL and the exchange MIC that resolution picked. A type whose input accepts more than one name for a subject can return a different one than you sent: a crypto monitor names the asset by coinmarketcap_id whichever name you created it with. A monitor Tako can no longer render against its type's current schema returns a reduced form; subject still names what it watches.
The subject the type resolved from your parameters, such as the listing that a ticker matched, in the shape listMonitorTypes returns as subject_schema. Check it before you rely on the monitor. Tako resolves it once, when you create the monitor, and never re-resolves it, so it names what the monitor watches rather than what that subject is called today. Empty for a type that resolves no subject.
Show child attributes
Show child attributes
active, paused Why Tako paused the monitor. Null while the monitor is active, and null when you paused it yourself.
fired_once, unloadable, expired, completed When Tako last evaluated this monitor. Null until the first evaluation.
How that evaluation ended. Null until the first evaluation, and null again after you resume a paused monitor, because the pause makes the earlier outcome meaningless. On an active monitor with no firings, a recent predates_monitor or before_window means the monitor is running and waiting for an occurrence that happens after you created it. no_occurrence means the type found no occurrence, which includes finding no usable data to compare.
fired, already_fired, no_occurrence, predates_monitor, outside_lookback, unloadable, completed, unknown_type, inactive, deleted, expired, before_window, crashed The monitor's actions as Tako stored them: the fields you set on each action, and channel_ids only on an action where you set it. A field you left out takes the kind's default when the action runs. Empty for a monitor with no actions.