퀵스타트 — 예제 리포트 만들기
미리 준비된 샘플 이미지로 항상 성공하는 예제 리포트를 만들고, 공유 리포트까지 바로 확인합니다.
이 페이지의 호출은 전부 복사해서 그대로 실행할 수 있습니다. 발급받은 테스트 키만 넣으면, 미리 준비된 분석 가능한 샘플 이미지로 예제 리포트를 만들고 — 상태 확인 → 공유 리포트 열람까지 — 한 번에 따라가 볼 수 있습니다.
처음이라면 인증·호스트·모드 개념을 시작하기에서 먼저 보고 오면 좋습니다.
준비물
- 발급받은 테스트 키 (
atr_test_…). 아직 없다면 콘솔에서 프로젝트(test 환경)를 만들고 API 키를 발급하세요 — 전체 키 값은 발급 시 한 번만 표시됩니다. 자세한 절차는 시작하기를 참고하세요. curl, 그리고 JSON 파싱을 위한jq.
export ATRACE_API_KEY=atr_test_xxxxxxxxxxxxxxxxxxxx이 예제가 항상 성공하는 이유
아래 이미지 URL은 ATRACE가 호스팅하는 분석 가능한 실차 샘플입니다. 촬영 품질·각도 문제로 분석이 실패할 일이 없으므로, 키만 올바르면 리포트가 끝까지(분석 → 자동 공개) 완료됩니다. 실제 연동에서 쓰는 계약(요청·응답 형태)과 100% 동일하니, 여기서 동작을 확인한 뒤 이미지 URL만 자사 것으로 바꾸면 됩니다.
준비된 샘플 이미지
타이어 4개 위치 × {tread, sidewall} 슬롯에 매핑된 공개 샘플입니다. 트레드 4장은 마모(그루브 깊이)가
서로 다른 실차 샘플이라, 리포트에 위치별로 다른 트레드 깊이가 나타납니다.
| 슬롯 | 샘플 URL | 비고 |
|---|---|---|
| front_left · tread | https://docs.atrace.ai/samples/tire/tread-a-8mm.jpg | 트레드 약 8mm |
| front_right · tread | https://docs.atrace.ai/samples/tire/tread-a-6mm.jpg | 트레드 약 6mm |
| rear_left · tread | https://docs.atrace.ai/samples/tire/tread-b-4mm.jpg | 트레드 약 4mm |
| rear_right · tread | https://docs.atrace.ai/samples/tire/tread-c-2mm.jpg | 트레드 약 2mm |
| front_left · sidewall | https://docs.atrace.ai/samples/tire/sidewall-205-55R16.jpg | 단면폭 205 · 편평비 55 · 림 16인치 |
| rear_right · sidewall | https://docs.atrace.ai/samples/tire/sidewall-205-65R15.jpg | 단면폭 205 · 편평비 65 · 림 15인치 |
| front_right · sidewall | https://docs.atrace.ai/samples/tire/sidewall-165-60R15.jpg | tire_4t_4s에서만 사용 |
| rear_left · sidewall | https://docs.atrace.ai/samples/tire/sidewall-185-65R14.jpg | tire_4t_4s에서만 사용 |
사이드월 위치는 고정이 아닙니다
위 예시는 사이드월을 앞좌 + 뒤우 조합으로 보냅니다. 현장에서는 공간 제약으로 어느 바퀴를 찍게 될지 달라질 수 있고, 좌·우를 구분할 수 없으면 한쪽을 임의로 골라 보내도 됩니다. 자세한 배경은 이미지 수집을 보세요.
번호판 이미지(plate 모듈)는 아직 지원되지 않습니다. 다만 아래 예제는 plate_number(차량 번호)에
무작위 예시 번호를 만들어 함께 보내, 생성된 샘플 리포트에 차량 번호가 표시되도록 합니다 —
plate_number는 선택 필드이므로 생략해도 됩니다.
방법 1 — 고객 URL 모드 (가장 빠름, 한 번의 호출)
이미지 URL을 요청에 동봉하면 호출 한 번으로 분석이 시작됩니다.
template은 촬영 구성을 정하는 템플릿입니다 — 6장짜리 tire_4t_2s와 8장짜리 tire_4t_4s 중 고릅니다.
트레드 4장 + 사이드월 2장 = 6장.
# 무작위 예시 번호판 (선택 필드 plate_number). 직접 지정하거나 생략해도 됩니다.
PLATE="$((RANDOM%90+10))가$((RANDOM%9000+1000))"
RUN_ID="quickstart-4t2s-$(date +%s)-$RANDOM"
curl -X POST https://app.atrace.ai/api/v1/reports \
-H "Authorization: Bearer $ATRACE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $RUN_ID" \
-d '{
"plate_number": "'"$PLATE"'",
"external_inspection_id": "'"$RUN_ID"'",
"template": "tire_4t_2s",
"images": [
{ "module_type": "tire", "slot": { "position": "front_left", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-8mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "front_right", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-6mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_left", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-b-4mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_right", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-c-2mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "front_left", "image_type": "sidewall" },
"source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-55R16.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_right", "image_type": "sidewall" },
"source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-65R15.jpg" } }
]
}'트레드 4장 + 사이드월 4장 = 8장. 위 6장에 사이드월 2장(앞우 + 뒤좌)을 더합니다.
# 무작위 예시 번호판 (선택 필드 plate_number). 직접 지정하거나 생략해도 됩니다.
PLATE="$((RANDOM%90+10))가$((RANDOM%9000+1000))"
RUN_ID="quickstart-4t4s-$(date +%s)-$RANDOM"
curl -X POST https://app.atrace.ai/api/v1/reports \
-H "Authorization: Bearer $ATRACE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $RUN_ID" \
-d '{
"plate_number": "'"$PLATE"'",
"external_inspection_id": "'"$RUN_ID"'",
"template": "tire_4t_4s",
"images": [
{ "module_type": "tire", "slot": { "position": "front_left", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-8mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "front_right", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-6mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_left", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-b-4mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_right", "image_type": "tread" },
"source": { "url": "https://docs.atrace.ai/samples/tire/tread-c-2mm.jpg" } },
{ "module_type": "tire", "slot": { "position": "front_left", "image_type": "sidewall" },
"source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-55R16.jpg" } },
{ "module_type": "tire", "slot": { "position": "front_right", "image_type": "sidewall" },
"source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-165-60R15.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_left", "image_type": "sidewall" },
"source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-185-65R14.jpg" } },
{ "module_type": "tire", "slot": { "position": "rear_right", "image_type": "sidewall" },
"source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-65R15.jpg" } }
]
}'응답(202)에는 report_id와 이미 사용 가능한 share_url이 들어 있습니다.
{
"report_id": "123e4567-e89b-42d3-a456-426614174000",
"status": "processing",
"share_url": "https://app.atrace.ai/r/sh_abcdef"
}완료 확인 (폴링)
share_url은 생성 즉시 받지만, 분석·공개가 끝나야 열람 가능해집니다. GET /reports/{id}의
analysis_status와 publication_status를 폴링합니다.
REPORT_ID=123e4567-e89b-42d3-a456-426614174000 # 위 응답의 report_id로 교체
for i in $(seq 1 60); do # 최대 약 5분 (5초 × 60)
REP="$(curl -s "https://app.atrace.ai/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $ATRACE_API_KEY")"
ANALYSIS="$(echo "$REP" | jq -r '.analysis_status')"
PUBLICATION="$(echo "$REP" | jq -r '.publication_status')"
SUMMARY="$(echo "$REP" | jq -r '.summary_status // "-"')"
echo "[$i] analysis=$ANALYSIS publication=$PUBLICATION summary=$SUMMARY"
[ "$ANALYSIS" = "complete" ] && [ "$PUBLICATION" = "published" ] && break
sleep 5
done
if [ "$ANALYSIS" = "complete" ] && [ "$PUBLICATION" = "published" ]; then
echo "완료! 공유 리포트: $(echo "$REP" | jq -r '.links.share')"
curl -s "$(echo "$REP" | jq -r '.links.content')" \
-H "Authorization: Bearer $ATRACE_API_KEY" | jq '{status, content_revision, overall, sections}'
else
echo "아직 완료되지 않음 (analysis=$ANALYSIS, publication=$PUBLICATION). 슬롯을 확인하세요."
fi- 자체 렌더링 분석 완료 조건은
analysis_status == "complete", ATRACE 공유 화면 공개 조건은publication_status == "published"입니다. 활성 열람 링크는links.share값을 그대로 쓰세요. - 이 퀵스타트의 큐레이션 샘플은 템플릿의 성공 개수 조건을 충족하므로 두 조건에 곧 도달합니다.
- 자사 이미지에서
template.requirements[].minimum_success_count를 충족하지 못하면 공개 게이트를 통과할 수 없습니다.POST /reports/{id}/publish도 같은 조건을 우회하지 않습니다. 부족한 슬롯을 재분석하거나 새 원본으로 교체한 뒤 다시 폴링하세요. 429·5xx에는 지수 백오프로 재시도하세요. 자세한 상태 전이는 리포트 생성 흐름을 보세요.
방법 2 — Pre-Signed 모드 (자체 스토리지 없이, bash 스크립트)
자사 이미지 호스팅이 없다면 ATRACE가 발급한 URL에 직접 PUT으로 업로드합니다. 서명 URL에 PUT 하는 흐름이 처음이면 헷갈리기 쉬우므로, 아래 스크립트가 전 과정을 대신 처리합니다 — 샘플을 내려받아 업로드하고, 슬롯을 등록한 뒤, 완료까지 폴링합니다.
# 스크립트 내려받기
curl -O https://docs.atrace.ai/scripts/atrace-quickstart.sh
chmod +x atrace-quickstart.sh
# 실행 (키만 있으면 됩니다)
export ATRACE_API_KEY=atr_test_xxxxxxxxxxxxxxxxxxxx
./atrace-quickstart.sh # tire_4t_2s (6장)
TEMPLATE=tire_4t_4s ./atrace-quickstart.sh # tire_4t_4s (8장)스크립트가 하는 일은 다음과 같습니다.
리포트 생성 — images 없이 POST /reports를 호출하면, 타이어 8개 슬롯 전체의
upload_targets를 받습니다. 각 타깃에는 스토리지 PUT URL과 필수 UUID asset_id가 들어 있습니다.
스크립트는 무작위 예시 번호판(plate_number)도 함께
보내 완성된 샘플 리포트에 차량 번호가 표시되도록 합니다(선택 필드).
# 무작위 예시 번호판 (선택 필드 plate_number).
PLATE="$((RANDOM%90+10))가$((RANDOM%9000+1000))"
RUN_ID="quickstart-presigned-$(date +%s)-$RANDOM"
curl -X POST https://app.atrace.ai/api/v1/reports \
-H "Authorization: Bearer $ATRACE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $RUN_ID" \
-d '{ "plate_number": "'"$PLATE"'", "external_inspection_id": "'"$RUN_ID"'", "template": "tire_4t_2s" }'샘플 다운로드 + PUT 업로드 — 각 슬롯의 upload_url에 이미지 바이트를 그대로 PUT 합니다.
업로드는 스토리지로 바로 가고, ATRACE Report API를 거치지 않습니다.
curl -X PUT "<upload_url>" \
-H "Content-Type: image/jpeg" \
-H "Cache-Control: max-age=60" \
--data-binary @tread-a-8mm.jpg
# → HTTP 200슬롯 등록 (= 분석 자동 시작) — 실제로 업로드한 타깃만 등록합니다. 각 항목에는 생성 응답에서 받은
asset_id와 그 타깃의 중첩 슬롯(slot: { position, image_type })을 함께 보냅니다.
curl -X POST https://app.atrace.ai/api/v1/reports/$REPORT_ID/images \
-H "Authorization: Bearer $ATRACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "images": [
{ "asset_id": "1d2f4836-12f8-4bde-9e51-1aac3d848a50",
"module_type": "tire", "slot": { "position": "front_left", "image_type": "tread" } }
] }'asset_id 없이 슬롯만 보내는 이전 요청 형태는 v1.1부터 지원하지 않습니다.
완료 폴링 + 결과 조회 — 방법 1과 동일하게 analysis_status=complete와
publication_status=published를 확인합니다. 객관 결과는 report 응답, 문구와 자체 렌더링 데이터는
links.content, 공유 화면은 links.share에서 읽습니다.
Pre-Signed PUT 규약 (이대로 보내면 됩니다)
- 메서드: HTTP
PUT. - 본문: 원본 이미지 바이트 그대로(--data-binary). multipart·base64 아님. -Content-Type:image/jpeg또는image/png. - 성공 응답:200. - 만료: 발급 후 2시간(7200초). 만료되면POST /reports/{id}/upload-targets로 새 타깃을 발급받습니다.
재촬영할 때도 새 타깃을 발급받아 PUT한 뒤, 새 asset_id를
POST /reports/{id}/images?replace=true로 등록합니다. 현재 슬롯에 적용된 같은 asset_id의 등록 재시도는
멱등입니다. 교체·재분석 중에는 기존 공유 링크가 일시 비공개되고, 성공 후 자동으로 다시 공개됩니다.
결과 확인
공유 리포트(links.share)를 브라우저에서 열면, 위치별(T1~T4) 타이어 카드가 보입니다. 트레드는 측정된
그루브 깊이(mm), 사이드월은 인식된 규격이 표시됩니다. 이 예제는 마모 정도가 다른 트레드를 일부러 골랐으므로
위치마다 다른 깊이가 나타납니다.
| 위치 | 라벨 | 트레드 그루브 깊이 |
|---|---|---|
| 앞좌 | T1 | 약 8mm |
| 앞우 | T2 | 약 6mm |
| 뒤좌 | T3 | 약 4mm |
| 뒤우 | T4 | 약 2mm |
이제 이미지 URL만 자사 것으로 바꾸면 실제 연동 코드가 됩니다.