API ドキュメント

Cryptanio をアプリケーションに接続しましょう。

契約 v1 / 1.0.0 62 / 2026-10-10

目次

始める

API はサーバー向けです。先に Account でプロジェクト、サービス、アドレスプールを設定してください。API はその中で、キーが許可する操作を実行します。

  1. アカウントを確認し、マイサービスで必要なサービスを有効にしてください。
  2. 最小限の権限で API キーを作成し、サーバーに保管してください。
  3. 目的を選択してください:アドレスを監視、請求書を作成、またはイベントを受信。

サンプルは実データに対して実際の操作を行います。オブジェクトの作成や削除でサービスの割当量を消費する場合があります。キーはサンプルに埋め込まず、環境変数から読み取ります。

エージェントへの指示

この指示をエージェントのチャットまたはプロジェクトのルールに貼り付けてください。エージェントがサービス、料金、リファレンスを理解し、REST API または SDK を使ったアプリケーション連携を実装するのに役立ちます。エージェントはあなたの言語で回答できます。

連携の手順
Learn how to integrate a server-side application with Cryptanio's public REST API before proposing or writing integration code.

Start here:
- Website: https://cryptanio.com/
- Documentation index: https://cryptanio.com/llms.txt
- Product, services and pricing: https://cryptanio.com/cryptanio.md
- API integration index: https://cryptanio.com/docs/llms.txt
- API guide: https://cryptanio.com/docs.md
- Exact API v1 contract: https://cryptanio.com/openapi.json
- FAQ: https://cryptanio.com/faq/index.md
- SDK setup and examples: https://cryptanio.com/docs.html#sdk

Read the relevant method reference before using it. Use the public API at https://api.cryptanio.com/v1. Do not assume a public sandbox exists.
Use HTTP requests or the documented SDK for the application's language. Match request fields, response schemas and errors to OpenAPI; do not invent endpoints or SDK methods.
Check the actual enabled networks, service, project and API key permissions. Product documentation is not evidence of a live payment, balance or deployment.
Keep API keys in the user's server environment or secret store. Never ask the user to paste a key into chat or put it in a URL, browser bundle or log.
Default to reading. Create, change or delete objects only when the user authorizes the specific task. Explain quota or billing consequences before a write.
Follow the documented confirmation, webhook verification, pagination and retry rules. Reuse an invoice's original Idempotency-Key and request when retrying.
Show the returned chain, asset, address, amount and expiry. Preserve payment_route.kind and its exact string value: destination_tag, memo, comment or reference is mandatory when present. The merchant order reference is a separate field.
For a payment QR use the returned payment_uri when present. A Solana Pay reference is not a wallet memo; do not rebuild its URI or replace it with a plain address. Offer the exact returned checkout_url only to the payer; never construct a checkout URL from an invoice ID. Neither a checkout redirect nor a QR scan confirms payment.
Distinguish pending, confirmed, rolled-back and simulated data. If a fact is unavailable, say so instead of guessing.
Answer the user's questions in their language. If a necessary product decision is not documented, ask instead of inventing it.

このブロックにキーやアカウントデータは含まれていません。連携に必要な最小限の権限を持つ API キーを使用し、アプリケーションサーバーで保管してください。エージェントのチャットでキーを共有しないでください。

API リファレンス

メソッド:16

認証

サーバーから Authorization: Bearer <API_KEY> を送信してください。Account → API キーで実データ用のキーを作成し、必要なプロジェクトと操作に制限してください。公開サンドボックスは現在提供していません。

キーには読み取り専用、特定の操作、単一のプロジェクトやサービス、指定した IP/CIDR 範囲のアクセスを許可できます。有効期限、一時停止、失効もアクセスに影響します。キーを更新するには、適切な制限を持つ新しいキーを作成し、連携を切り替えてから古いキーを失効させてください。ブラウザーのコード、モバイルアプリ、URL にキーを埋め込まないでください。

範囲目的
watchesMonitoring
eventsイベントと支払い
invoicesPayments の請求書
webhooksWebhook エンドポイント
streamSSE

制限は互いに置き換わるのではなく、同時に適用されます。401 はキーが受け入れられなかったことを示し、403 は権限不足または許可されていない IP を示す場合があります。アクセスできないリソースは 404 を返す場合があります。エラーと再試行を参照してください。

SDK:すぐに使えるクライアント

使用する言語のファイルをダウンロードし、アプリケーションサーバーに保存して、コンストラクターにキーを渡してください。各クライアントはこのリファレンスの全 16 メソッドに対応しています。インストールする npm、PyPI、Composer、crates.io のパッケージはなく、ダウンロードしたファイルが SDK です。

言語要件ファイル
Node.jsNode.js 18+cryptanio.mjs
PythonPython 3.10+cryptanio.py
PHPPHP 8.1+ / cURLCryptanio.php
GoGo 1.22+cryptanio.go
RustRust 2021 / reqwest 0.12 / serde_json 1cryptanio.rs

これらのファイルはリリース 1.0.0 62 に属します。マニフェストには、バージョン、契約、各ファイルの SHA-256 が記載されています。先に環境変数へ CRYPTANIO_API_KEY と CRYPTANIO_PROJECT_ID を設定してください。これらの例はイベントの読み取りのみを行いますが、実際のアカウントデータにアクセスします。

Node.js

例を .mjs ファイルとして cryptanio.mjs と同じ場所に保存してください。

Node.js
import { Cryptanio } from './cryptanio.mjs';
const key = process.env.CRYPTANIO_API_KEY;
const project = process.env.CRYPTANIO_PROJECT_ID;
if (!key || !project) throw new Error('Set API key and project ID');
const api = new Cryptanio(key);
const page = await api.listEvents({ project, limit: 25 });
console.log(page);

既存インボイスの支払い案内を読み取るには、そのIDをCRYPTANIO_RESOURCE_IDに設定します。次の例は必須のpayment_route、QR用に返されたpayment_uri、正確なcheckout_urlを保持します。結果は自分の画面を通じて支払者に渡し、公開ログには記録しないでください。金額は文字列のまま保持され、存在しないフィールドは省略されます。

Node.js
import { Cryptanio } from './cryptanio.mjs';
const key = process.env.CRYPTANIO_API_KEY;
const invoiceID = process.env.CRYPTANIO_RESOURCE_ID;
if (!key || !invoiceID) throw new Error('Set API key and invoice ID');
const api = new Cryptanio(key);
const invoice = await api.getInvoice(invoiceID);
const payment = {
  chain: invoice.chain, asset: invoice.asset, address: invoice.address,
  amount: invoice.amount, expires_at: invoice.expires_at,
  payment_route: invoice.payment_route,
  payment_uri: invoice.payment_uri, checkout_url: invoice.checkout_url,
};
console.log(JSON.stringify(payment, null, 2));
Python

例を .py ファイルとして cryptanio.py と同じ場所に保存してください。

Python
import os
from cryptanio import Cryptanio
api = Cryptanio(os.environ['CRYPTANIO_API_KEY'])
page = api.list_events({
    'project': os.environ['CRYPTANIO_PROJECT_ID'], 'limit': 25
})
print(page)

既存インボイスの支払い案内を読み取るには、そのIDをCRYPTANIO_RESOURCE_IDに設定します。次の例は必須のpayment_route、QR用に返されたpayment_uri、正確なcheckout_urlを保持します。結果は自分の画面を通じて支払者に渡し、公開ログには記録しないでください。金額は文字列のまま保持され、存在しないフィールドは省略されます。

Python
import json
import os
from cryptanio import Cryptanio
api = Cryptanio(os.environ['CRYPTANIO_API_KEY'])
invoice = api.get_invoice(os.environ['CRYPTANIO_RESOURCE_ID'])
payment = {field: invoice[field] for field in (
    'chain', 'asset', 'address', 'amount', 'expires_at',
    'payment_route', 'payment_uri', 'checkout_url'
) if field in invoice}
print(json.dumps(payment, ensure_ascii=False))
PHP

例を .php ファイルとして Cryptanio.php と同じ場所に保存し、cURL 拡張機能を有効にしてください。

PHP
<?php
require __DIR__ . '/Cryptanio.php';
$key = getenv('CRYPTANIO_API_KEY');
$project = getenv('CRYPTANIO_PROJECT_ID');
if (!$key || !$project) throw new RuntimeException('Set API key and project ID');
$api = new Cryptanio($key);
$page = $api->listEvents(['project' => $project, 'limit' => 25]);
echo json_encode($page, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);

既存インボイスの支払い案内を読み取るには、そのIDをCRYPTANIO_RESOURCE_IDに設定します。次の例は必須のpayment_route、QR用に返されたpayment_uri、正確なcheckout_urlを保持します。結果は自分の画面を通じて支払者に渡し、公開ログには記録しないでください。金額は文字列のまま保持され、存在しないフィールドは省略されます。

PHP
<?php
require __DIR__ . '/Cryptanio.php';
$key = getenv('CRYPTANIO_API_KEY');
$invoiceID = getenv('CRYPTANIO_RESOURCE_ID');
if (!$key || !$invoiceID) throw new RuntimeException('Set API key and invoice ID');
$api = new Cryptanio($key);
$invoice = $api->getInvoice($invoiceID);
$payment = array_intersect_key($invoice, array_fill_keys([
    'chain', 'asset', 'address', 'amount', 'expires_at',
    'payment_route', 'payment_uri', 'checkout_url'
], true));
echo json_encode($payment, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
Go

Go モジュール内の cryptanio/ ディレクトリにファイルを配置してください。この例ではモジュール example.local/myapp を使用しています。インポートパスを自分のモジュール名に置き換えてください。外部依存関係は不要です。

Go
package main

import (
    "context"
    "fmt"
    "os"
    "example.local/myapp/cryptanio"
)

func main() {
    key, project := os.Getenv("CRYPTANIO_API_KEY"), os.Getenv("CRYPTANIO_PROJECT_ID")
    if key == "" || project == "" { panic("Set API key and project ID") }
    api, err := cryptanio.New(key, "", 0)
    if err != nil { panic(err) }
    page, err := api.ListEvents(context.Background(), map[string]any{
        "project": project, "limit": 25,
    })
    if err != nil { panic(err) }
    fmt.Println(page)
}

既存インボイスの支払い案内を読み取るには、そのIDをCRYPTANIO_RESOURCE_IDに設定します。次の例は必須のpayment_route、QR用に返されたpayment_uri、正確なcheckout_urlを保持します。結果は自分の画面を通じて支払者に渡し、公開ログには記録しないでください。金額は文字列のまま保持され、存在しないフィールドは省略されます。

Go
package main

import (
    "context"
    "encoding/json"
    "os"
    "example.local/myapp/cryptanio"
)

func main() {
    key, invoiceID := os.Getenv("CRYPTANIO_API_KEY"), os.Getenv("CRYPTANIO_RESOURCE_ID")
    if key == "" || invoiceID == "" { panic("Set API key and invoice ID") }
    api, err := cryptanio.New(key, "", 0)
    if err != nil { panic(err) }
    invoice, err := api.GetInvoice(context.Background(), invoiceID)
    if err != nil { panic(err) }
    payment := make(map[string]any)
    for _, field := range []string{
        "chain", "asset", "address", "amount", "expires_at",
        "payment_route", "payment_uri", "checkout_url",
    } {
        if value, ok := invoice[field]; ok { payment[field] = value }
    }
    if err := json.NewEncoder(os.Stdout).Encode(payment); err != nil { panic(err) }
}
Rust

ファイルを src/cryptanio.rs、例を src/main.rs として保存してください。以下の依存関係を Cargo.toml に追加します。これは同期的に処理を待機するクライアントです。非同期ワーカー上で直接実行しないでください。

Cargo.toml
[dependencies]
reqwest = { version = "=0.12.24", default-features = false, features = ["blocking", "json", "rustls-tls"] }
serde_json = "=1.0.145"
Rust
mod cryptanio;
use cryptanio::Cryptanio;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Cryptanio::new(&std::env::var("CRYPTANIO_API_KEY")?)?;
    let project = std::env::var("CRYPTANIO_PROJECT_ID")?;
    let page = api.list_events(&[("project", &project), ("limit", "25")])?;
    println!("{page}");
    Ok(())
}

既存インボイスの支払い案内を読み取るには、そのIDをCRYPTANIO_RESOURCE_IDに設定します。次の例は必須のpayment_route、QR用に返されたpayment_uri、正確なcheckout_urlを保持します。結果は自分の画面を通じて支払者に渡し、公開ログには記録しないでください。金額は文字列のまま保持され、存在しないフィールドは省略されます。

Rust
mod cryptanio;
use cryptanio::Cryptanio;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Cryptanio::new(&std::env::var("CRYPTANIO_API_KEY")?)?;
    let invoice = api.get_invoice(&std::env::var("CRYPTANIO_RESOURCE_ID")?)?;
    let mut payment = serde_json::Map::new();
    for field in ["chain", "asset", "address", "amount", "expires_at",
                  "payment_route", "payment_uri", "checkout_url"] {
        if let Some(value) = invoice.get(field) {
            payment.insert(field.to_owned(), value.clone());
        }
    }
    println!("{}", serde_json::Value::Object(payment));
    Ok(())
}

メソッドの呼び出し

Node.js と PHP は listEvents、Python と Rust は list_events、Go は ListEvents を使用します。各メソッドはリファレンスの一つのリクエストに対応します。フィルターはオブジェクト/マップで、Rust ではペアのリストです。Go のメソッドは常に context.Context を最初の引数に取ります。未知のフィルターは送信前に拒否されます。

Node.js / PHP メソッドHTTP
createWatchPOST /v1/watches
listWatchesGET /v1/watches
getWatchGET /v1/watches/{id}
deleteWatchDELETE /v1/watches/{id}
listEventsGET /v1/events
listPaymentsGET /v1/payments
createInvoicePOST /v1/invoices
listInvoicesGET /v1/invoices
getInvoiceGET /v1/invoices/{id}
cancelInvoicePOST /v1/invoices/{id}/cancel
createEndpointPOST /v1/endpoints
listEndpointsGET /v1/endpoints
deleteEndpointDELETE /v1/endpoints/{id}
streamEventsGET /v1/stream
getHealthGET /v1/health
listChainsGET /v1/chains

監視対象と Webhook の作成ではリクエスト本文を渡します。単一リソースの操作では文字列の ID を渡します。createInvoice(body, idempotencyKey) では、ASCII の英字、数字、ハイフン、アンダースコアからなる 16~80 文字のキーが必要です。再試行では同じキーと本文を再利用してください。SDK は新しいキーを生成せず、自動再試行も行いません。本文、エラー、権限は各メソッドのページを参照してください。

応答、エラー、ストリーミング

JSON 応答はフィールド名を保持し、ID、金額、カーソルは文字列のままです。ページ取得は各メソッドの説明に従い手動で行います。エラーは HTTP ステータス、code、message、Retry-After を示します。HTTP 応答がない場合のステータスは 0 です(Rust は None)。リダイレクトは追跡しません。通常の JSON 応答は 8 MiB までです。既定のタイムアウトは 30 秒で、最大 300 秒に設定できます。Python ではネットワーク操作に、他のクライアントではストリーミングを含むリクエスト全体に適用されます。タイムアウトは書き込みが実行されなかった証明にはなりません。

言語/エラーフィールド
Node.js / Python: ApiErrorstatus, code, message, retry_after
PHP: CryptanioErrorstatus, apiCode, getMessage(), retryAfter
Go: *APIErrorStatus, Code, Message, RetryAfter
Rust: ApiErrorstatus: Option<u16>, code, message, retry_after

streamEvents は、再接続やイベント解析を行わずに SSE の未処理バイト列を提供します。Node.js の ReadableStream、閉じることのできる Python HTTP 応答、Go の io.ReadCloser、Rust の blocking::Response です。不要になったストリームは解放してください。PHP はデータ片をコールバックに渡し、false を返すと停止します。ストリーミングは Webhook の代わりにはならず、履歴の再送も保証しません。SSE のルールを参照してください。

最初の監視対象

Account で有効な Monitoring サービスを持つプロジェクトと、watches・events 権限を持つキーを作成します。必要な場合はアカウント認証を完了してください。設定からプロジェクト ID をコピーし、実際に監視したいアドレスだけを追加します。

サーバーの環境変数に CRYPTANIO_API_KEY と CRYPTANIO_PROJECT_ID を設定してください。例のアドレスを自分のアドレスに置き換えます。このリクエストは実際の監視対象を追加し、取引をシミュレーションしません。

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

成功応答には id が含まれます。保存してください。GET /v1/watches/{id} は支払いではなく監視対象と設定を返します。検出した活動を確認するには、GET /v1/events を watch_id で絞り込んで取得してください。取引が検出される前に一覧が空なのは正常です。応答、エラー、他の言語の例。

Payments の請求書

プロジェクトで Payments を有効にし、Account で対応アドレスをプールに追加してください。既定のプロジェクト選択に頼らず、project を明示的に送信してください。amount は暗号資産単位の文字列で、invoice_currency/invoice_amount は注文の見積りを別途表します。

CRYPTANIO_PROJECT_ID に Payments プロジェクト、CRYPTANIO_API_KEY に請求書の権限を持つキーを設定してください。CRYPTANIO_OPERATION_ID は新しい注文ごとに一意でなければなりません。同じ操作の再試行では再利用してください。請求書は実データに作成されます。

Shell / cURL
#!/usr/bin/env bash
set -euo pipefail
: "${CRYPTANIO_API_KEY:?Set CRYPTANIO_API_KEY}"
: "${CRYPTANIO_OPERATION_ID:?Set CRYPTANIO_OPERATION_ID}"
: "${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' \
  --header "Idempotency-Key: $CRYPTANIO_OPERATION_ID" \
  --data-binary '{"project":'"$(json_string "$CRYPTANIO_PROJECT_ID")"',"invoice_currency":"USD","invoice_amount":"12.50","reference":"order-42"}' \
  "https://api.cryptanio.com/v1/invoices" \
  --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

キーは invoices と Payments を許可する必要があります。Monitoring の例のキーは別のサービスに制限されている場合があります。Idempotency-Key は 16-80 文字の ASCII 英字、数字、-、_ で構成されます。同じキーで同じ正規化済みリクエストを繰り返すと、201 と既存の請求書を返します。内容を変更すると 409 conflict を返します。操作キーはアカウント全体で共通です。reference はその代わりになりません。

購入者に、返されたネットワーク、資産、アドレス、amount、有効期限を表示します。payment_routeがある場合は、そのkindと正確な文字列valueも渡してください。destination_tag、memo、comment、referenceは、このインボイスに支払いを対応付けるために必須です。注文のreferenceフィールドは別のものです。

返されたpayment_uriがある場合は、支払いQRにそのまま使用してください。Solana Pay referenceはウォレットのmemoではありません。URIを単なるアドレスに置き換えたり、再構築したりしないでください。ウォレットで必須の識別子を送れない場合は、支払者にcheckout_urlまたは対応ウォレットを案内してください。

checkout_urlは新規インボイスのホスト型支払いページです。返された正確なURLだけを支払者に共有し、IDから組み立てないでください。リンクでは支払いの詳細と状態を閲覧できるため、公開ログには記録しないでください。フィールドがなければ完全な支払い案内を表示します。ブラウザーのリダイレクトは支払いの証明になりません。APIまたは検証済みwebhookを確認してください。

注文を区別するため、askedがamountと異なる場合があります。amount_rawを任意精度の整数として照合してください。既定のTTLは60分、最大は10080分です。インボイス一覧はbeforeを受け取りますがnext_beforeは返しません。最後の項目のIDで続きを取得し、空のページで終了します。

Customer

フィールド型必須説明
idstringはいお客様のシステム内の顧客識別子。
maxLength: 120
Product

フィールド型必須説明
idstringいいえ自分のシステム内の製品識別子。
maxLength: 120
namestringいいえ製品名。
maxLength: 200
quantityintegerいいえ数量。
minimum: 1、maximum: 1000000
Payer

フィールド型必須説明
commentstringはい支払者のコメント。
maxLength: 500
InvoiceMetadata

最大 20 組、JSON は最大 8192 バイト。シークレットを含めないでください。

object 最大 20 組、JSON は最大 8192 バイト。シークレットを含めないでください。

Monitoring の監視

監視対象は単一の Monitoring プロジェクトに属します。同じアドレスを複数のプロジェクトで、それぞれ独立した方向・資産ルールとともに使用できます。アドレス帳リストと Address Sources は Account で接続してください。この REST API はそれらの管理コマンドを公開していません。

一覧は ID の降順です。next_before がある場合は、プロジェクトとフィルターを変更せず、次のリクエストで before として渡してください。limit の既定値は 50、上限は 200 です。ID は文字列で保存してください。削除した監視対象は有効な一覧から除外されます。この削除では、他のプロジェクトやアドレス帳からアドレスを削除しません。

イベントと履歴

/v1/events は各サービスでキーがアクセスできるイベントを返し、/v1/payments は Payments に限定されます。project、address、chain、type、watch_id、tx_id で絞り込めます。before は ID カーソルであり、日付ではありません。from/to フィルターはありません。next_before で次のページを取得できます。

検出したイベントの履歴は最大 30 日間参照できます。配信されたすべてのメッセージの保管庫ではなく、notice や webhook.test の復元は保証されません。REST Event は Webhook とは別のスキーマを持ち、v1 内でフィールドが追加される場合があります。

Event

フィールド型必須説明
event_idstringはい内部構造を持たない識別子。文字列のまま保持してください。
minLength: 1
event_typestringはいイベントの種別。新しい種別が追加される場合があります。
chainstringはいネットワークコード。
servicestringいいえ判明している場合のサービス。
watch_idstringいいえ監視対象に紐付いている場合のプロジェクト監視 ID。
minLength: 1
occurred_atstringはいRFC 3339 形式の UTC 日時。
date-time
paymentobject | nullはい支払いデータ。支払い以外のイベントでは null。GET /events は contract/notice ペイロードを返しません。
sandboxbooleanいいえテストイベント。省略時は false。
EventPayment

REST/SSE の支払いデータ。フィールドはイベントとネットワークにより異なり、正規化された Webhook v1 の形式とは異なります。

フィールド型必須説明
tx_idstringいいえ取引の識別子。
indexintegerいいえ取引内の送金インデックス。
minimum: 0
heightintegerいいえ分かる場合のブロック高。
minimum: 0
addressstringいいえ監視対象のアドレス。
assetstringいいえREST/SSE の資産:文字列の識別子です。Webhook の asset オブジェクトではありません。
amount_rawstringいいえ最小単位の整数金額を表す文字列。
pattern: ^[0-9]+$
amountstringいいえ正確な小数の金額を表す文字列。浮動小数点は使用しないでください。
pattern: ^[0-9]+(?:\.[0-9]+)?$
decimalsintegerいいえ小数点以下の桁数。
minimum: 0
confirmationsintegerいいえ承認数。
minimum: 0
revisionintegerいいえ送金状態のリビジョン。
minimum: 0
directionstringいいえ監視対象のアドレスを基準とする方向。
in、out
simulatedbooleanいいえシミュレーションされたイベント。
latebooleanいいえ遅れて検出された送金。
block_hashstringいいえブロックハッシュ。
match_keystringいいえネットワークで使用される場合の照合識別子。
metaobjectいいえ
invoiceobjectいいえ
customerobjectいいえ
productobjectいいえ
payerobjectいいえ
metadataobjectいいえ

Webhook イベント

配信は少なくとも一度行われる方式で、同じイベントが複数回届く場合があります。署名を検証後、連携側で event_id により重複を排除してください。処理の記録と業務上の変更を同じデータベーストランザクションで保存します。tx_id/address/asset のキーは異なる遷移、方向、プロジェクトをまとめてしまうため、event_id の代わりにはなりません。

署名された本文から event_type と event_id を読み取ってください。X-Event-Type/X-Event-Id ヘッダーは HMAC に含まれないため、使用する場合は本文と照合してください。支払いの更新時は project_id、direction、payment.revision を考慮してください。配信順序を前提にせず、不明な種類は安全に無視しながら診断用に保存してください。

系統本文
payment.pending / confirmed / rolled_back入金
debit.pending / confirmed / rolled_back出金
contract.approval / owner_added / owner_removed / threshold_changed / permissions_changedcontract
asset.unexpectedcontract。資産は受け付け済みの支払いとして計上されません
account.notice / account.notification / treasury.alarm / subscription.noticenotice.subject, notice.text
webhook.test支払いを伴わない制御イベント

schema_version: v1 はイベントの種類に応じて payment、contract、notice を含みます。webhook.test にはありません。ID と金額は文字列です。amount_raw は最小単位、amount は小数表記です。ネットワークと資産は chains で確認してください。完全なオブジェクトスキーマは OpenAPI にあります。

ヘッダー意味
X-Timestamp署名時の Unix 秒
X-Signaturehex HMAC-SHA256(timestamp + '.' + raw body)
X-Event-Id / X-Event-Type署名対象の本文と比較してください。
X-Attempt1 から始まる試行番号

イベントを永続的に受け付けた後、2xx を返してください。各試行のタイムアウトは 10 秒です。ネットワーク障害、408、425、429、5xx は最長 24 時間再試行し、待機時間は 2 秒から 15 分でランダムな変動を加えます。Retry-After に従います。リダイレクトは追跡しません。その他の 3xx/4xx は配信を終了し、410 は送信先と未配信キューを廃止します。

Webhook の形式例(説明用)
{
  "schema_version": "v1",
  "event_id": "2300",
  "event_type": "payment.confirmed",
  "occurred_at": "2026-10-06T10:00:00Z",
  "project_id": "1002",
  "service": "monitoring",
  "mode": "test",
  "sandbox": true,
  "payment": {
    "chain": "ethereum",
    "direction": "in",
    "asset": {
      "symbol": "ETH"
    },
    "address": "0x52908400098527886E0F7030069857D2E4169EE7",
    "tx_id": "simulated_2300",
    "index": 0,
    "amount": "1.000000000000000000",
    "amount_raw": "1000000000000000000",
    "decimals": 18,
    "confirmations": 0,
    "revision": 1,
    "simulated": true
  }
}
Webhook

公開署名付き Webhook v1 の本文。payment.* と debit.* は payment、contract.* と asset.unexpected は contract、account.notice、account.notification、treasury.alarm、subscription.notice は notice を含みます。webhook.test には業務ペイロードがありません。配信再試行の重複は event_id で排除してください。

フィールド型必須説明
schema_versionstringはいWebhook ペイロードのバージョン。
v1
event_idstringはいイベント ID:配信の再試行時も変わりません。異なる状態には異なる event_id が付く場合があります。
minLength: 1
event_typestringはい署名された本文内の種類。署名検証後に使用してください。新しい種類が追加される場合があります。
occurred_atstringはいRFC 3339 形式の UTC 日時。
date-time
project_idstringはい内部構造を持たない識別子。文字列のまま保持してください。
minLength: 1
servicestringいいえ該当する場合のプロジェクトのサービス。
modestringはいイベントのモード。
live、test
sandboxbooleanはい明示的なシミュレーションフラグ。
paymentobjectいいえ
contractobjectいいえ
invoiceobjectいいえ
customerobjectいいえ
productobjectいいえ
payerobjectいいえ
metadataobjectいいえ
noticeobjectいいえ
WebhookPayment

フィールド型必須説明
chainstringはいネットワークコード。
directionstringはい入金:in、出金:out。
in、out
assetobjectはい
addressstringはい監視対象のアドレス。
tx_idstringはい取引 ID。
indexintegerはい送金インデックス。どのネットワークでも 0 を前提にしないでください。
minimum: 0
heightintegerいいえ判明している場合のブロック高。
minimum: 0
block_hashstringいいえ判明している場合のブロックハッシュ。
match_keystringいいえ該当する場合のネットワーク照合識別子。
amountstringはい正確な小数の金額を表す文字列。浮動小数点は使用しないでください。
pattern: ^[0-9]+(?:\.[0-9]+)?$
amount_rawstringはい最小単位の整数金額を表す文字列。
pattern: ^[0-9]+$
decimalsintegerはい小数点以下の桁数。
minimum: 0
confirmationsintegerはい承認数。
minimum: 0
revisionintegerはい送金状態のリビジョン。取引の識別情報で異なる event_id を統合しないでください。
minimum: 0
latebooleanいいえ遅れて検出された送金で、請求書の状態 late とは異なります。
simulatedbooleanいいえシミュレーションされた送金。
valuationobjectいいえ
WebhookAsset

フィールド型必須説明
symbolstringいいえ判明している場合のシンボル。シンボルだけではトークンを特定できません。
standardstringいいえ判明している場合のトークン規格。
contractstringいいえ該当する場合の、そのネットワーク上のトークンコントラクト。
identifierstringいいえその他のネットワーク固有のトークン識別子。
WebhookContract

フィールド型必須説明
chainstringはいネットワークコード。
addressstringはい監視対象のアドレスまたはコントラクト。
tx_idstringはい取引 ID。
indexintegerはいイベントのインデックス。
minimum: 0
heightintegerいいえブロック高。
minimum: 0
block_hashstringいいえブロックハッシュ。
kindstringいいえ変更の種類。
assetstringいいえ判明している場合の対象資産識別子です。
detailobjectいいえ
simulatedbooleanいいえシミュレーションされたイベント。
WebhookInvoice

フィールド型必須説明
idstringはい内部構造を持たない識別子。文字列のまま保持してください。
minLength: 1
referencestringいいえ注文参照番号。
statusstringいいえpending は支払い待ち、seen は検出済み、partial は一部支払い済み、paid は支払い完了、underpaid/overpaid/late は判断が必要、expired は期限切れ、canceled はキャンセル済みです。
pending、seen、paid、underpaid、partial、overpaid、expired、late、canceled
currencystringいいえ注文の見積もり通貨。
amountstringいいえ正確な小数の金額を表す文字列。浮動小数点は使用しないでください。
pattern: ^[0-9]+(?:\.[0-9]+)?$
Notice

フィールド型必須説明
subjectstringはい通知の件名。
textstringはい通知の本文。
Valuation

フィールド型必須説明
currencystringはい評価額の通貨。例:USD。
amountstringはい正確な小数の金額を表す文字列。浮動小数点は使用しないでください。
pattern: ^[0-9]+(?:\.[0-9]+)?$
ratestringはい小数形式の文字列で表した資産の為替レート。
pattern: ^[0-9]+(?:\.[0-9]+)?$
rate_atstringはいRFC 3339 形式の UTC 日時。
date-time
providerstringいいえ判明している場合の価格情報の提供元名。

署名の検証

JSON を解析する前に、空白や改行を含む元の本文バイト列に対して HMAC を検証してください。時刻の新しさの確認はリプレイを抑えますが、永続的な event_id による重複排除の代わりにはなりません。例では 64 文字の 16 進署名と、サーバー時刻から 300 秒以内のタイムスタンプだけを受け入れます。対象の Webhook 送信先のシークレットを使用してください。

Node.js
import { createHmac, timingSafeEqual } from "node:crypto";
import { TextDecoder } from "node:util";

// rawBody is the original HTTP request Buffer, before JSON.parse or serialization.
export function verifyWebhook(secret, timestamp, rawBody, signature, nowSeconds = Math.floor(Date.now() / 1000)) {
  if (typeof secret !== "string" || secret.length === 0 || !Buffer.isBuffer(rawBody) || rawBody.length === 0 ||
      typeof timestamp !== "string" || !/^(0|[1-9][0-9]*)$/.test(timestamp) ||
      typeof signature !== "string" || !/^[0-9a-f]{64}$/i.test(signature) ||
      !Number.isSafeInteger(nowSeconds) || nowSeconds < 0) return false;

  const signedAt = Number(timestamp);
  if (!Number.isSafeInteger(signedAt) || Math.abs(nowSeconds - signedAt) > 300) return false;

  const expected = createHmac("sha256", secret).update(timestamp).update(".").update(rawBody).digest();
  return timingSafeEqual(expected, Buffer.from(signature, "hex"));
}

// headers is Node.js request.headers (lowercase names). Optional X-Event-Id/Type
// headers are not signed separately; compare them with the verified body.
export function readSignedWebhook(secret, timestamp, rawBody, signature, headers = {}, nowSeconds) {
  if (!verifyWebhook(secret, timestamp, rawBody, signature, nowSeconds) ||
      headers === null || typeof headers !== "object" || Array.isArray(headers)) return null;

  let event;
  try {
    event = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(rawBody));
  } catch {
    return null;
  }
  if (event === null || typeof event !== "object" || Array.isArray(event) || event.schema_version !== "v1" ||
      typeof event.event_id !== "string" || event.event_id.length === 0 ||
      typeof event.event_type !== "string" || event.event_type.length === 0) return null;

  for (const [header, field] of [["x-event-id", "event_id"], ["x-event-type", "event_type"]]) {
    if (headers[header] !== undefined && headers[header] !== event[field]) return null;
  }
  return event;
}

Node.js の例をダウンロード

Go
package webhook

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"strconv"
	"time"
	"unicode/utf8"
)

// VerifyWebhook checks the original HTTP body bytes before parsing JSON.
// Optional nowSeconds is used only for deterministic tests.
func VerifyWebhook(secret, timestamp string, rawBody []byte, signature string, nowSeconds ...int64) bool {
	if secret == "" || len(rawBody) == 0 || len(signature) != 64 || len(nowSeconds) > 1 {
		return false
	}
	signedAt, err := strconv.ParseInt(timestamp, 10, 64)
	if err != nil || signedAt < 0 || strconv.FormatInt(signedAt, 10) != timestamp {
		return false
	}
	now := time.Now().Unix()
	if len(nowSeconds) == 1 {
		now = nowSeconds[0]
	}
	if now < 0 || now-signedAt < -300 || now-signedAt > 300 {
		return false
	}
	provided, err := hex.DecodeString(signature)
	if err != nil || len(provided) != sha256.Size {
		return false
	}
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(timestamp))
	mac.Write([]byte("."))
	mac.Write(rawBody)
	return hmac.Equal(mac.Sum(nil), provided)
}

// WebhookEvent contains only routing fields. Parse other fields from rawBody
// after ReadSignedWebhook succeeds; unknown fields are allowed.
type WebhookEvent struct {
	SchemaVersion string `json:"schema_version"`
	EventID       string `json:"event_id"`
	EventType     string `json:"event_type"`
}

// ReadSignedWebhook extracts event_id/type only from the verified body.
// X-Event-Id/Type are not signed separately; nonempty values must match the body.
func ReadSignedWebhook(secret, timestamp string, rawBody []byte, signature, eventIDHeader, eventTypeHeader string,
	nowSeconds ...int64) (*WebhookEvent, error) {
	if !VerifyWebhook(secret, timestamp, rawBody, signature, nowSeconds...) {
		return nil, errors.New("invalid webhook signature or timestamp")
	}
	var event WebhookEvent
	if !utf8.Valid(rawBody) || json.Unmarshal(rawBody, &event) != nil || event.SchemaVersion != "v1" ||
		event.EventID == "" || event.EventType == "" {
		return nil, errors.New("invalid webhook body")
	}
	if eventIDHeader != "" && eventIDHeader != event.EventID || eventTypeHeader != "" && eventTypeHeader != event.EventType {
		return nil, errors.New("webhook headers do not match the signed body")
	}
	return &event, nil
}

Go の例をダウンロード

Webhook エンドポイント

特定のプロジェクトにポート 443 の公開 HTTPS URL を追加します。URL 内の認証情報、フラグメント、リダイレクト、非公開の宛先は許可されません。アカウントあたり最大 20 件のエンドポイントを登録できます。各エンドポイントのシークレットは初回作成時のみ返されるため、サーバーに保存してください。

同じプロジェクトとモードで同じ URL を再作成すると、200 と、シークレットを含まない既存のエンドポイントを返します。新規エンドポイントは 201 を返します。DELETE は安全な再実行も含め、200 と id、deleted: true を返します。キーで参照できるのはそのモードと許可されたプロジェクトのみで、配信はプロジェクト設定に従います。

SSE ストリーム

SSE はサーバー側の連携とリアルタイム表示用です。配信を保証せず、取り逃したイベントを再送することもありません。Bearer ヘッダーを持つサーバー側 HTTP クライアントを使用してください。標準のブラウザー EventSource はこのヘッダーを送信できません。API キーをブラウザーのコードやクエリ文字列に含めないでください。

メッセージは event: payment と独自の StreamEvent 形式を使い、webhook v1 や REST Event とは異なります。コメントはコロンで始まり、ハートビートは約 20 秒ごとに届きます。retry: 5000 は再接続のヒントです。切断後は events から利用可能なブロックチェーンイベント履歴を取得してください。

StreamEvent

SSE data の JSON で、webhook v1 とは異なります。支払い以外のイベントは payment を省略し、contract を含む場合があります。

フィールド型必須説明
event_idstringはい内部構造を持たない識別子。文字列のまま保持してください。
minLength: 1
event_typestringはいイベントの種別。新しい種別が追加される場合があります。
chainstringはいネットワークコード。
servicestringいいえ判明している場合のサービス。
watch_idstringいいえ監視対象に紐付いている場合のプロジェクト監視 ID。
minLength: 1
occurred_atstringはいRFC 3339 形式の UTC 日時。
date-time
paymentobject | nullいいえ支払いデータ。支払い以外のイベントでは null。GET /events は contract/notice ペイロードを返しません。
sandboxbooleanいいえテストイベント。省略時は false。
project_idstringいいえ内部構造を持たない識別子。文字列のまま保持してください。
minLength: 1
project_namestringいいえプロジェクト名。
urlstringいいえAccount のイベントへのリンク。
uri
contractobjectいいえ
modestringいいえlive または test。
live、test

支払いと請求書の状態

ブロックチェーン上の支払い状態と注文状態は別です。payment.pending は十分な承認前の検出、payment.confirmed はネットワーク/プロジェクトの承認条件の達成、payment.rolled_back は巻き戻しを示します。pending、出金、シミュレーションのイベントを根拠に注文を履行しないでください。

Invoice意味
pending支払い待ち
partial一部を受領済み。プロジェクトの部分払い方針に従います
paid支払い受付済み
underpaid不足払いには判断が必要です
overpaid過払いには適用される方針に基づく判断が必要です
late期限後の支払いには判断が必要です
expired支払期限切れ
canceled請求書をキャンセルしました。記録は引き続き参照できます。

needs_decision は underpaid、overpaid、late の場合に存在します。これらの状態は Account で解決してください。チェーンの再編と再取り込みにより、新しい遷移と新しい payment.revision が発生する場合があります。confirmed は将来の変更がないという無条件の保証ではありません。

エラーと安全な再試行

application/json
{"error":{"code":"forbidden","message":"this API key is read-only"}}

ロジックには HTTP ステータスと error.code、診断には message を使用してください。成功した一覧応答には data があり、単一のオブジェクトは直接返されます。Health は 503 の場合も含め、独自の status/version スキーマを使用します。message の厳密な文言に依存しないでください。

HTTP操作
400JSON、形式、パラメーターを修正してください。変更せずに再試行しないでください。
401キー、有効期限、一時停止、失効を確認してください。
403スコープ、読み取り/書き込み、プロジェクト、サービス、IP、アカウント認証を確認してください。
404ID、キーのモード、アクセス権を確認してください。制限によってリソースが非表示になる場合があります。
402Monitoring の監視数上限です。プランを確認してください。
409競合、無効なサービス、使用中のプール、または制限。コードを確認してください。
429Retry-After に従い、アカウント全体のリクエスト頻度を下げてください
500 / 503上限を設けたバックオフで再試行してください。請求書作成では元の Idempotency-Key を必ず使用します

タイムアウトは操作が実行されなかったことを意味しません。再試行で請求書の操作キーを変更しないでください。重複防止のないメソッドは先に状態を確認し、すべての POST が冪等だと仮定しないでください。

ネットワークと制限

選択した API ホストの chains を使用して、その環境のネットワーク、資産、機能、確認回数のカタログを取得してください。一般カタログへの掲載は、その環境でのネットワークの有効化や、すべての操作への対応を保証しません。サービスの利用枠と予算は Account、価格は料金ページで確認してください。

アカウントの認証済み REST リクエストの上限は、有料サービスなしで毎秒 10 件、有料サービスありで毎秒 50 件です。短時間のバースト容量は 20/100 件です。アカウントのすべてのキーとモードでこの上限を共有します。超過時は Retry-After とともに 429 を返します。サービスの利用枠と API のレート制限は別の制限です。

サービスの料金と利用枠

API バージョン

このリファレンスの対象は v1(リリース 1.0.0 62)です。更新日:2026-10-10。新しい機能を使う前に、GET /v1/health でデプロイ済みリリースを確認してください。ドキュメントのバージョンだけでは、デプロイ済みであることは確認できません。

公開 API契約
https://api.cryptanio.com/v1

安定した連携には /v1 を使用してください。バージョンのないパスは、その環境の現在の安定契約を選択します。不明な /vN は 404 を返します。X-API-Version は契約を識別し、X-Server-Version と health.version は製品リリースを識別します。別の API 契約を意味するものではありません。

OpenAPI 3.1 をダウンロード

API の変更

リリース 1.0.0 62 には Node.js、Python、PHP、Go、Rust のダウンロード可能な SDK と、AI エージェント向けローカル MCP が含まれています。リファレンス、Markdown、直接の HTTP リクエスト例は別途利用できます。公開サンドボックスは提供していません。API の動作は変わりません。

v1 では、クライアントは追加の応答フィールドを許容する必要があります。不明な種類のイベントを受け入れても、注文の履行や支払いの計上を意味するわけではありません。変更を利用する前に、選択した環境のバージョンで利用可能か確認してください。