개발자
책을 읽음으로 표시하는 것도 API 작업입니다.
서재에서 작품을 “읽음”으로 표시하면 웹사이트는 아래 요청을 보냅니다. 프로그램도 같은 요청을 보내면 같은 결과를 받고 같은 검사를 거칩니다.
쓰기
쓰기 요청을 한 줄씩 살펴봅니다
PUT /v1/works/{id}/reader-status
Authorization: Bearer …
Idempotency-Key: 7f3c2a9e-read
Content-Type: application/json
{
"actingSubject":
"https://rezics.com/id/…",
"expectedVersion": 3,
"status": "read",
"finishedOn": "2026-10-19"
}경로가 작품을 가리킵니다
{id}REZICS의 모든 항목에는 https://rezics.com/id/로 시작하는 고정 식별자가 있습니다. 언어나 사이트가 바뀌어도 같습니다.
ID 명시
actingSubject계정은 자신이나 조직을 대표할 수 있습니다. 쓰기 요청마다 어떤 ID로 작업하는지 명시해야 하며, 서버는 실행 전에 해당 ID의 권한을 확인합니다.
안전한 재전송
Idempotency-Key모든 쓰기 요청에 멱등성 키를 포함합니다. 시간이 초과되거나 연결이 끊긴 뒤 같은 키로 다시 보내도 중복으로 기록되지 않습니다.
덮어쓰기 방지
expectedVersion3번째 버전을 읽었다면 요청에도 3번째 버전을 명시합니다. 그 사이 다른 사람이 수정했으면 이번 쓰기는 기존 내용을 덮어쓰지 않습니다.
오류는 문제 세부 정보로
application/problem+json실패하면 고정된 code를 반환합니다. 프로그램은 메시지 문구를 비교하지 않고 코드에 따라 분기할 수 있습니다.
재전송
같은 요청을 다시 보내면 같은 결과를 받습니다.
같은 키와 같은 내용을 다시 보내면 서버는 첫 요청의 결과를 반환합니다. 버전은 계속 4이고 replayed는 true가 됩니다. 같은 키에 다른 내용을 보내면 409 reader_status_conflict를 반환합니다. 버전이 이미 3이 아니면 409 stale_reader_status를 반환하므로 다시 읽은 뒤 쓰면 됩니다.
첫 요청
200 { "status": "read", "version": 4, "replayed": false }재전송
200 { "status": "read", "version": 4, "replayed": true }버전 만료
409 { "status": 409, "code": "stale_reader_status" }
타입
API와 타입은 같은 정의에서
REZICS 웹사이트는 TypeScript로 API를 호출하며 요청과 응답 타입은 서버의 라우트 선언에서 직접 가져옵니다. 필드 이름이 바뀌거나 오류 코드가 추가되면 호출하는 쪽에서 컴파일할 때 알 수 있습니다. TypeScript SDK도 같은 정의에서 생성되므로 웹사이트와 같은 타입을 사용합니다.
OpenAPI 3.1 문서도 같은 라우트 선언에서 생성됩니다. 각 작업의 검증 방식, 요청 형식, 상태 코드별 응답을 명시합니다.
main().v1
.works({ id: uuid(work) })
['reader-status'].put({
actingSubject,
expectedVersion,
status: 'read',
...dates,
}, headers())generated/openapi/main/public.json
읽기
읽기에도 규칙이 있습니다
nextCursor · snapshot긴 목록에는 다음 페이지 커서가 있어 끝까지 차례로 읽을 수 있습니다. 서재 내보내기에는 스냅샷도 포함되어 데이터가 중간에 바뀌면 알려 줍니다. 서로 다른 파일을 임의로 조합하게 두지 않습니다.
count.precision검색 결과의 전체 개수가 정확한 값인지 “최소 이만큼”인지 명시합니다.
title.language · basis제목에는 언어 태그와 문자 방향을 표시합니다. 이 언어가 요청한 언어인지, 같은 문자 체계인지, 다른 문자 체계인지, 대체 언어인지도 설명합니다.
404 resource_unavailable볼 권한이 없는 리소스는 존재하지 않는 리소스와 같은 응답을 반환해 존재 여부를 드러내지 않습니다.