Référence de l’API

Créer une surveillance Monitoring

POST/v1/watches

Contrat v1 / 1.0.0 62 / 2026-10-10

Sur cette page

Rattachez une adresse à un projet Monitoring existant avec des règles indépendantes. Les projets sont créés dans Account. Une adresse peut être utilisée dans différents projets. Répéter un rattachement identique ne constitue pas une API générale de mise à jour des règles ; utilisez Account pour les modifier.

Permissions de la clé : watches / write / monitoring.

Corps de la requête

ChampTypeObligatoireDescription
projectstringNonID du projet. Requis pour lister ou créer des surveillances sauf si la clé est limitée à un projet. Pour les autres opérations, l’omission utilise le contexte de compte/projet de l’opération ; indiquez-le explicitement.
chainstringOuiCode réseau issu de GET /v1/chains.
minLength: 1
addressstringOuiAdresse dans le réseau sélectionné ; validée et normalisée.
minLength: 1
assetstringNonActif par défaut pour exact : native, symbole pris en charge ou identifiant de token.
Par défaut : native
labelstringNonLibellé du carnet d’adresses.
maxLength: 60
notestringNonNote facultative du carnet d’adresses.
maxLength: 280
watch_outgoingbooleanNonRecevoir également les opérations sortantes ; le réseau doit les prendre en charge.
Par défaut : false
asset_policystringNonexact sélectionne un actif ; allow utilise asset_ids ; all sélectionne tous les actifs du réseau. Les réseaux sans tokens ne prennent en charge que native/exact.
exact, allow, all ; Par défaut : exact
asset_idsstring[]NonExactement un pour exact, au moins un pour allow, vide pour all. Avec exact et une liste vide, asset est utilisé.
maxItems: 100
excluded_asset_idsstring[]NonActifs à exclure.
maxItems: 100
min_confirmationsintegerNonConfirmations minimales.
Par défaut : 0 ; minimum: 0
min_amountstringNonSeuil non négatif en plus petites unités, pas un montant décimal.
pattern: ^[0-9]+$
watch_contractsbooleanNonRecevoir les événements de contrat pris en charge.
Par défaut : false
watch_unexpected_assetsbooleanNonRecevoir les événements d’actifs inattendus.
Par défaut : false
application/json
{
  "project": "1002",
  "chain": "ethereum",
  "address": "0x52908400098527886E0F7030069857D2E4169EE7",
  "asset": "native",
  "label": "Treasury"
}

Exemples de requêtes

Les exemples réalisent une opération réelle dans votre compte. Définissez les variables d’environnement nommées dans le code. Gardez votre clé privée ; les requêtes d’écriture ne sont pas réessayées automatiquement.

Shell / cURL
#!/usr/bin/env bash
set -euo pipefail
: "${CRYPTANIO_API_KEY:?Set CRYPTANIO_API_KEY}"
: "${CRYPTANIO_PROJECT_ID:?Set CRYPTANIO_PROJECT_ID}"
json_string() {
  local text="$1" char code index output='"'
  for ((index=0; index<${#text}; index++)); do
    char="${text:index:1}"
    case "$char" in
      '"'|'\') output+="\\$char" ;;
      *) printf -v code '%d' "'$char"
         if ((code < 32)); then printf -v char '\\u%04x' "$code"; fi
         output+="$char" ;;
    esac
  done
  printf '%s"' "$output"
}
response_file="$(mktemp)"
trap 'rm -f "$response_file"' EXIT
transfer_status=0
http_status="$(curl \
  --silent --show-error --max-time 30 --request POST \
  --header "Authorization: Bearer $CRYPTANIO_API_KEY" \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data-binary '{"project":'"$(json_string "$CRYPTANIO_PROJECT_ID")"',"chain":"ethereum","address":"0x52908400098527886E0F7030069857D2E4169EE7","asset":"native","label":"Treasury"}' \
  "https://api.cryptanio.com/v1/watches" \
  --output "$response_file" --write-out '%{http_code}')" || transfer_status=$?
if [[ "$http_status" == 2?? ]]; then
  cat "$response_file"
  exit "$transfer_status"
fi
printf 'HTTP %s\n' "$http_status" >&2
cat "$response_file" >&2
exit 1
Télécharger l’exemple
Go
// Go; standard library only. Run: go run request.go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "time"
)

func env(name string) string {
    value := os.Getenv(name)
    if value == "" { fmt.Fprintln(os.Stderr, "Set", name); os.Exit(1) }
    return value
}
func run() error {
    path := "/v1/watches"

    endpoint, err := url.Parse("https://api.cryptanio.com" + path)
    if err != nil { return err }
    query := endpoint.Query()

    endpoint.RawQuery = query.Encode()
    var payload map[string]any
    if err := json.Unmarshal([]byte("{\"project\":\"1002\",\"chain\":\"ethereum\",\"address\":\"0x52908400098527886E0F7030069857D2E4169EE7\",\"asset\":\"native\",\"label\":\"Treasury\"}"), &payload); err != nil { return err }
    payload["project"] = env("CRYPTANIO_PROJECT_ID")
    body, err := json.Marshal(payload)
    if err != nil { return err }
    request, err := http.NewRequest("POST", endpoint.String(), bytes.NewReader(body))
    if err != nil { return err }
    request.Header.Set("Authorization", "Bearer " + env("CRYPTANIO_API_KEY"))
    request.Header.Set("Accept", "application/json")
    request.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 30 * time.Second, CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}
    response, err := client.Do(request)
    if err != nil { return err }
    defer response.Body.Close()
    if response.StatusCode < 200 || response.StatusCode >= 300 {
        body, err := io.ReadAll(response.Body)
        if err != nil { return err }
        return fmt.Errorf("HTTP %d: %s", response.StatusCode, body)
    }
    _, err = io.Copy(os.Stdout, response.Body)
    return err
}
func main() {
    if err := run(); err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
}
Télécharger l’exemple
Rust
// Cargo.toml dependencies:
// reqwest = { version = "=0.12.24", features = ["blocking", "json"] }
// serde_json = "=1.0.145"
use std::{error::Error, io, time::Duration};
use reqwest::{blocking::Client, redirect::Policy, Method, Url};

fn env(name: &str) -> Result<String, Box<dyn Error>> {
    let value = std::env::var(name)?;
    if value.is_empty() { return Err(format!("Set {name}").into()); }
    Ok(value)
}
fn run() -> Result<(), Box<dyn Error>> {
    let mut url = Url::parse("https://api.cryptanio.com")?;
    {
        let mut segments = url.path_segments_mut().map_err(|_| "Invalid base URL")?;
        segments.clear();
        segments.push("v1");
        segments.push("watches");
    }
    let client = Client::builder().timeout(Duration::from_secs(30)).redirect(Policy::none()).build()?;
    let request = client.request(Method::POST, url)
        .header("Authorization", format!("Bearer {}", env("CRYPTANIO_API_KEY")?))
        .header("Accept", "application/json".to_owned())
        .header("Content-Type", "application/json".to_owned());
    let mut body: serde_json::Value = serde_json::from_str("{\"project\":\"1002\",\"chain\":\"ethereum\",\"address\":\"0x52908400098527886E0F7030069857D2E4169EE7\",\"asset\":\"native\",\"label\":\"Treasury\"}")?;
    body["project"] = serde_json::Value::String(env("CRYPTANIO_PROJECT_ID")?);
    let request = request.json(&body);
    let mut response = request.send()?;
    let status = response.status();
    if !status.is_success() { return Err(format!("HTTP {}: {}", status.as_u16(), response.text()?).into()); }
    io::copy(&mut response, &mut io::stdout())?;
    Ok(())
}
fn main() {
    if let Err(error) = run() { eprintln!("{error}"); std::process::exit(1); }
}
Télécharger l’exemple
PHP
<?php
// PHP 8 with the cURL extension. Run this on your server.
function env(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '') throw new RuntimeException('Set ' . $name);
    return $value;
}
try {
    $path = '/v1/watches';

    $query = [

    ];
    $url = 'https://api.cryptanio.com' . $path . ($query ? '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986) : '');
    $headers = [
        'Authorization: ' . 'Bearer ' . env('CRYPTANIO_API_KEY'),
        'Accept: ' . 'application/json',
        'Content-Type: ' . 'application/json',
    ];
    $body = json_decode('{"project":"1002","chain":"ethereum","address":"0x52908400098527886E0F7030069857D2E4169EE7","asset":"native","label":"Treasury"}', true, 512, JSON_THROW_ON_ERROR);
    $body['project'] = env('CRYPTANIO_PROJECT_ID');
    $curl = curl_init($url);
    curl_setopt_array($curl, [
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_POSTFIELDS => json_encode($body, JSON_THROW_ON_ERROR),
    ]);
    $response = curl_exec($curl);
    if ($response === false) throw new RuntimeException(curl_error($curl));
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    if ($status < 200 || $status >= 300) throw new RuntimeException('HTTP ' . $status . ': ' . $response);
    echo $response;
} catch (Throwable $error) {
    fwrite(STDERR, $error->getMessage() . PHP_EOL);
    exit(1);
}
Télécharger l’exemple
Python
# Python 3; standard library only.
import json
import os
import sys
from urllib.error import HTTPError, URLError
from urllib.parse import quote, urlencode
from urllib.request import HTTPRedirectHandler, Request, build_opener

def env(name):
    result = os.environ.get(name)
    if not result:
        raise ValueError("Set " + name)
    return result

class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None

try:
    path = "/v1/watches"

    query = {

    }
    url = "https://api.cryptanio.com" + path + ("?" + urlencode(query) if query else "")
    headers = {
        "Authorization": "Bearer " + env("CRYPTANIO_API_KEY"),
        "Accept": "application/json",
        "Content-Type": "application/json",
    }
    body = json.loads("{\"project\":\"1002\",\"chain\":\"ethereum\",\"address\":\"0x52908400098527886E0F7030069857D2E4169EE7\",\"asset\":\"native\",\"label\":\"Treasury\"}")
    body["project"] = env("CRYPTANIO_PROJECT_ID")
    data = json.dumps(body).encode("utf-8")
    request = Request(url, data=data, headers=headers, method="POST")
    with build_opener(NoRedirect()).open(request, timeout=30) as response:
        if not 200 <= response.status < 300:
            raise ValueError("HTTP " + str(response.status))
        sys.stdout.buffer.write(response.read())
except HTTPError as error:
    print("HTTP " + str(error.code) + ": " + error.read().decode("utf-8", errors="replace"), file=sys.stderr)
    sys.exit(1)
except (ValueError, URLError, OSError) as error:
    print(str(error), file=sys.stderr)
    sys.exit(1)
Télécharger l’exemple
Node.js
// Node.js 18+. Run on your server, never in a browser.
const env = name => {
  const result = process.env[name];
  if (!result) throw new Error(`Set ${name}`);
  return result;
};
try {
  let path = "/v1/watches";

  const url = new URL(path, "https://api.cryptanio.com");

  const headers = {
    "Authorization": "Bearer " + env("CRYPTANIO_API_KEY"),
    "Accept": "application/json",
    "Content-Type": "application/json",
  };
  const body = {
    "project": "1002",
    "chain": "ethereum",
    "address": "0x52908400098527886E0F7030069857D2E4169EE7",
    "asset": "native",
    "label": "Treasury"
  };
  body["project"] = env("CRYPTANIO_PROJECT_ID");
  const response = await fetch(url, {
    method: "POST", headers, redirect: "manual",
    signal: AbortSignal.timeout(30_000), body: JSON.stringify(body),
  });
  if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  if (response.body) {
    for await (const chunk of response.body) process.stdout.write(chunk);
  }
} catch (error) {
  console.error(error.message);
  process.exitCode = 1;
}
Télécharger l’exemple

Réponses et erreurs

201 Réponse réussie.
ChampTypeObligatoireDescription
idstringOuiIdentifiant opaque ; conservez-le sous forme de chaîne.
minLength: 1
project_idstringOuiIdentifiant opaque ; conservez-le sous forme de chaîne.
minLength: 1
servicestringOuiService du projet.
monitoring
book_address_idstringOuiID de l’adresse correspondante dans le carnet d’adresses.
minLength: 1
statusstringOuiÉtat du rattachement projet-adresse.
active, paused, deleted
chainstringOuiCode réseau.
addressstringOuiAdresse normalisée.
assetstringOuiActifs dans la chaîne de réponse ; plusieurs actifs sont séparés par des virgules.
metaobjectNonLibellé et note de l’adresse, si configurés.
watched_asstringNonIdentifiant supplémentaire de l’adresse, si le réseau l’utilise.
sandboxbooleanNontrue pour une surveillance de test ; l’omission signifie false.
watch_outgoingbooleanOuiIndique si les opérations sortantes sont surveillées.
origin_kindsstring[]OuiModes d’ajout de l’adresse au projet.
created_atstringOuiDate et heure UTC selon RFC 3339.
date-time
201 application/json
{
  "id": "1008",
  "project_id": "1002",
  "service": "monitoring",
  "book_address_id": "1007",
  "status": "active",
  "chain": "ethereum",
  "address": "0x52908400098527886E0F7030069857D2E4169EE7",
  "asset": "native",
  "sandbox": true,
  "watch_outgoing": false,
  "origin_kinds": [
    "manual"
  ],
  "created_at": "2026-10-06T10:00:00Z"
}
400 Requête invalide (bad_request, unsupported_asset).
ChampTypeObligatoireDescription
errorobjectOui
400 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
401 Aucune clé API active valide (unauthorized).
ChampTypeObligatoireDescription
errorobjectOui
401 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
402 Limite de ressources atteinte (limit_reached).
ChampTypeObligatoireDescription
errorobjectOui
402 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
403 La clé n’autorise pas l’opération, le projet, le service ou l’IP ; e-mail non confirmé.
ChampTypeObligatoireDescription
errorobjectOui
403 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
409 Conflit d’état, paramètres de nouvelle tentative contradictoires ou limite de ressources de paiement (conflict, limit_reached, service_inactive).
ChampTypeObligatoireDescription
errorobjectOui
409 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
429 Trop de requêtes (rate_limited) ; réessayez après Retry-After.
ChampTypeObligatoireDescription
errorobjectOui
429 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
500 Erreur interne (internal).
ChampTypeObligatoireDescription
errorobjectOui
500 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
503 Indisponibilité temporaire (unavailable) ; réessayez avec un délai progressif.
ChampTypeObligatoireDescription
errorobjectOui
503 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}

Gestion des erreurs et nouvelles tentatives sûres

Objets imbriqués

Watch

ChampTypeObligatoireDescription
idstringOuiIdentifiant opaque ; conservez-le sous forme de chaîne.
minLength: 1
project_idstringOuiIdentifiant opaque ; conservez-le sous forme de chaîne.
minLength: 1
servicestringOuiService du projet.
monitoring
book_address_idstringOuiID de l’adresse correspondante dans le carnet d’adresses.
minLength: 1
statusstringOuiÉtat du rattachement projet-adresse.
active, paused, deleted
chainstringOuiCode réseau.
addressstringOuiAdresse normalisée.
assetstringOuiActifs dans la chaîne de réponse ; plusieurs actifs sont séparés par des virgules.
metaobjectNonLibellé et note de l’adresse, si configurés.
watched_asstringNonIdentifiant supplémentaire de l’adresse, si le réseau l’utilise.
sandboxbooleanNontrue pour une surveillance de test ; l’omission signifie false.
watch_outgoingbooleanOuiIndique si les opérations sortantes sont surveillées.
origin_kindsstring[]OuiModes d’ajout de l’adresse au projet.
created_atstringOuiDate et heure UTC selon RFC 3339.
date-time
ID

Identifiant opaque. Son format n’est pas garanti ; ne le convertissez pas en nombre.

string Identifiant opaque. Son format n’est pas garanti ; ne le convertissez pas en nombre.

StringMap

object

WatchRequest

ChampTypeObligatoireDescription
projectstringNonID du projet. Requis pour lister ou créer des surveillances sauf si la clé est limitée à un projet. Pour les autres opérations, l’omission utilise le contexte de compte/projet de l’opération ; indiquez-le explicitement.
chainstringOuiCode réseau issu de GET /v1/chains.
minLength: 1
addressstringOuiAdresse dans le réseau sélectionné ; validée et normalisée.
minLength: 1
assetstringNonActif par défaut pour exact : native, symbole pris en charge ou identifiant de token.
Par défaut : native
labelstringNonLibellé du carnet d’adresses.
maxLength: 60
notestringNonNote facultative du carnet d’adresses.
maxLength: 280
watch_outgoingbooleanNonRecevoir également les opérations sortantes ; le réseau doit les prendre en charge.
Par défaut : false
asset_policystringNonexact sélectionne un actif ; allow utilise asset_ids ; all sélectionne tous les actifs du réseau. Les réseaux sans tokens ne prennent en charge que native/exact.
exact, allow, all ; Par défaut : exact
asset_idsstring[]NonExactement un pour exact, au moins un pour allow, vide pour all. Avec exact et une liste vide, asset est utilisé.
maxItems: 100
excluded_asset_idsstring[]NonActifs à exclure.
maxItems: 100
min_confirmationsintegerNonConfirmations minimales.
Par défaut : 0 ; minimum: 0
min_amountstringNonSeuil non négatif en plus petites unités, pas un montant décimal.
pattern: ^[0-9]+$
watch_contractsbooleanNonRecevoir les événements de contrat pris en charge.
Par défaut : false
watch_unexpected_assetsbooleanNonRecevoir les événements d’actifs inattendus.
Par défaut : false
RawAmount

string

Error

ChampTypeObligatoireDescription
errorobjectOui