開発者向け

公開API Beta

安全なスコープ付きAPIキーと、安定したバージョン管理のJSON仕様で、ワークスペースの連携を構築できます。

インタラクティブなAPIリファレンスを開く

クイックスタート

  1. 01

    APIキーを開く

    設定 を開いて 開発者 を選択し、APIキー を探して キーを作成 を選択します。キーを作成できるのはオーナーと管理者です。

  2. 02

    APIキーを作成する

    名前 を入力し、有効期限(日数) を選び、チャネルへのアクセス を すべてのチャネル または 選択したチャネル から選んで、スコープ で連携に必要な最小限のスコープを選びます。リクエストは、エンドポイントが必要とするリソースの操作権限がキーに正確にある場合にのみ成功します。キーを作成 を選択します。

  3. 03

    APIキーを保存する

    キー全体は一度だけ表示されます。シークレットマネージャーにコピーしてから、保存しました を選択します。

  4. 04

    キーを送信する

    Bearerトークンを使うか、同じ値を x-api-key で送信します。キーをクエリ文字列やブラウザのコードに含めないでください。

cURL

curl https://www.usesonny.com/api/v1/contacts?limit=25 \
  --header "Authorization: Bearer sonny_your_key"

キーは安全に保たれます

キーのセキュリティ
キーには sonny_ の接頭辞と 64 文字のランダムな文字列が使われ、保存時は一方向ハッシュ化され、有効期限を設定でき、キーごとに毎分 600 リクエストの上限があります。キーは1つのワークスペースに紐づきます。
キーを取り消すには、横にあるゴミ箱ボタンを選択します。APIキーを取り消しますか? で 削除 を選択して確定します。キーはすぐに使えなくなります。
呼び出しのたびに認可
Sonnyはハッシュとスコープを確認したうえで、作成者のワークスペースのアクティブなメンバーシップ、ロール、請求状況を再確認します。そのユーザーを削除または無効化すると、そのユーザーのキーはすぐに無効になります。
選択したチャネルは、すべてのREST APIとMCPの呼び出しで適用されます。連絡先、プロパティ、タグ、Webhook管理のエンドポイントには、すべてのチャネルへのアクセスが必要です。フォームからの作成では、選択したチャネルで contacts:write と conversations:write を使えます。単独の連絡先エンドポイントは、引き続きワークスペース全体が対象です。

スコープ

  • contacts:read
  • contacts:write
  • tags:read
  • tags:write
  • conversations:read
  • conversations:write
  • messages:read
  • messages:write
  • messages:send
  • webhooks:read
  • webhooks:write
  • kb:read
  • kb:write
  • csat:read
  • attachments:write
  • members:read
  • contact-memory:read
  • contact-memory:write
  • reporting:read

リソース

連絡先
連絡先、型付きプロパティ、完全一致の絞り込み、顧客メモリーを管理します。データ保護の依頼に応じて、連絡先をアーカイブしたり、すべての会話とともに完全に消去したりできます。
ソース
設定済みのソースと、それぞれがチャット、メール、またはその両方に対応しているかを確認します。
会話
フォームから問い合わせを作成し、対応が必要なものを絞り込み、エージェントやチームに割り当て、スヌーズ、タグ付け、一括更新を行います。
同期
保存したカーソルを使って、ワークスペースの永続的な変更と削除の記録を再取得します。
メンバーとチーム
割り当て可能なメンバー、対応状況、実際のチャネルへのアクセスを確認します。
レポート
サポート、チーム、AI、ナレッジ、リード、稼働状況のレポートを読み取ります。
メッセージ
メッセージ履歴と添付ファイルの抽出内容を読み取り、非公開のファイルをアップロードし、社内メモを追加し、顧客への返信を送信・編集します。
Webhook
エンドポイント、購読、テスト、配信、再試行を管理します。
ナレッジベース
ソースごとにヘルプセンターの記事とカテゴリーを作成、読み取り、更新、削除します。
顧客満足度
ワークスペース全体、チャネルごと、会話ごとのCSATスコアを読み取り、評価の値、コメント、担当者、期間で絞り込んだ個々の評価を一覧表示します。

AIツールからSonnyを使う

Sonny MCPは、公開APIのすべての操作をツールとして公開しています。クライアントはOAuth 2.1でのログイン、またはスコープ付きAPIキーで接続し、すべての呼び出しで同じスコープ、ワークスペースの境界、ビジネスルールが維持されます。

Sonny MCPガイドを読む

レスポンスとエラー

コレクションのレスポンスは data を使い、該当する場合はページ情報を含みます。すべてのレスポンスに x-request-id が含まれます。安全なリクエストIDを指定すると、Sonnyはそれをそのまま返します。エラーでは、機密性の高い実装の詳細を明かさない安全なメッセージが返されます。

{
  "error": {
    "type": "validation_error",
    "message": "Invalid email address",
    "requestId": "req_01J..."
  }
}
400
入力、JSON、クエリ、またはカーソルが不正です。
401
APIキーがない、無効、期限切れ、またはスコープがありません。
402
ワークスペースの請求状況により、このリクエストはブロックされています。
403
キー作成者のワークスペースでのロールでは許可されていません。
404
リソースがキーのワークスペースに存在しません。
409
リクエストが既存のリソースと競合しています。
410
同期カーソルの期限が切れています。現在の状態を初期化し、新しいカーソルから再取得してください。
413
アップロードが許可されたサイズを超えています。
422
ソースにメールチャネルがないか、送信されたフィールドの値が不正です。
429
キーごとのレート制限を超えました。
500
予期しないエラーが発生しました。リクエストIDを添えて再試行してください。
503
Webhookの配信待ちが上限に達しています。しばらくしてから再試行してください。

レート制限

各APIキーは、1分あたり最大600リクエストを送信できます。すべてのレスポンスで、標準の RateLimit-Limit、RateLimit-Remaining、RateLimit-Reset ヘッダーにより現在の時間枠が報告されるため、クライアントは推測せずに自分でペースを調整できます。上限を超えると、APIは Retry-After ヘッダー付きで 429 を返します。その秒数だけ待ってから再試行してください。

バージョン管理と廃止

APIのバージョンはURLのパス(/api/v1)で管理しています。同じバージョン内では、新しいエンドポイント、新しい任意のフィールド、新しい列挙値など、追加の変更のみを行います。互換性を壊す変更は新しいバージョンとしてリリースし、v1のエンドポイントを廃止する前には、少なくとも6か月前に告知します。告知は、このページ、有効なAPIキーを持つワークスペースのオーナーへのメール、影響を受けるエンドポイントの Deprecation ヘッダーと Sunset ヘッダーで行います。

送信済みの返信を編集する

  1. APIキーまたはMCP接続に、messages:read と messages:send のスコープと、返信のチャネルへのアクセスを付与します。
  2. 会話のメッセージを読み取り、自分が送った担当者の返信のIDをコピーします。APIキーは作成者として、OAuthは接続したメンバーとして動作します。
  3. 以下のリクエストで差し替えのテキストを送るか、MCPで conversationId、messageId、body を指定して edit_message を呼び出します。
  4. 返されたメッセージを確認します。ID、添付ファイル、既読表示、元の送信時刻は変わりません。
curl --request PATCH \
  https://www.usesonny.com/api/v1/conversations/conversation_1/messages/message_1 \
  --header "Authorization: Bearer sonny_your_key" \
  --header "Content-Type: application/json" \
  --data '{"body":"The corrected reply"}'

編集すると、会話記録と接続中のチャットクライアントの表示が修正されます。メールや通知が再送されることはなく、すでに配信されたメールは変わりません。編集できるのは、自分が送った担当者としての顧客への返信だけです。受信メッセージ、ボットの返信、社内メモ、ほかのメンバーの返信は編集できません。メールの配信が保留中の場合は、完了してから編集してください。差し替えのテキストは1〜50,000文字で、以前のHTMLとリンクのプレビューはクリアされます。連携サービスには message.updated のWebhookと同期イベントが届きます。新しいメッセージIDだけをポーリングしても編集は見つからないため、永続的な同期フィードを使ってください。

フォームから会話を作成する

フォームの送信内容を POST /api/v1/conversations に送ります。Sonnyはメールアドレスで連絡先を検索または作成し、回答を保存して、選んだソースのメールチャネルで受信の会話を開きます。チャネルのチーム、割り当てルール、通知が適用されます。エージェントはメールで返信します。

  1. conversations:write と contacts:write を持つキーを作成します。クライアントの選択したチャネルに限定することもできます。ソースIDは GET /api/v1/sources で確認できます。これには conversations:read も必要です。
  2. n8nで HTTP Request ノードを追加します。メソッドは POST、URLは https://www.usesonny.com/api/v1/conversations です。キーはHeader Authの認証情報に、Authorization と値 Bearer sonny_your_key として保存します。
  3. Send Body を有効にし、JSON と Using JSON を選んでから、JSONフィールド全体を Expression に切り替えて、この例を貼り付けます。ソースIDを置き換え、入力フィールドをフォームに対応させます。再試行で同じ値が使われるよう、フォームの固定で一意な送信IDを使ってください。
{{ {
  sourceId: "YOUR_CLIENT_SOURCE_ID",
  contact: { email: $json.email, name: $json.name },
  subject: "Website enquiry",
  message: $json.message,
  fields: {
    Company: String($json.company ?? ""),
    Budget: String($json.budget ?? ""),
    Service: String($json.service ?? "")
  },
  externalId: "website-form-" + $json.submissionId
} }}

ノードのその他のオプションは、n8nのHTTP Requestガイドをご覧ください。同等のMCPツールは create_conversation で、ペイロードと権限は同じです。

新しいフィールド名はテキストのプロパティになります。既存の数値、URL、日付、選択肢のフィールドには、有効な文字列の値を渡す必要があります。不正な値の場合は、フィールド名を示した 422 が返され、何も保存されません。日付にはISO形式の日付またはタイムスタンプを使え、選択肢の値は選択肢のいずれかと一致する必要があります。フィールドは最大50個、名前は100文字まで、値は5,000文字まで受け付けます。プロパティは、連絡先と会話のサイドバーに表示されます。任意の htmlMessage を指定した場合も含め、どちらのメッセージ本文にも回答のコピーが残ります。

任意の tags には、既存のワークスペースのタグIDを最大20個指定できます。レスポンスには conversation、contact の概要、message、deduplicated が含まれます。新しい送信には 201 が返されます。同じソースで externalId を再利用すると、元のIDと deduplicated: true 付きで 200 が返され、変更された内容は無視されます。外部IDがない場合は、呼び出すたびに新しい会話が作成されます。作成時の添付ファイルとAIの自動応答には対応していません。

エージェントのワークフロー

振り分け、対応、そして常に同期

RESTとMCPは同じ権限とワークフローを共有しています。認証情報で、現在のチャネルへのアクセスを広げることはできず、絞り込むことだけができます。メンバーシップからチャネルを外すと、連携からもそのチャネルが外れます。

対応が必要な会話を見つける

awaitingReply、unread、unassigned、assigneeId、agentGroupId、snoozed、priority、tagIds で絞り込みます。awaitingReply は社内メモを無視します。unread は認証されたメンバーごとの状態です。unassigned は、チームが割り当てられていても個人の担当者がいないことを意味します。タグは指定したいずれかのIDに一致します。

GET /api/v1/conversations?status=open&awaitingReply=true&compact=true&sort=waitingSince&direction=asc

waitingSince、lastMessageAt、createdAt、またはビジネス上の優先度で、direction に asc または desc を指定して並べ替えます。同順の場合はIDで決まります。絞り込みを省略すると、compact=false と snoozed=any が維持されます。RESTの tagIds はカンマ区切りのIDを受け付け、MCPでは配列も使えます。waitingSince は、最後の返信の後の最初の受信メッセージから始まり、追加のメッセージや社内メモではリセットされません。古いスレッドが再び浮上するよう、Webhookが届かないときでも、この待機キューのスキャンを定期的に実行してください。

受信トレイを読み直さずに追いつく

conversations:read を指定して GET /api/v1/sync を使います。永続フィードには、会話の変更、タグ、メッセージ、連絡先のプロパティ、メモリー、削除の記録が含まれます。各ペイロードにはそれぞれの読み取りスコープも必要です。メッセージ本文には messages:read が、メモリーには contact-memory:read が必要です。制限された認証情報では、許可されたチャネルの分だけが返されます。

  1. カーソルなしで開始し、hasMore が false になるまで nextCursor をたどって、そのカーソルを保存します。
  2. 初期状態に必要な、現在の会話/連絡先の一覧と履歴を読み取ります。
  3. 保存したカーソルから再取得して、読み取り中に起きた変更に追いつきます。各ページを処理してから、nextCursor を保存します。

イベントの id で重複を除外してください。再取得は少なくとも1回の配信を保証するため、後続の処理にも独自の重複対策が必要です。カーソルなしのリクエストは直近1時間分で、完全なスナップショットではありません。イベントは30日間保持されます。HTTP 410 resync_required が返されたら、再度初期化してください。スコープやチャネルへのアクセスを広げた後も初期化してください。limit は最大100、maxBodyChars は最大10,000(デフォルト500)です。compact=true を設定すると、body/bodyTruncated の代わりに、200文字までのメッセージの textPreview/textTruncated フィールドが返されます。Webhookでエージェントを起動できますが、フィードはWebhookを購読していない場合や、Webhookの配信が滞っている場合でも利用できます。

確認結果を一度記録して共有する

調査を繰り返す前に、list_conversation_checks(GET /api/v1/conversations/{conversationId}/checks)を読み取ってください。結果は record_conversation_check(同じパスへのPUT)で、key、result、checkedBy と、カードのIDやURLを示す任意の reference を指定して保存します。例:key=product-version、result=Shopstar Go verified、checkedBy=Engineer、reference=card-X。Sonnyは認証された actorId と checkedAt のタイムスタンプを記録します。同じキーを再利用すると、その確認だけが置き換わります。これは履歴ではなく現在の状態です。読み取りには conversations:read、書き込みには conversations:write が必要で、どちらも会話のチャネルに限定されます。これらの呼び出しで返信が送られたり、販売者が回答済みとして記録されたりすることはありません。

割り当てと一括更新

GET /api/v1/members and /teams(members:read)で、アクティブで割り当て可能なメンバーとチームを確認します。レスポンスには対応状況と実際のチャネルへのアクセスが含まれ、メールアドレスは含まれません。conversations:write を使って、status、priority、assigneeId、agentGroupId、snoozedUntil、snoozedUntilReply、addTagIds、removeTagIds を変更します。

POST /api/v1/conversations/batch
{
  "conversationIds": ["conversation_1", "conversation_2"],
  "updates": { "agentGroupId": "team_1", "assignment": "round_robin" }
}

ラウンドロビンでは、会話のチャネルにアクセスできる対応可能なチームメンバーが選ばれます。対象となるメンバーがいない場合、単一の更新では409が返され、一括処理ではその項目が失敗します。一括処理では最大100個の一意なIDを受け付け、会話ごとにひとつのパッチをアトミックに適用します。{ id, ok, error? } の結果をすべて確認してください。一部の項目が失敗する場合があります。一括処理には現在のリクエスト単位のレート制限が適用され、項目数による重み付けはありません。

Sonny AIと顧客情報を共有する

contact-memory:read/write で、連絡先のメモリーを一覧表示、保存、削除します。contactId と、アクセス可能な sourceId の両方を指定してください。連絡先には、そのソースでの会話が必要です。保存した事実には、アプリと同じ検証、重複の処理、上限が適用され、手動のメモリーとして記録されます。

プロパティの定義は /api/v1/properties で読み取り、値は /api/v1/contacts/{contactId}/properties で読み取り・設定します。MCPでは list_properties、get_contact_properties、set_contact_property を使えます。これらには contacts:read/write と、すべてのチャネルへのアクセスが必要です。propertyId または propertyName のどちらか一方を指定し、文字列の値、またはクリアする場合は null を指定します。テキスト、数値、URL、日付、選択肢の値は、フィールドの定義に照らして検証されます。

PUT /api/v1/contacts/contact_1/properties
{ "propertyName": "Plan", "value": "Pro" }

GET /api/v1/contacts?property[Plan]=Pro

プロパティの絞り込みは、保存された文字列と完全一致で照合します。複数のプロパティを指定した場合は、すべてに一致する必要があります。APIで書き込まれた値は、Co-Pilotと自動応答でAPIのデータとして表示されます。既存の認証済み顧客とソースのルールは引き続き適用されます。通常の手動入力による社内向けのフィールド値は、このAIの文脈から除外されたままです。

チームと同じレポートを読み取る

reporting:read を指定して GET /api/v1/reporting/{kind} を呼び出します。種類は overview、volume、response-times、agents、sources、tags、csat、ai、knowledge、leads、online-hours です。overview は件数、応答時間、CSATをまとめたものです。絞り込みには、period(1〜365日、デフォルト30)、組み合わせで指定する from/to の日付(to は含みません)、granularity(day/month)、source、assigneeId、tagId を使えます。source には all、all-chat、all-email、website:{id}、email:{id} を指定できます。

レポートには、ダッシュボードと同じクエリと現在のアクセス確認が使われます。knowledge は、選択したソース、担当者、タグとは関係なく、日付と許可されたチャネルを使います。online-hours は、アクセス可能なメンバーのワークスペースでのオンライン状況を測定し、会話数はチャネルに限定されたままです。既存の /csat エンドポイントは、独自の csat:read スコープを使い、対象となる母集団が異なる場合があります。

返信や社内メモでファイルを送る

attachments:write を付与し、会話用に最大25MBのファイルをアップロードします。POST /api/v1/attachments には、multipart の file フィールドと conversationId フィールドを指定します。 レスポンスには id と expiresAt が含まれます。1時間以内に、最大10個の attachmentIds を返信またはメモに渡します。各アップロードはあなたのユーザーと会話に紐づき、一度だけ使えます。使われなかったアップロードは、期限切れ後に削除されます。

POST /api/v1/conversations/conversation_1/reply
{ "attachmentIds": ["upload_1"] }

返信には messages:send が、社内メモには messages:write が必要で、社内メモが顧客に届くことはありません。添付ファイルだけのメッセージにも対応しています。メールの返信では、メールのサイズの範囲内でファイルを添付し、残りはダウンロードリンクにします。オフライン時のチャットのメールにはファイルのリンクが含まれます。メールで送られたリンクは添付ファイルが存在する限り使えるため、受信者は後から開けます。メールを転送すると、それらのファイルへのアクセスも共有されます。配信の失敗は emailDeliveryStatus で確認してください。

認可されたメッセージの読み取りには、downloadUrl、downloadExpiresAt、aiStatus、aiDescription、aiExtractedText に加え、リンクされた動画(Loom、Vimeoなど)の videoTranscripts が含まれます。ダウンロードリンクの有効期間は15分です。新しいリンクが必要な場合は、メッセージを読み直してください。API/MCPで新しくアップロードしたファイルは非公開のストレージに保存されます。以前の添付ファイルは公開のままで、access=legacy_public と示され、元のURLは期限切れになりません。ワークスペースでSonny AIが有効な場合、メッセージを読み取るとその画像の読み取りが始まります。画像の読み取りと動画の文字起こしは、メッセージの到着後まもなく完了します。処理中のものがある間、レスポンスは readsInProgress で始まり、その nextStep に次に行うべき呼び出しが正確に示されます。waitSeconds(最大30)を指定すると、1回のリクエストで完了を待てます。顧客向けのウィジェットとリアルタイムのメッセージには、抽出内容や文字起こしは含まれません。

リクエストとレスポンスの仕様をすべて見る

ナレッジベース

外部のソースから同期する

固定の外部IDを使って記事とカテゴリーを同期し、MarkdownやHTMLをインポートし、画像をアップロードし、並び順を設定し、読者のオーディエンスを管理できます。アップサートを繰り返すと、既存のコンテンツが更新されます。

  1. チャネルの sourceId を選び、kb:read と kb:write を付与します。APIキーはサーバーに保管し、チャネルへのアクセスを限定してください。
  2. カテゴリーを作成してから、記事を下書きとして同期します。公開する前に、書式とアクセスを確認してください。
  3. ヘルプセンターのアクセスを設定して公開し、読者の画面をテストします。以降の更新には、ページ送りと固定の外部IDを使ってください。
REST の同期手順をすべて見る

顧客オーディエンスを管理する

認証済みの顧客の属性からグループを作成し、ヘルプセンター、カテゴリー、記事に適用します。引き継いだすべての制限を満たす必要があります。APIとMCPの認証情報は、スコープの範囲内でスタッフとして動作します。読者のアクセスを確認するには、プレビューと実際の顧客セッションでテストしてください。

ヘルプセンターのオーディエンスを設定・テストする

関連ドキュメント