快速开始
大约 15 分钟,你就能在网站上放好聊天插件、完成第一次 API 调用,并收到第一个 Webhook。
1. 把插件放到网站上
在工作台打开 站点,添加你的网站并复制嵌入代码,粘贴到每个需要显示聊天窗的页面 </body> 之前:
html
<script src="https://cdn.sealreply.com/widget.js" data-site-key="sk_…" async></script>插件只在站点允许的域名上加载,而且要先验证第一个域名(DNS TXT 记录或验证文件)。详见 安装插件。
2. 创建 API Key
打开 开发者 → 创建 API Key,本指南勾选 conversations:read 和 messages:write 即可。复制 Key——它以 sr_live_ 开头,只显示这一次。请只放在你的服务器上:拿到 Key 的人可以在权限范围内代表整个工作区操作。
3. 第一次调用
先在网站上以访客身份发起一个聊天,这样就有一个待接入的会话。然后列出待接入的会话:
sh
curl https://api.sealreply.com/v1/conversations?status=waiting \
-H "Authorization: Bearer $SEALREPLY_API_KEY"所有响应都是同一种结构:
json
{ "success": true, "data": [{ "id": "0192…", "status": "waiting", "visitor": { "display_name": "Visitor #4821" } }], "error": null, "meta": { "has_more": false, "next_cursor": null } }接下来以“集成”身份回复最早的那个会话。完整程序如下,选你用的语言:
js
// Your first API calls in Node.js (18+): list waiting conversations and
// answer the oldest as your integration. Needs a key with conversations:read
// and messages:write.
const API = process.env.SEALREPLY_API_URL ?? "https://api.sealreply.com";
const KEY = process.env.SEALREPLY_API_KEY;
async function call(method, path, body) {
const res = await fetch(API + path, {
method,
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
body: body && JSON.stringify(body),
});
const json = await res.json();
if (!json.success) throw new Error(`${res.status} ${json.error.code}: ${json.error.message}`);
return json.data;
}
const waiting = await call("GET", "/v1/conversations?status=waiting");
console.log(`${waiting.length} waiting`);
const oldest = waiting.at(-1);
if (oldest) {
const message = await call("POST", `/v1/conversations/${oldest.id}/messages`, {
client_msg_id: crypto.randomUUID(), // makes retries safe
content_type: "text",
text: "Thanks for waiting! Someone will be with you in a minute.",
});
console.log(`replied to ${oldest.visitor.display_name}: ${message.id}`);
}py
"""Your first API calls in Python 3 (standard library only): list waiting
conversations and answer the oldest as your integration. Needs a key with
conversations:read and messages:write."""
import json
import os
import urllib.error
import urllib.request
import uuid
API = os.environ.get("SEALREPLY_API_URL", "https://api.sealreply.com")
KEY = os.environ["SEALREPLY_API_KEY"]
def call(method, path, body=None):
req = urllib.request.Request(
API + path,
method=method,
data=json.dumps(body).encode() if body is not None else None,
headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"},
)
try:
with urllib.request.urlopen(req) as res:
return json.load(res)["data"]
except urllib.error.HTTPError as e:
err = json.load(e)["error"]
raise SystemExit(f"{e.code} {err['code']}: {err['message']}")
waiting = call("GET", "/v1/conversations?status=waiting")
print(f"{len(waiting)} waiting")
if waiting:
oldest = waiting[-1]
message = call("POST", f"/v1/conversations/{oldest['id']}/messages", {
"client_msg_id": str(uuid.uuid4()), # makes retries safe
"content_type": "text",
"text": "Thanks for waiting! Someone will be with you in a minute.",
})
print(f"replied to {oldest['visitor']['display_name']}: {message['id']}")php
<?php
// Your first API calls in PHP 7.4+ (curl extension): list waiting
// conversations and answer the oldest as your integration. Needs a key with
// conversations:read and messages:write.
$api = getenv('SEALREPLY_API_URL') ?: 'https://api.sealreply.com';
$key = getenv('SEALREPLY_API_KEY');
function sealreply_call(string $method, string $path, ?array $body = null)
{
global $api, $key;
$ch = curl_init($api . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $key", 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => $body === null ? null : json_encode($body),
]);
$json = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$json['success']) {
fwrite(STDERR, "$status {$json['error']['code']}: {$json['error']['message']}\n");
exit(1);
}
return $json['data'];
}
$waiting = sealreply_call('GET', '/v1/conversations?status=waiting');
echo count($waiting) . " waiting\n";
if ($waiting) {
$oldest = end($waiting);
$message = sealreply_call('POST', "/v1/conversations/{$oldest['id']}/messages", [
'client_msg_id' => bin2hex(random_bytes(16)), // makes retries safe
'content_type' => 'text',
'text' => 'Thanks for waiting! Someone will be with you in a minute.',
]);
echo "replied to {$oldest['visitor']['display_name']}: {$message['id']}\n";
}go
//go:build ignore
// Your first API calls in Go (standard library only): list waiting
// conversations and answer the oldest as your integration. Needs a key with
// conversations:read and messages:write.
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
)
var (
api = envOr("SEALREPLY_API_URL", "https://api.sealreply.com")
key = os.Getenv("SEALREPLY_API_KEY")
)
func envOr(name, fallback string) string {
if v := os.Getenv(name); v != "" {
return v
}
return fallback
}
// call sends a request and decodes the envelope's data into out.
func call(method, path string, body, out any) error {
var payload bytes.Buffer
if body != nil {
if err := json.NewEncoder(&payload).Encode(body); err != nil {
return err
}
}
req, err := http.NewRequest(method, api+path, &payload)
if err != nil {
return err
}
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
var env struct {
Success bool `json:"success"`
Data json.RawMessage `json:"data"`
Error *struct{ Code, Message string }
}
if err := json.NewDecoder(res.Body).Decode(&env); err != nil {
return err
}
if !env.Success {
return fmt.Errorf("%d %s: %s", res.StatusCode, env.Error.Code, env.Error.Message)
}
return json.Unmarshal(env.Data, out)
}
type conversation struct {
ID string `json:"id"`
Visitor struct {
DisplayName string `json:"display_name"`
} `json:"visitor"`
}
func main() {
var waiting []conversation
if err := call("GET", "/v1/conversations?status=waiting", nil, &waiting); err != nil {
log.Fatal(err)
}
fmt.Printf("%d waiting\n", len(waiting))
if len(waiting) == 0 {
return
}
oldest := waiting[len(waiting)-1]
id := make([]byte, 16)
rand.Read(id)
var message struct{ ID string }
err := call("POST", "/v1/conversations/"+oldest.ID+"/messages", map[string]string{
"client_msg_id": hex.EncodeToString(id), // makes retries safe
"content_type": "text",
"text": "Thanks for waiting! Someone will be with you in a minute.",
}, &message)
if err != nil {
log.Fatal(err)
}
fmt.Printf("replied to %s: %s\n", oldest.Visitor.DisplayName, message.ID)
}用 SEALREPLY_API_KEY=sr_live_… node first-call.mjs(或对应语言的命令)运行。回复会出现在访客的聊天窗里,工作台里标为 集成。这些程序在我们的测试中会连真实 API 运行,照抄即可用。
4. 接收 Webhook
打开 开发者 → Webhook → 添加地址,填你服务器上的 HTTPS 地址,勾选 message.created,复制签名密钥(whsec_…)。在工作台发送一个测试事件,然后按 接收 Webhook 校验签名。