> ## Documentation Index
> Fetch the complete documentation index at: https://surf-dcinside-api.kr.ask.surf/llms.txt
> Use this file to discover all available pages before exploring further.

# Conventions

> Proposed transport, timestamps, retries and current service protections

## Contract status

This is a proposed rehearsal contract. Required fields in OpenAPI describe the proposed wire format; they are not evidence that DCinside has agreed to every field. Existing implementation restrictions are identified below so that they can be resolved before rehearsal.

## Base URL and authentication

Surf and DCinside need to confirm the reachable rehearsal host, a long-lived scoped credential, and whether an IP allowlist is practical for the sending machines. `rtb.example.com` is a placeholder, not a working host.

The current API accepts the key as the whole header value:

```http theme={null}
Authorization: <api-key>
```

Credential scope and rotation procedure remain to be agreed. The current key check does not implement per-endpoint scopes; do not assume a `403` scope check is active. `/v1/health` currently permits unauthenticated access.

## Formats

| Topic | Proposed convention |
| - | - |
| Encoding | UTF-8 JSON. Plain JSON and gzip are supported; send `Content-Encoding: gzip` only when compressed. |
| Times | RFC 3339 with an explicit offset, including `Z` for UTC. Normalize to KST for cycle IDs and time-of-day features. A `+09:00` wire offset is not mandatory. |
| Counters | Non-negative integers; `null` means unknown. Do not substitute zero for an unknown reading. |
| Post identity | `gall_id` plus `post_no`; post numbers are not globally unique. |
| Field mapping | Reuse the delivered v1.2/v1.3 column names where practical. Additional metadata and required fields need payload review. |
| Extra fields | The current parser ignores unknown fields without necessarily warning. Confirm any field on which the integration depends. |

## Cycle interval

We propose five minutes initially, matching 288 daily cycles in DCinside's acceptance draft. DCinside described a configurable 2–5-minute interval. The current implementation only accepts five-minute boundaries; this is an implementation restriction, not a jointly agreed business requirement. Confirm the interval before rehearsal and support the agreed setting.

The existing wire shape uses the KST cycle time as `cycle_id`, for example `20260929T0205`. Keep that ID stable on retries. The exact ID format remains part of the proposed protocol.

## Retries and recovery

For cycles, the proposal is: same ID and same body returns the original completed result; same ID with a different body returns `409 cycle_conflict`. `GET /v1/scores/{cycle_id}` retrieves that result without scoring again. A new cycle may produce new scores for the same pending posts.

Skipping a late score does **not** mean discarding undelivered candidate data or removals. Retain unacknowledged data until receipt is established by replay, retrieval or reconciliation. Avoid changing a possibly accepted request under the same ID. Cross-cycle recovery and retention rules must be settled and tested before rehearsal.

A response deadline and a retry budget must be agreed separately. The helper client's 60-second default is a local implementation setting, not an agreed response deadline. There is no automatic `202`/polling switch in the current API.

## Current service protections

| Protection | Current implementation |
| - | - |
| JSON request body | 16 MiB after decompression |
| New candidates per cycle | No candidate-count cap |
| Each other cycle array | 5,000 rows |
| Outcomes per request (Not in scope for trial) | 5,000 records |
| Image body | 5 MiB |
| Weight version / note | Version up to 64 characters using letters, digits, `.`, `_`, `-`; note up to 500 characters |

These are engineering protections, not client quotas. Validate them against the full queue before rehearsal. If a complete cycle exceeds a protection, change the limit or agree a batch protocol; never silently truncate or sample the queue. Different bodies cannot be split under one cycle ID. Pagination is not currently implemented.

DCinside handles the 24-hour age filter and sends aged-out removals. About 2,200 new posts/day is an estimate; it is not an API limit.
