Upload an Image
curl --request PUT \
--url https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN} \
--header 'Authorization: <api-key>' \
--header 'Content-Type: image/jpeg' \
--data '<string>'import requests
url = "https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}"
payload = "<string>"
headers = {
"Authorization": "<api-key>",
"Content-Type": "image/jpeg"
}
response = requests.put(url, data=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: '<api-key>', 'Content-Type': 'image/jpeg'},
body: '<string>'
};
fetch('https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => "<string>",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: image/jpeg"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}"
payload := strings.NewReader("<string>")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "image/jpeg")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}")
.header("Authorization", "<api-key>")
.header("Content-Type", "image/jpeg")
.body("<string>")
.asString();require 'uri'
require 'net/http'
url = URI("https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'image/jpeg'
request.body = "<string>"
response = http.request(request)
puts response.read_body{
"error": {
"code": "bad_request",
"message": "2 fields failed validation",
"fields": [
{
"path": "candidates[0].created_at",
"problem": "timestamp must include an explicit offset"
},
{
"path": "engagement[3].views",
"problem": "must be a non-negative integer or null"
}
]
}
}{
"error": {
"code": "unauthorized",
"message": "API key missing or unknown"
}
}{
"error": {
"code": "conflict",
"message": "image already exists with different bytes"
}
}{
"error": {
"code": "too_large",
"message": "JSON body exceeds 16 MiB after decompression"
}
}{
"error": {
"code": "unsupported_media_type",
"message": "expected image/jpeg"
}
}{
"error": {
"code": "server_error",
"message": "internal error"
}
}Images API
Upload an Image
Proposed image transfer for new rehearsal candidates
PUT
/
v1
/
images
/
{gall_id}
/
{post_no}
/
{NN}
Upload an Image
curl --request PUT \
--url https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN} \
--header 'Authorization: <api-key>' \
--header 'Content-Type: image/jpeg' \
--data '<string>'import requests
url = "https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}"
payload = "<string>"
headers = {
"Authorization": "<api-key>",
"Content-Type": "image/jpeg"
}
response = requests.put(url, data=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: '<api-key>', 'Content-Type': 'image/jpeg'},
body: '<string>'
};
fetch('https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => "<string>",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: image/jpeg"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}"
payload := strings.NewReader("<string>")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "image/jpeg")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}")
.header("Authorization", "<api-key>")
.header("Content-Type", "image/jpeg")
.body("<string>")
.asString();require 'uri'
require 'net/http'
url = URI("https://dcinside-rtb-api.stg.kr.ask.surf/v1/images/{gall_id}/{post_no}/{NN}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'image/jpeg'
request.body = "<string>"
response = http.request(request)
puts response.read_body{
"error": {
"code": "bad_request",
"message": "2 fields failed validation",
"fields": [
{
"path": "candidates[0].created_at",
"problem": "timestamp must include an explicit offset"
},
{
"path": "engagement[3].views",
"problem": "must be a non-negative integer or null"
}
]
}
}{
"error": {
"code": "unauthorized",
"message": "API key missing or unknown"
}
}{
"error": {
"code": "conflict",
"message": "image already exists with different bytes"
}
}{
"error": {
"code": "too_large",
"message": "JSON body exceeds 16 MiB after decompression"
}
}{
"error": {
"code": "unsupported_media_type",
"message": "expected image/jpeg"
}
}{
"error": {
"code": "server_error",
"message": "internal error"
}
}DCinside sends each candidate’s images once through the agreed HTTPS PUT route; uploads may follow the candidate record by one or two cycles.
The agreed transfer follows the delivered v1.3 layout,
<gall_id>/<post_no>/<NN>.jpg. NN is the original body’s one-based image position, zero-padded to at least two digits. Gaps are permitted when a source image cannot be fetched. Preserve original positions rather than renumbering.
The delivered image convention includes all images, resized to a maximum 1,024-pixel long edge without upscaling. The request body for this endpoint is JPEG. The current server has a 5 MiB per-image engineering limit; verify it against rehearsal data rather than treating it as a client quota.
images_in_post gives the original post’s image count. For Model 0924’s upimg_cnt feature, a provided as-of admin snapshot value takes precedence, including an explicit zero; otherwise candidate images_in_post supplies the count. Received image bytes are never used to infer this value, and scoring does not wait for uploads. Images are outside the rehearsal pass criteria. The optional LLM deduplication stage uses available local uploads and reports incomplete evidence; image-only posts without usable evidence remain unchecked but eligible in ranked unless a duplicate is confirmed. Later uploads change dedup cache fingerprints and make affected background work eligible again. Resulting verdicts can appear in a new cycle, while completed responses remain immutable. No image URL in body_html is fetched by the API. See Event deduplication.
The optional X-Content-SHA256 header checks the uploaded bytes. Repeating the same image path with identical bytes is safe in the current implementation. Different bytes at an existing image key return 409; the stored image is preserved. Image bytes and their SHA-256 digest are immutable database records on the durable volume. Verify volume retention and replay across deployment restarts before rehearsal. The current route accepts only 1–3 digits for NN and stores a three-digit name; confirm this path convention against the client image layout rather than assuming it matches every source filename.Authorizations
Proposed API key sent as the whole Authorization header value. One long-lived key, handed privately to the partner contact and rotated on either side's request. Per-endpoint scopes are not currently enforced.
Headers
Hex SHA-256 of the body. When present we verify it, and a mismatch is rejected with 400.
Pattern:
^[0-9a-f]{64}$Path Parameters
Gallery id.
Minimum string length:
1Example:
"example_gallery"
Post number.
Required range:
x >= 1Example:
31900001
The image's position in the original body: one-based, zero-padded to at least two digits, gaps allowed. The v1.3 layout <gall_id>/<post_no>/<NN>.jpg.
Pattern:
^\d{2,}$Example:
"01"
Body
image/jpeg
The JPEG, 1024 px on the long edge. Smaller originals are not upscaled.
Response
Already stored with the same bytes.