Skip to content

快速开始 ​

大约 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 校验签名。

接下来 ​