API 문서
QR 코드 생성과 URL 단축을 REST로 제공합니다. 인증 키가 필요 없고, 모든 응답에Access-Control-Allow-Origin: *가 붙어 브라우저에서 바로 호출할 수 있습니다.
기준 URL
https://your-domainQR 코드 생성
/api/qr/api/qr두 메서드는 동일한 파라미터를 받습니다. GET은 쿼리 문자열, POST는 JSON 본문을 사용합니다. 기본 응답은 이미지 바이트라 <img src>에 URL을 그대로 넣을 수 있습니다.
공통 옵션
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| type | string | url | url · text · email · tel · sms · wifi · vcard · geo |
| format | string | png | png 또는 svg. 그 외 포맷은 지원하지 않습니다. |
| size | int | 512 | 64–2000. 출력 한 변의 픽셀 길이 (여백 포함). |
| margin | int | 2 | 0–20. 모듈 단위의 여백(quiet zone). |
| ecc | string | M | L·M·Q·H. 오류 복원 레벨. 인쇄물에는 H 권장. |
| dark | string | #000000 | 전경색. #rgb · #rrggbb · #rrggbbaa. |
| light | string | #ffffff | 배경색. #ffffff00 을 주면 투명 PNG. |
| response | string | binary | json 으로 주면 dataUrl 을 담은 JSON 반환. |
| download | bool | false | true 면 Content-Disposition: attachment 추가. |
type 별 내용 파라미터
중첩 객체가 아닌 평면 구조라 쿼리 문자열과 JSON 본문에서 형태가 같습니다.
| type | 필수 | 선택 |
|---|---|---|
| url | data | — |
| text | data | — |
| to | subject, body | |
| tel | phone | — |
| sms | phone | message |
| wifi | ssid | password, encryption(WPA·WEP·nopass), hidden |
| vcard | 이름·전화·이메일 중 하나 | firstName, lastName, organization, title, phone, email, website, address, note |
| geo | latitude, longitude | — |
긴 URL을 짧게 넣기 (권장)
URL이 길수록 QR 패턴이 촘촘해져 인쇄물/저조도 환경에서 스캔 실패가 늘어날 수 있습니다. 먼저 /api/shorten으로 짧은 링크를 만든 뒤 그 값을 /api/qr?data=...에 넣는 흐름을 권장합니다. 웹 UI에서는 QR 탭 URL 입력 아래 “이 URL 숏으로 바꾸기” 버튼이 같은 동작을 수행합니다.
# 1) 긴 URL 단축
curl -X POST "https://your-domain/api/shorten" \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/really/long/path?utm_source=newsletter&utm_medium=email"}'
# 응답 예시
{
"shortUrl": "https://your-domain/s/abc1234",
...
}
# 2) shortUrl을 QR에 인코딩
curl "https://your-domain/api/qr?data=https://your-domain/s/abc1234&size=512&ecc=H" --output short-link-qr.png예시
# 가장 단순한 형태 — PNG 이미지가 그대로 돌아옵니다
curl "https://your-domain/api/qr?data=https://example.com" --output qr.png
# 투명 배경 SVG, 여백 없음
curl "https://your-domain/api/qr?data=https://example.com&format=svg&light=%23ffffff00&margin=0" \
--output qr.svg
# Wi-Fi 접속용 QR
curl "https://your-domain/api/qr?type=wifi&ssid=MyCafe&password=hunter2&encryption=WPA" \
--output wifi.png
# POST + JSON, dataUrl 로 받기
curl -X POST "https://your-domain/api/qr" \
-H 'Content-Type: application/json' \
-d '{"type":"vcard","firstName":"길동","lastName":"홍","phone":"+82-10-1234-5678",
"ecc":"H","size":800,"response":"json"}'HTML에 바로 삽입
<img src="https://your-domain/api/qr?data=https://example.com&size=256" width="256" alt="QR" />URL 단축
/api/shorten요청 본문
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| url | string | 필수 | 줄일 http/https 주소. 스킴 생략 시 https 로 간주. |
| slug | string | 선택 | 원하는 코드. 영문·숫자·하이픈·밑줄 3–64자. |
| expiresIn | int | 선택 | 만료까지 남은 초. 생략하면 만료 없음. |
예시
curl -X POST "https://your-domain/api/shorten" \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/very/long/path","slug":"my-link","expiresIn":86400}'응답 (201 Created)
{
"code": "my-link",
"shortUrl": "https://your-domain/s/my-link",
"url": "https://example.com/very/long/path",
"createdAt": "2026-07-28T08:00:00.000Z",
"expiresAt": "2026-07-29T08:00:00.000Z",
"clicks": 0,
"lastClickedAt": null,
"qrUrl": "https://your-domain/api/qr?data=...",
"statsUrl": "https://your-domain/api/links/my-link",
"reused": false
}slug 없이 같은 URL을 두 번 단축하면 새 코드를 만들지 않고 기존 링크를 그대로 돌려주며 200과 reused: true가 됩니다. 이 서비스의 QR API URL(/api/qr?…)은 단축할 수 있습니다. 단축 링크·통계 URL처럼 이미 짧은 주소는 새로 만들지 않고, 저장된 링크가 있으면 그 값을 돌려줍니다.
링크 조회 및 리다이렉트
/s/{code}원본 주소로 307 리다이렉트하고 클릭 수를 1 올립니다. 코드가 없거나 만료되었으면 안내 페이지를 보여줍니다. 예: https://your-domain/s/my-link
/api/links/{code}클릭 수와 만료 정보를 JSON으로 반환합니다. 없으면 404.
curl "https://your-domain/api/links/my-link"/api/health서비스 상태와 현재 저장소 드라이버를 반환합니다.
관리자 전용
아래 두 엔드포인트는 ADMIN_TOKEN 환경변수가 설정되어 있을 때만 동작하며 Authorization: Bearer <token> 헤더가 필요합니다. 변수가 없으면 404로 응답합니다. 삭제를 공개하면 누구나 남의 링크를 지울 수 있고, 목록을 공개하면 단축된 모든 URL이 노출되기 때문입니다.
/api/links/{code}/api/links?limit=50curl -X DELETE "https://your-domain/api/links/my-link" \
-H "Authorization: Bearer $ADMIN_TOKEN"오류 형식
모든 오류는 같은 형태입니다. 검증 실패(422)일 때 details에 필드별 메시지가 담깁니다.
{
"error": {
"code": "validation_failed",
"message": "Request validation failed.",
"details": { "size": "Too big: expected number to be <=2000" }
}
}| 상태 | code | 의미 |
|---|---|---|
| 400 | bad_request | 본문이 JSON이 아니거나 URL을 인코딩할 수 없음 |
| 401 | unauthorized | 관리자 토큰이 없거나 틀림 |
| 404 | not_found | 코드를 찾을 수 없거나 관리자 기능이 비활성화됨 |
| 409 | conflict | 요청한 slug 가 이미 사용 중 |
| 413 | payload_too_large | 본문 또는 인코딩된 내용이 한도 초과 |
| 415 | unsupported_media_type | Content-Type 이 application/json 이 아님 |
| 422 | validation_failed | 파라미터 값이 규칙에 맞지 않음 |
| 503 | service_unavailable | 고유 코드 발급 실패 — 재시도 권장 |
제한 사항
- • QR에 담을 수 있는 내용은 최대 2,953 바이트입니다(버전 40, ECC L 기준). 복원 레벨을 올리면 한도가 줄어듭니다.
- • 단축 대상 URL은 최대 2,048자이며
http/https만 허용합니다. - • 이 서비스의 단축 링크·페이지를 대상으로 새 단축 링크를 만들 수는 없습니다. 예외로 QR API URL(
/api/qr?…)은 단축할 수 있습니다. - • 사설·루프백·링크로컬 주소(
localhost,10.x,192.168.x,169.254.x등)는 단축할 수 없습니다. - • 현재 레이트 리밋이 없습니다. 공개 인터넷에 노출하기 전에 IP 단위 제한을 붙이는 것을 권장합니다.