AFTERLOG

Afterlog cho nhà phát triển

Đưa hành trình Afterlog vào ứng dụng và dịch vụ của bạn.

Widget nhúng

Đặt thanh trượt Before↔Current hoặc thẻ hành trình lên bất kỳ trang nào. Chỉ hành trình công khai — không cần API key.

Xem trực tiếp

Thẻ script

Thêm script SDK và một div giữ chỗ; widget tự gắn và tự điều chỉnh chiều cao.

<script async src="https://afterlog.me/sdk/afterlog.js"></script>
<div data-afterlog-journey="JOURNEY_ID" data-afterlog-theme="light"></div>

iframe trực tiếp

Nhúng không cần JavaScript. Dùng theme=light|dark và variant=slider|card.

<iframe
  src="https://afterlog.me/embed/journey/JOURNEY_ID?theme=light&variant=slider"
  width="480" height="520" style="border:0;max-width:100%"
  scrolling="no" loading="lazy" title="Afterlog journey"></iframe>

oEmbed

Dán URL hành trình vào Slack, WordPress và các công cụ hỗ trợ oEmbed.

GET https://afterlog.me/api/oembed?url=https://afterlog.me/journey/JOURNEY_ID&format=json

Partner API

API REST chỉ đọc dành cho đối tác đã duyệt. Đưa hành trình công khai, xu hướng, tìm kiếm và hồ sơ vào sản phẩm của bạn.

Xác thực

Gửi khóa của bạn trong header x-api-key. Cấp khóa từ bảng điều khiển nhà phát triển bên dưới.

curl https://api.afterlog.me/v1/partner/trending \
  -H "x-api-key: ak_live_..."

Truy cập sớm

API Đối tác hiện chỉ dành cho người được mời. Đăng ký ứng dụng, rồi chúng tôi duyệt trước khi khóa của bạn hoạt động.

  • 403Ứng dụng chưa được duyệt, hoặc khóa đã bị thu hồi.
  • 401Thiếu hoặc x-api-key không hợp lệ.
  • 429Vượt giới hạn tần suất — chờ theo header Retry-After rồi thử lại.

Điểm cuối

Mọi đường dẫn đều tương đối so với https://api.afterlog.me/v1 và chỉ đọc. Xu hướng và tìm kiếm phân trang bằng cursor và nextCursor.

GET /partner/trending?category=&sort=trending|helpful&cursor=&limit=
GET /partner/search?q=&cursor=&limit=
GET /partner/journeys/:id
GET /partner/profiles/:username
GET /partner/profiles/:username/journeys?sort=recent|pinned

Cấu trúc phản hồi

Hành trình được trả về dưới dạng chế độ xem công khai — ảnh bìa, thẻ, thống kê và chủ sở hữu. Không có trường riêng của người xem hay trường riêng tư.

{
  "items": [
    {
      "id": "cmr576hhy000n5s6a1b2c3d4",
      "userId": "cmr4qx8p0000ab12cd34",
      "title": "코 성형 회복 여정",
      "category": "BEAUTY",
      "categoryCustom": null,
      "startDate": "2026-01-15",
      "privacy": "PUBLIC",
      "status": "PUBLISHED",
      "description": "붓기와 회복 과정을 매주 기록합니다.",
      "tags": ["recovery", "beauty"],
      "coverMediaId": "cmr58a4k0001...",
      "coverUrl": "https://disk.afterlog.me/media/.../320.webp",
      "captureSlots": [{ "key": "front", "label": "Front" }, { "key": "side", "label": "Side" }],
      "heroSlot": "front",
      "createdAt": "2026-01-15T09:12:00.000Z",
      "updatedAt": "2026-07-14T02:31:00.000Z",
      "stats": {
        "daysCount": 180, "updatesCount": 12, "viewsCount": 3400,
        "savesCount": 210, "followersCount": 95, "helpfulCount": 88,
        "completedReadsCount": 40, "forksCount": 3, "helpfulnessScore": 0.82
      },
      "owner": {
        "userId": "cmr4qx8p0000ab12cd34", "username": "riah_kim",
        "displayName": "Riah", "avatarMediaId": null,
        "avatarUrl": "https://disk.afterlog.me/media/.../320.webp"
      },
      "trendingScore": 128.4
    }
  ],
  "nextCursor": "eyJjIjoiMjAyNi0wNy0xNCJ9"
}

Sẵn sàng xây dựng? Đăng ký ứng dụng và cấp khóa đầu tiên của bạn.

Mở bảng điều khiển nhà phát triển

OAuth cho dữ liệu người dùng

Cho phép người dùng kết nối tài khoản Afterlog để ứng dụng của bạn đọc hành trình của họ — kể cả riêng tư — thay mặt họ. Authorization Code + PKCE (S256).

Luồng

  1. 1. Đưa người dùng đến URL ủy quyền kèm PKCE challenge và các scope yêu cầu.
  2. 2. Người dùng xem xét và chấp thuận trên Afterlog; chúng tôi chuyển hướng về redirect_uri kèm code dùng một lần và state của bạn.
  3. 3. Đổi code lấy token tại token endpoint, gửi kèm code_verifier ban đầu của bạn.
  4. 4. Gọi Partner API với Authorization: Bearer <access_token>. Token truy cập kéo dài 1 giờ; dùng refresh để xoay vòng.

Scope

journeys.readĐọc hành trình và nhật ký của người dùng đã kết nối, kể cả riêng tư.
profile.readĐọc hồ sơ công khai của người dùng đã kết nối.

URL ủy quyền

Chuyển hướng trình duyệt đến đây. redirect_uri phải khớp chính xác với một giá trị đã đăng ký trên ứng dụng, và bắt buộc PKCE với method=S256.

https://afterlog.me/oauth/authorize?response_type=code
  &client_id=YOUR_APP_ID
  &redirect_uri=https://your.app/callback
  &scope=journeys.read%20profile.read
  &state=RANDOM_CSRF
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

Đổi token

Đổi code lấy token access + refresh. Client confidential còn gửi client_secret.

curl -X POST https://api.afterlog.me/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "client_id": "YOUR_APP_ID",
    "code": "<code from redirect>",
    "redirect_uri": "https://your.app/callback",
    "code_verifier": "<original PKCE verifier>"
  }'

Dùng token

Gửi access token dưới dạng header Bearer khi đọc Partner API. Với journeys.read, hành trình riêng tư của người dùng đã kết nối cũng được bao gồm.

curl https://api.afterlog.me/v1/partner/journeys/JOURNEY_ID \
  -H "Authorization: Bearer <access_token>"

Webhook

Nhận thông báo khi người dùng đã kết nối thêm nhật ký hoặc công khai hành trình. Payload là tín hiệu mỏng — lấy chi tiết từ Partner API.

Quản lý điểm cuối

Đăng ký, liệt kê và xóa điểm cuối theo ứng dụng trong bảng điều khiển nhà phát triển. Secret ký được hiển thị một lần khi tạo. URL phải là https và không được trỏ tới host riêng.

Sự kiện

journey.update.createdNgười dùng đã kết nối thêm một nhật ký (Update) vào hành trình.
journey.publishedNgười dùng đã kết nối công khai một hành trình.

Payload

Mỗi lần gửi có id duy nhất (dùng cho idempotency), một event, dấu thời gian và một đối tượng data mỏng.

{
  "id": "whd_5f3a1c...",                     // 배달 고유 id (수신측 idempotency 키)
  "event": "journey.update.created",
  "createdAt": "2026-07-19T09:00:00.000Z",
  "data": {
    "journeyId": "jr_...", "updateId": "up_...",
    "username": "riah", "title": "코 성형 회복 여정"
  }
}

Xác minh chữ ký

Mỗi yêu cầu có X-Afterlog-Signature: t=<unix>,v1=<hex>, trong đó v1 = HMAC-SHA256 của "<t>.<body thô>". Tính lại trên body thô và so sánh theo thời gian hằng số.

// header: X-Afterlog-Signature: t=<unix>,v1=<hex>
const [t, v1] = header.split(',').map((s) => s.split('=')[1]);
const expected = crypto
  .createHmac('sha256', secret)                // secret = whsec_...
  .update(`${t}.${rawBody}`)                   // 받은 원문 바디 그대로 사용
  .digest('hex');
const ok = crypto.timingSafeEqual(
  Buffer.from(expected), Buffer.from(v1),
);
// t 가 최근(±5분)인지도 확인해 재전송(replay)을 막는다.

Thử lại và tự tắt

2xx là thành công. Thất bại và hết thời gian (10s) được thử lại tối đa 3 lần. Sau 10 lần thất bại tích lũy, điểm cuối tự động bị tắt; tạo lại để bật lại.

Afterlog cho nhà phát triển | Afterlog