인증

API 자체를 설명하는 인덱스를 제외한 모든 요청에 헤더 하나만 넣으면 됩니다.

Authorization: Bearer <your api key>

토큰은 프로필 페이지에서 발급합니다. 계정당 최대 10개까지 발급할 수 있고 각각 따로 폐기할 수 있으므로, 하나가 유출되어도 다른 토큰에 영향을 주지 않고 삭제할 수 있습니다. 유료 요금제가 필요합니다. 유료 요금제가 없으면 /와 /v1/account를 제외한 모든 엔드포인트가 403 plan_required를 반환합니다.

OAuth 2.1을 통해 애플리케이션이 대신 토큰을 받게 할 수도 있습니다. 로그인한 뒤 애플리케이션이 요청하는 권한을 확인하고 ‘허용’을 누르면 됩니다. 이렇게 받은 토큰도 같은 헤더에 넣으며, 똑같이 작동합니다.

?key=를 쓰지 않는 이유

쿼리 문자열에 넣은 키는 의도하지 않은 곳에 남습니다. 웹 서버 접근 로그, 브라우저 기록, 프록시 로그, 그리고 응답에 포함된 링크를 열 때 전송되는 Referer 헤더 등입니다. 그래서 API는 이 방식을 받지 않으며, 그 이유를 담아 401 missing_key를 반환합니다.

메인 사이트의 기존 ?export= URL은 여전히 ?key=를 받습니다. 몇 년 전에 작성된 스크립트들이 이 방식에 의존하고 있어, 없애면 그 스크립트들이 작동하지 않기 때문입니다. 키를 URL에 넣을 수 있는 곳은 여기뿐입니다. 자세한 내용은 기존 내보내기 URL을 참고하세요.

키가 작동하는지 확인하기

/v1/account는 가장 부담 없는 호출입니다. 할당량을 쓰지 않고 요금제가 없는 계정에서도 작동하므로, ‘이 키가 유효한가’와 ‘내가 무엇을 이용할 수 있는가’를 한 번에 확인할 수 있습니다.

curl -H "Authorization: Bearer $KEY" https://api.publicwww.com/v1/account
{
  "plan": "enterprise",
  "plan_until": 1819461840,
  "full_access": true,
  "quota": {
    "searches": { "limit": 300, "used": 12, "resets_at": 1787961600 },
    "snippets": { "limit": 100, "used": 3,  "resets_at": 1787961600 }
  },
  "limits": {
    "disclosed_positions": 4294967295,
    "max_per_page": 1000000,
    "max_per_page_snippets": 10000
  }
}

발생할 수 있는 오류

상태코드의미
401missing_keyAuthorization: Bearer 헤더가 없습니다. 쿼리 문자열에 넣은 키는 인정되지 않습니다.
401invalid_key키에 해당하는 계정이 없습니다. 불필요한 줄 바꿈이나 따옴표가 들어가 있지 않은지 확인하세요.
403plan_required키는 정상이지만 계정에 유료 요금제가 없습니다.

401 응답에는 WWW-Authenticate: Bearer 헤더도 포함되므로, 인증을 범용적으로 처리하는 HTTP 클라이언트도 올바르게 동작합니다.

애플리케이션용 OAuth 2.1

어시스턴트, 연동 서비스, 호스팅 서비스처럼 다른 사람을 대신해 작동하는 애플리케이션은 사용자에게 일일이 토큰을 복사해 달라고 요청하면 안 됩니다. 대신 사용자를 PublicWWW로 보내면, 사용자가 로그인해 애플리케이션을 승인하고, 애플리케이션은 자체 토큰을 받습니다. 이 토큰은 다른 토큰과 마찬가지로 Authorization: Bearer로 보내며, 해당 계정의 요금제, 할당량, 속도 제한 안에서 API 전체와 https://api.publicwww.com/mcp의 MCP 서버를 이용할 수 있습니다.

항목위치
인가 서버 메타데이터(RFC 8414)https://publicwww.com/.well-known/oauth-authorization-server
보호된 리소스 메타데이터(RFC 9728)https://api.publicwww.com/.well-known/oauth-protected-resource
인가 엔드포인트https://publicwww.com/oauth/authorize
토큰 엔드포인트https://publicwww.com/oauth/token
폐기 엔드포인트(RFC 7009)https://publicwww.com/oauth/revoke

애플리케이션 식별

클라이언트 등록 절차는 없습니다. client_id는 애플리케이션이 게시하는 작은 JSON 문서, 즉 클라이언트 메타데이터 문서의 https URL입니다. PublicWWW는 누군가 연결할 때마다 이 문서를 읽으므로 이름과 리디렉션 주소가 항상 최신 상태로 유지되며, 승인하는 사람은 어떤 호스트가 이 문서를 게시했는지 확인할 수 있습니다.

{
  "client_id": "https://app.example.com/oauth/client.json",
  "client_name": "Example App",
  "redirect_uris": ["https://app.example.com/oauth/callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
  • 문서 안의 client_id는 문서가 제공되는 URL과 정확히 같아야 합니다. 문서는 경로가 있는 URL에서 https로, 리디렉션을 따르지 않고 가져옵니다. 5초 안에 응답해야 하며 크기는 64KB 미만이어야 합니다.
  • redirect_uris는 https 주소여야 합니다. 사용자 컴퓨터에서 실행되는 애플리케이션이라면 127.0.0.1, localhost, [::1]의 http 주소도 허용되며, 이 경우 포트는 무엇이든 일치하는 것으로 봅니다. myapp:// 같은 사용자 지정 스킴은 허용되지 않습니다.
  • 모든 애플리케이션은 공개 클라이언트입니다. 문서에 지정된 token_endpoint_auth_method와 관계없이 토큰 요청에는 시크릿이 들어가지 않으며, 대신 PKCE로 인가 코드를 보호합니다.

인증 흐름

PKCE를 사용하는 인가 코드 방식이며, 메서드는 S256만 지원합니다. 사용자를 인가 엔드포인트로 보내세요.

https://publicwww.com/oauth/authorize
    ?response_type=code
    &client_id=https%3A%2F%2Fapp.example.com%2Foauth%2Fclient.json
    &redirect_uri=https%3A%2F%2Fapp.example.com%2Foauth%2Fcallback
    &code_challenge=<BASE64URL(SHA-256(code_verifier))>
    &code_challenge_method=S256
    &state=<random>

사용자는 아직 로그인하지 않았다면 이메일로 받은 일회용 코드로 로그인하고, 애플리케이션 이름과 문서를 게시한 호스트, 돌아갈 주소를 확인한 뒤 ‘허용’ 또는 ‘취소’를 누릅니다. redirect_uri로 돌아올 때 code, 보낸 state, iss=https://publicwww.com(RFC 9207)이 함께 전달됩니다. 코드는 10분 동안 유효하며 한 번만 사용할 수 있습니다. 코드를 토큰으로 교환하세요.

curl https://publicwww.com/oauth/token \
     -d grant_type=authorization_code \
     -d code="$CODE" \
     -d code_verifier="$VERIFIER" \
     -d client_id=https://app.example.com/oauth/client.json \
     -d redirect_uri=https://app.example.com/oauth/callback
{ "access_token": "<token>", "token_type": "Bearer", "scope": "mcp" }

scope는 생략할 수 있습니다. 스코프는 mcp 하나뿐이며 API 전체를 포함합니다. resource(RFC 8707)도 생략할 수 있으며, 보낼 경우 https://api.publicwww.com/mcp 또는 https://api.publicwww.com이어야 합니다.

토큰 유효 기간

폐기될 때까지 유효합니다. 만료 기간도, 리프레시 토큰도 없습니다. 오늘 작동하는 연동은 아무도 손대지 않아도 내일도 계속 작동합니다. 토큰은 의도적인 조치로만 폐기됩니다. 사용자가 프로필 페이지에서 애플리케이션 연결을 해제하거나, 애플리케이션이 직접 토큰을 폐기하거나, 계정이 삭제되는 경우입니다.

curl https://publicwww.com/oauth/revoke \
     -d token="$TOKEN" \
     -d client_id=https://app.example.com/oauth/client.json

폐기 엔드포인트는 토큰이 존재했는지와 관계없이 항상 200을 반환합니다.

OAuth 오류

단계코드의미
인가오류 페이지client_id 문서를 읽을 수 없거나, redirect_uri가 문서에 등록되어 있지 않습니다. 사용자는 리디렉션되지 않습니다. 검증되지 않은 주소로는 절대 이동하지 않습니다.
인가invalid_requestcode_challenge가 없거나, 메서드가 S256이 아닙니다.
인가unsupported_response_typeresponse_type=code 이외의 값입니다.
인가, 토큰invalid_targetresource가 API가 아닌 다른 값입니다.
인가access_denied사용자가 ‘취소’를 눌렀습니다.
토큰invalid_grant코드를 알 수 없거나, 이미 사용되었거나, 만료되었거나, 다른 client_id에 발급된 코드입니다. 또는 code_verifier나 redirect_uri가 일치하지 않습니다.
토큰unsupported_grant_typeauthorization_code 이외의 값입니다.

오류 페이지를 제외한 인가 오류는 redirect_uri로 error, error_description, state, iss와 함께 돌아옵니다. 토큰 오류는 같은 두 필드를 JSON으로 담은 400 응답입니다.

다음 요청 보내기