Channels
The Channels API lets you connect Schift to messaging platforms such as KakaoTalk. You can receive user messages via webhook, run RAG queries against a bucket, and send notifications back to users.
Note: All endpoints that mutate or list channel configurations require API key authentication via
Authorization: Bearer $SCHIFT_API_KEY. The Kakao webhook endpoint instead requires a registeredbot_idplus a validX-Kakao-Timestamp/X-Kakao-SignatureHMAC signature.
POST /v1/channels/kakao/webhook
Section titled “POST /v1/channels/kakao/webhook”Receive a user message from KakaoTalk via a Kakao i Open Builder skill callback. This endpoint performs RAG: it embeds the user’s message, searches the bucket linked to the channel configuration, and returns the results in KakaoTalk simpleText format.
Authentication
Section titled “Authentication”This endpoint does not use an API key. Every request must pass two checks, otherwise it returns 403 Invalid webhook signature:
- The
bot_idin the request body must match a registered channel configuration. - The request must carry a valid HMAC signature computed with the
secretstored in that channel configuration.
| Header | Description |
|---|---|
X-Kakao-Timestamp | Unix timestamp in seconds (integer). Requests outside a 300-second freshness window are rejected with 403. |
X-Kakao-Signature | Hex-encoded HMAC-SHA256(secret, "{timestamp}." + raw_request_body). The raw body bytes are signed as-is — do not re-serialize the JSON. |
A missing header, an unparseable or stale timestamp, an unconfigured secret, or a signature mismatch all return 403.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
bot_id | string | Yes | Bot identifier registered in a channel configuration. |
user_id | string | Yes | KakaoTalk user ID. |
utterance | string | Yes | User’s message text. |
Response
Section titled “Response”Returns a KakaoTalk simpleText response:
{ "version": "2.0", "template": { "outputs": [ { "simpleText": { "text": "Search results..." } } ] }}Errors
Section titled “Errors”| Status | Description |
|---|---|
400 | Invalid JSON body. |
403 | Invalid or missing bot_id, unknown channel configuration, missing/stale X-Kakao-Timestamp, or invalid X-Kakao-Signature. |
Rate-limited requests (more than 30 requests per 60 seconds per bot_id) receive a 200 KakaoTalk-format message asking the user to retry later.
Example
Section titled “Example”BODY='{"bot_id":"bot-abc123","user_id":"user-xyz789","utterance":"법인세 계산 방법"}'TS=$(date +%s)SIG=$(printf '%s.%s' "$TS" "$BODY" \ | openssl dgst -sha256 -hmac "$KAKAO_WEBHOOK_SECRET" -hex | awk '{print $NF}')
curl -X POST https://api.schift.io/v1/channels/kakao/webhook \ -H "Content-Type: application/json" \ -H "X-Kakao-Timestamp: $TS" \ -H "X-Kakao-Signature: $SIG" \ -d "$BODY"Response:
{ "version": "2.0", "template": { "outputs": [ { "simpleText": { "text": "1. (score: 0.92)\n법인세는 기업의 순이익에 대해 부과되는 세금입니다.\n\n2. (score: 0.88)\n기본세율은 정상기업 기준 22%입니다." } } ] }}POST /v1/channels/kakao/send
Section titled “POST /v1/channels/kakao/send”Send an alimtalk (KakaoTalk notification) to a user. Requires API key authentication.
알림톡은 규제 채널입니다: 사전 승인된 템플릿(template_code)과 수신자 전화번호(phone)가 항상 필요합니다. 자유 텍스트 메시지나 KakaoTalk user ID 기반 발송은 지원하지 않습니다 — 둘 중 하나라도 빠지면 400을 반환합니다. 동기 응답이 필요하면 webhook 응답을 사용하세요.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
channel_config_id | string | Yes | Channel configuration ID from POST /v1/channels/configs. |
phone | string | Yes | Recipient’s phone number. |
template_code | string | Yes | Kakao template code pre-approved in the Kakao Business dashboard. |
template_args | object | No | Template variables as key-value strings. |
Response
Section titled “Response”| Field | Type | Description |
|---|---|---|
status | string | "sent" on success. |
result | object | Kakao API response details, including message_id and sent_at. |
Errors
Section titled “Errors”| Status | Description |
|---|---|
400 | Missing template_code or phone. |
404 | Channel configuration not found. |
Example
Section titled “Example”curl -X POST https://api.schift.io/v1/channels/kakao/send \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SCHIFT_API_KEY" \ -d '{ "channel_config_id": "config-abc123", "phone": "01012345678", "template_code": "template_001", "template_args": { "product_name": "Schift API", "discount_percent": "20%" } }'Response:
{ "status": "sent", "result": { "message_id": "msg-abc123", "sent_at": 1609459200000 }}POST /v1/channels/configs
Section titled “POST /v1/channels/configs”Register a new channel configuration that stores provider-specific credentials and settings.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the configuration. |
provider | string | Yes | Provider type, such as "kakao", "slack", or "discord". |
config | object | Yes | Provider-specific configuration object. |
For Kakao, the config object should contain:
| Field | Type | Required | Description |
|---|---|---|---|
rest_api_key | string | Yes | Kakao REST API key. |
channel_id | string | Yes | Kakao channel ID. |
admin_key | string | No | Kakao admin key. |
collection | string | Yes | Bucket name used for RAG queries. |
bot_id | string | Yes | Bot ID used for webhook authentication. |
secret | string | Yes | HMAC-SHA256 secret used to verify X-Kakao-Signature on incoming webhooks. Webhook calls for a configuration without a secret are rejected with 403. |
Response
Section titled “Response”| Field | Type | Description |
|---|---|---|
id | string | Unique configuration ID. |
name | string | Configuration name. |
provider | string | Provider type. |
Errors
Section titled “Errors”| Status | Description |
|---|---|
400 | Invalid or missing required fields. |
401 | Missing or invalid API key. |
Example
Section titled “Example”curl -X POST https://api.schift.io/v1/channels/configs \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SCHIFT_API_KEY" \ -d '{ "name": "Legal RAG Bot", "provider": "kakao", "config": { "rest_api_key": "xxxxxxxxxxxxxxxx", "channel_id": "channel-123", "bot_id": "bot-abc123", "collection": "legal-docs", "secret": "whsec_xxxxxxxxxxxxxxxx" } }'Response:
{ "id": "config-abc123", "name": "Legal RAG Bot", "provider": "kakao"}GET /v1/channels/configs
Section titled “GET /v1/channels/configs”Retrieve all channel configurations for your organization. API secrets are masked in the response.
Response
Section titled “Response”Returns an array of configuration objects:
[ { "id": "config-abc123", "name": "Legal RAG Bot", "provider": "kakao", "config": { "rest_api_key": "xxxxxx...xxxx", "channel_id": "channel-123", "collection": "legal-docs" } }]Errors
Section titled “Errors”| Status | Description |
|---|---|
401 | Missing or invalid API key. |
Example
Section titled “Example”curl https://api.schift.io/v1/channels/configs \ -H "Authorization: Bearer $SCHIFT_API_KEY"DELETE /v1/channels/configs/{config_id}
Section titled “DELETE /v1/channels/configs/{config_id}”Remove a channel configuration permanently.
Path parameters
Section titled “Path parameters”| Parameter | Type | Description |
|---|---|---|
config_id | string | Unique configuration ID. |
Response
Section titled “Response”| Field | Type | Description |
|---|---|---|
deleted | boolean | true if deletion succeeded. |
Errors
Section titled “Errors”| Status | Description |
|---|---|
401 | Missing or invalid API key. |
404 | Configuration not found. |
Example
Section titled “Example”curl -X DELETE https://api.schift.io/v1/channels/configs/config-abc123 \ -H "Authorization: Bearer $SCHIFT_API_KEY"Response:
{ "deleted": true}API versions
Section titled “API versions”All endpoints in this document are part of the v1 Channels API. There is no v2 version at this time.