문서 · 레퍼런스
관리 REST API
콘솔에서 하는 일을 HTTP로 해요. 엔드포인트 315개를 서버 코드(rest.ts, operations.ts)에서 읽어 이 페이지와 OpenAPI 문서를 만들어요. 이 목록은 서버 코드에서 만들어져요. 새 기능이 생기면 여기에도 바로 나타나요.
시작하기
기본 주소
https://end.blackall.ai/api/v1
인증
모든 요청에 Authorization: Bearer <토큰> 헤더가 필요해요. 토큰은 콘솔의 계정 → API · MCP 토큰에서 만든 bwk_… 개인 토큰이거나, MCP 클라이언트가 OAuth로 받은 액세스 토큰이에요.
curl https://end.blackall.ai/api/v1/me \
-H "Authorization: Bearer $ONEEND_TOKEN"
범위와 역할
토큰 범위는 read와 write예요. 읽기만 하면 read, 무엇이든 바꾸면 write가 필요해요. 토큰은 주인의 역할을 따라서, 역할이 모자라면 write 토큰이라도 403을 받아요.
언어
오류 문장과 note는 ?lang=en, ?lang=ja 또는 Accept-Language 헤더를 따라요. 아무것도 없으면 한국어예요. 나머지 응답은 데이터라서 언어와 상관없어요.
한도
요청 본문은 기본 256 KiB까지예요. 더 큰 본문을 받는 경로(마이그레이션, 함수 배포 등)는 항목에 따로 적었어요. 토큰별 요청 횟수 제한은 없고, CORS는 모든 출처에 열려 있어요.
OpenAPI 3.1
같은 내용을 OpenAPI 3.1 문서로 받을 수 있어요. 코드 생성기나 Postman에 그대로 넣으세요.
openapi.json 내려받기 · https://end.blackall.ai/docs/api/openapi.json
상태 코드
실패하면 아래 상태 코드와 함께 {"error": {"message": "…"}}를 돌려줘요. 메시지에 다음에 할 일이 적혀 있어요.
{ "error": { "message": "…" } }
note가 있으면 다음에 할 일을 알려 주는 문장이에요.
계정과 리전
GET /api/v1/
API 버전 이 API의 이름과 버전을 돌려줘요. 토큰이 맞는지 확인할 때 써요.
curl "https://end.blackall.ai/api/v1/" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/me
내 계정 이 토큰이 누구의 것이고 어떤 권한을 가졌는지 알려줘요. operator는 운영자 도구를 쓸 수 있는지(active)와, 못 쓰면 이 계정의 이유(refused: not_listed, token_bound, no_second_factor)예요. 무엇부터 할지 모를 때 먼저 부르세요.
curl "https://end.blackall.ai/api/v1/me" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/me', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/regions
리전 목록 리전 목록이에요. can_create가 true인 곳만 지금 만들 수 있어요. 리전은 나중에 못 바꾸니 create_project 전에 확인하세요.
curl "https://end.blackall.ai/api/v1/regions" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/regions', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/regions/requests
리전 요청 아직 열리지 않은 리전(can_create가 false인 곳)이 필요하다고 남겨요. 담당자가 직접 연락해요. 날짜를 약속하지는 않아요. 이미 열린 리전은 요청하지 말고 create_project로 바로 만드세요.
curl -X POST "https://end.blackall.ai/api/v1/regions/requests" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"region":"kr"}'
const response = await fetch('https://end.blackall.ai/api/v1/regions/requests', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"region": "kr"
}),
})
const result = await response.json()
GET /api/v1/server-sizes
서버 크기와 가격 서버 크기(메모리)마다 구글 서버, CPU, 지역별 월 금액(monthly_minor)이에요. 통화를 비우면 조직의 결제 통화예요. KRW는 원(부가세 포함), USD는 센트(결제할 때 세금 추가)예요. included_in이 pro인 크기는 Pro 요금제에 포함돼요. region_status가 planned인 지역은 준비 중이라 고를 수 없어요. listed가 false면 아직 팔지 않는 것이라 sizes가 비어 있어요.
curl "https://end.blackall.ai/api/v1/server-sizes?region=kr¤cy=KRW" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/server-sizes?region=kr¤cy=KRW', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/imports/sources
가져올 곳 이 조직에 연결한 원본 계정(Supabase, Vercel, PostgreSQL)마다 프로젝트 목록과 지금까지의 가져오기를 봐요. 계정 연결은 토큰이 대화에 남지 않게 콘솔(connect_url)에서 해요.
curl "https://end.blackall.ai/api/v1/imports/sources?org=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/imports/sources?org=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/imports
가져오기 시작 콘솔에서 만든 가져오기(import)나 import_sources의 connection·project로 가져오기를 시작해요(묶음마다 새 프로젝트, 원본은 그대로). Supabase는 address에 세션 풀러 연결 문자열이 필요해요(쓰고 지워요). 다시 시작하면 바뀐 것만 옮겨요. 소유자·관리자·개발자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/imports?org=value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{}'
const response = await fetch('https://end.blackall.ai/api/v1/imports?org=value', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({}),
})
const result = await response.json()
GET /api/v1/imports/{id}
가져오기 진행 상황 콘솔의 가져오기 진행 화면과 같아요. 옮길 곳마다 단계(스키마, 로그인 사용자, 데이터, 파일, 예약 작업…)의 상태와 수, 옮기지 않는 것과 이유, 확인할 것을 보여줘요.
curl "https://end.blackall.ai/api/v1/imports/ID?org=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/imports/ID?org=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
프로젝트
GET /api/v1/projects
프로젝트 목록 이 계정의 프로젝트와 각각의 API 주소를 돌려줘요. status는 ready(쓸 수 있음), provisioning(데이터베이스를 만드는 중, 몇 초), failed(retry_provisioning), paused예요.
curl "https://end.blackall.ai/api/v1/projects" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects
프로젝트 만들기 데이터베이스·인증·파일 저장소가 딸린 프로젝트를 만들어요. 리전은 비우면 기본 리전이고 나중에 못 바꿔요. 조직이 여럿이면 org로 골라요(요금제의 프로젝트 수 안에서). status가 provisioning이면 wait(초)를 주거나 ready가 된 뒤 표·키를 쓰세요.
curl -X POST "https://end.blackall.ai/api/v1/projects?wait=0" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","region":"kr","org":"value","wait":0,"tier":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects?wait=0', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"region": "kr",
"org": "value",
"wait": 0,
"tier": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}
프로젝트 하나 list_projects가 돌려주는 항목 하나를 ref로 찾아 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PATCH /api/v1/projects/{ref}
이름 바꾸기 프로젝트 이름이나 조직 이름, 또는 둘 다 바꿔요. ID(ref)와 주소는 바뀌지 않아요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","organisation":"My team"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"organisation": "My team"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/pause
프로젝트 일시정지 프로젝트를 멈춰요: 사이트·API·함수는 503, 실시간·예약 작업·새 배포도 멈춰요. 데이터는 남고 resume_project로 바로 돌아와요. 90일 넘게 멈추면 데이터베이스를 보관 저장소로 옮겨요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/pause" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/pause', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/resume
프로젝트 다시 시작 일시정지한 프로젝트를 다시 시작해요. 무료 요금제에서 3일 동안 쓰지 않아 멈춘 프로젝트도 이걸로(또는 새 배포로) 다시 켜요. 예약 작업은 놓친 실행을 몰아서 하지 않고 다음 일정부터 돌아요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/resume" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/resume', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/archive
데이터베이스 보관 상태 데이터베이스를 못 쓰는 상태(결제 실패, 무료 요금제, 일시정지)가 90일 이어지면 보관 저장소로 옮겨요. 이 프로젝트의 state(none, scheduled, archiving, archived, restoring, purged), reason, archive_at, purge_at(옮긴 뒤 1년, 보관 파일과 파일을 지우는 때), restore_blocked_by를 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/archive" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/archive', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/archive/restore
보관한 데이터베이스 복원 보관한 데이터베이스를 다시 만들어요(보통 몇 분). 결제가 안 끝났거나 무료 요금제면 거절해요(restore_blocked_by). 보관 파일이 지워졌으면 빈 데이터베이스를 만들어요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/archive/restore" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/archive/restore', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/archive/download
보관 파일 내려받기 주소 보관한 데이터베이스(pg_dump 형식, pg_restore로 복원)를 1시간 동안 내려받을 수 있는 서명 주소를 만들어요. 이유를 함께 적어야 하고, 개인정보 접속기록에 남아요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/archive/download" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"reason":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/archive/download', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"reason": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}
프로젝트 삭제 프로젝트의 표·가입자·파일·함수·예약 작업·환경 변수·도메인을 영구히 지워요. 되돌릴 수 없어요. 사용자가 요청할 때만 쓰고 confirm에 프로젝트 이름을 넣으세요. 마지막 프로젝트는 못 지워요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/retry-provisioning
준비 실패한 프로젝트 다시 시도 데이터베이스를 만들지 못한 프로젝트를 다시 준비해요. 다른 도구가 "만들지 못했어요"로 거절할 때 쓰세요. 프로젝트를 새로 만들지 마세요. 요금만 두 배가 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/retry-provisioning" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/retry-provisioning', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
키와 서명
GET /api/v1/projects/{ref}/keys
API 키 가져오기 프로젝트 주소와 두 키예요. 비밀 키는 접근 규칙을 무시하니 서버에서만 쓰세요(쓰기 권한 토큰 필요). 프론트엔드용이면 only: "publishable"로 부르세요: 주소와 공개 키만 오고 읽기 권한 토큰으로도 돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/keys?only=publishable" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/keys?only=publishable', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/api-keys
이름 붙은 API 키 목록 용도별로 만든 bw_publishable_·bw_secret_ 키의 이름, 종류, 앞부분, 마지막 사용 시각, 폐기 여부예요. 비밀 키의 값은 돌려주지 않아요. 공개 키는 값도 줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/api-keys" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/api-keys', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/api-keys
API 키 만들기 이름 붙은 키를 하나 만들어요. publishable은 브라우저용(접근 규칙을 따름), secret은 서버용(접근 규칙을 무시)이에요. 비밀 키 값은 이 응답에만 있고 다시 볼 수 없어요. 소유자·관리자만 만들 수 있고, 프로젝트마다 20개까지예요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/api-keys" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"kind":"publishable","name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/api-keys', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"kind": "publishable",
"name": "my-name"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/api-keys/{id}
API 키 폐기 이름 붙은 키 하나를 폐기해요. 30초 안에 그 키로 오는 요청이 거부돼요. 다른 키는 그대로예요. 되돌릴 수 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/api-keys/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/api-keys/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/signing
토큰 서명 방식 로그인 토큰을 HS256과 ES256 중 무엇으로 서명하는지와, 지금 받아 주는 예전 키(유예 중인 키)를 보여줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/signing
토큰 서명 방식 바꾸기 ES256으로 바꾸면 새 로그인부터 비대칭 키로 서명하고, 다른 서버가 공개 키(JWKS)로 토큰을 확인할 수 있어요. 이미 받은 토큰은 만료될 때까지 그대로 통해요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"alg":"HS256"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"alg": "HS256"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/signing/rotate
키 교체 공개 키·비밀 키를 서명하는 키를 새로 만들어요. 예전 키는 grace_hours(0, 1, 24, 168) 동안 더 받아요. 0(기본)이면 지금 앱이 30초 안에 모두 멈추니 confirm에 프로젝트 이름이 필요해요. 사용자가 요청할 때만, 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing/rotate" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"grace_hours":0,"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing/rotate', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"grace_hours": 0,
"confirm": "my-project"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/signing/keys/{kid}
예전 키 폐기 유예 중인 예전 키를 지금 끝내요. kid는 get_jwt_signing의 keys에서 state가 rotating인 것이에요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing/keys/KEY_ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/signing/keys/KEY_ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
데이터베이스
GET /api/v1/projects/{ref}/advisors
보안·성능 점검 데이터베이스 구조의 보안·성능 문제를 찾아요: RLS가 꺼진 표, 누구나 쓰는 규칙, 규칙을 무시하는 뷰, search_path 없는 security definer 함수, 사용자 표를 내보내는 뷰, 인덱스 없는 외래 키, 기본 키 없는 표, 중복 인덱스, 행마다 uid()를 부르는 규칙. 고칠 SQL(remedy)도 줘요. 표나 규칙을 바꾼 뒤 부르세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/advisors" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/advisors', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/tables/{table}/csv
표를 CSV로 내보내기 표를 CSV로 돌려줘요(첫 줄은 열 이름). 1MB를 넘으면 잘리고 truncated가 true예요: filters로 나눠 받으세요. 빈 칸은 NULL, ""는 빈 문자열이에요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/tables/notes/csv?sort=value&desc=true" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/tables/notes/csv?sort=value&desc=true', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/tables/{table}/csv
CSV를 표로 가져오기 CSV를 표에 넣어요. 첫 줄의 열 이름대로 들어가요(columns로 바꿔요). 한 줄이라도 실패하면 아무것도 넣지 않고 줄 번호와 이유를 알려 줘요. 2MB, 10,000줄까지예요. 따옴표 없는 빈 칸은 NULL이나 기본값이에요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/tables/notes/csv" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"csv":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/tables/notes/csv', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"csv": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/tables
표 목록 프로젝트의 표와 각 표의 칸, 대략의 줄 수, 접근 규칙 상태를 돌려줘요. 규칙이 켜져 있고 규칙 수가 0이면 공개 키로는 아무것도 보이지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/tables" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/tables', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/policies
접근 규칙 목록 어떤 표의 어떤 동작이 누구에게 열려 있는지 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/policies" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/policies', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/rows/{table}
표 내용 보기 표의 앞부분을 그대로 읽어요. 확인용이며, 조건이 필요하면 run_sql을 쓰세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rows/notes?limit=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rows/notes?limit=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/migrations
마이그레이션 기록 apply_migrations로 적용한 마이그레이션의 버전·이름·적용 시각을 오래된 순으로 돌려줘요. 기록은 프로젝트 스키마의 oneend_migrations 표에 있어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/migrations" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/migrations', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/migrations
마이그레이션 적용 적용하지 않은 마이그레이션을 버전 순으로 하나씩 트랜잭션으로 실행하고 기록해요(적용된 건 건너뛰어요). 실패하면 그것만 되돌리고 멈추며 앞의 것은 남아요. run_sql 대신 쓰면 같은 변경을 다른 프로젝트에도 적용할 수 있어요. supabase/migrations 파일도 그대로 돼요: Supabase 이름(public., auth.uid(), storage., to authenticated)은 이 프로젝트 이름으로 바꿔 실행하고 translated로 알려 줘요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/migrations" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"migrations":[{"version":"20260101000000","name":"my-name","sql":"select 1"}]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/migrations', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"migrations": [
{
"version": "20260101000000",
"name": "my-name",
"sql": "select 1"
}
]
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/migrations/{version}
마이그레이션 기록 지우기 마이그레이션 하나를 적용하지 않은 것으로 되돌려요. 기록만 지우고 그 마이그레이션이 만든 것은 그대로 둬요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/migrations/20260101000000" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/migrations/20260101000000', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/schema
스키마를 SQL로 프로젝트의 스키마(타입, 시퀀스, 표와 제약, 외래 키, 인덱스, 함수, 뷰, 트리거, RLS와 규칙)를 다시 만들 수 있는 SQL로 돌려줘요. 행 데이터와 권한은 들어 있지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/schema" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/schema', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/types/typescript
TypeScript 타입 만들기 프로젝트의 표·뷰·함수·열거형으로 supabase-js의 createClient<Database>()에 넣는 Database 타입을 만들어요. 스키마를 바꾼 뒤 다시 부르세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/types/typescript?schema=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/types/typescript?schema=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/sql/query
SQL 조회 (읽기 전용) 조회 한 문장(SELECT 등)을 읽기 전용으로 실행해요(읽기 권한 토큰도 돼요). 바꾸는 문장은 run_sql을 쓰세요. Vault 비밀 값은 비어 있어요. 문법: https://www.postgresql.org/docs/16/sql-commands.html
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/sql/query" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"sql":"select 1"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/sql/query', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"sql": "select 1"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/sql
SQL 실행 (변경) 데이터나 구조를 바꾸는 SQL(CREATE, INSERT, UPDATE, DELETE 등)을 실행해요. 조회만이면 query_sql을 쓰세요. 문법은 PostgreSQL 16(https://www.postgresql.org/docs/16/sql-commands.html)이에요. 새 표는 접근 규칙이 켜진 채라 규칙을 만들기 전엔 공개 키로 안 보여요. 규칙의 권한 이름은 <ref>_anon, <ref>_authenticated, <ref>_service_role이에요. Supabase SQL(public., auth.uid(), storage., to authenticated)은 이 프로젝트 이름으로 바꿔 실행하고 translated로 알려 줘요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/sql" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"sql":"select 1"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/sql', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"sql": "select 1"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/database
데이터베이스 연결 정보 이 프로젝트 PostgreSQL에 직접 연결할 주소를 봐요: direct(5432, 세션: 마이그레이션 도구·DB 클라이언트)와 pooler(6543, 트랜잭션: 서버리스). 비밀번호는 저장하지 않아 [YOUR-PASSWORD]로 나와요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/database/password
데이터베이스 비밀번호 새로 만들기 직접 연결 비밀번호를 새로 만들어 한 번만 보여 줘요. 이전 비밀번호의 연결은 다음부터 거부되니 confirm에 프로젝트 이름(list_projects의 name)이 필요해요. 이 사용자는 RLS를 거치지 않으니 서버에만 두세요. keep_for_deploys: true면 암호화해 저장하고 서버·미들웨어·함수가 실행될 때 DATABASE_URL·POSTGRES_URL·DIRECT_URL로 받아요(빌드 제외). 배포한 코드가 모든 행을 읽게 되니 사용자가 원할 때만 켜요. 빼면 넘기던 것도 멈춰요. 사용자가 요청할 때만 쓰고, 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/password" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/password', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/mysql
MySQL 데이터베이스 목록 MySQL 데이터베이스(MariaDB 11.4)마다 받는 앱(app, null은 프로젝트 전체), 상태, 크기와 요금제 최대 개수(max)예요. available이 false면 이 서버에 아직 MySQL이 없어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/mysql
MySQL 데이터베이스 만들기 WordPress 같은 MySQL 앱용 데이터베이스와 전용 로그인을 만들어요(보통 1분). app을 주면 그 앱만, 없으면 프로젝트의 앱 모두가 받아요. 서버는 시작할 때 MYSQL_URL·MYSQL_HOST·MYSQL_PORT·MYSQL_USER·MYSQL_PASSWORD·MYSQL_DATABASE와 WORDPRESS_DB_HOST·WORDPRESS_DB_USER·WORDPRESS_DB_PASSWORD·WORDPRESS_DB_NAME을 받아요(빌드 제외). 매일 밤 백업돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/mysql/{name}
MySQL 데이터베이스를 앱에 연결 MySQL 데이터베이스를 받을 앱을 바꿔요. app이 null이면 프로젝트 전체용이 돼요. 앱 하나에는 데이터베이스 하나만 연결돼요. 실행 중인 서버는 다시 시작하거나 다시 배포하면 바뀐 값을 받아요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"app":"owner/repo"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"app": "owner/repo"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/mysql/{name}
MySQL 데이터베이스 지우기 MySQL 데이터베이스와 로그인, 백업을 모두 지워요. 되돌릴 수 없으니 사용자가 요청할 때만 쓰고 confirm에 데이터베이스 이름을 넣으세요. 받던 앱은 다음 시작부터 MYSQL_*를 받지 않아요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/mysql/{name}/connection
MySQL 연결 정보 MySQL 데이터베이스의 주소, 포트, 데이터베이스 이름, 로그인, 비밀번호와 앱이 받는 변수(variables)를 돌려줘요. 주소는 이 서버 안의 앱에서만 닿아요. 비밀번호는 쓰기 권한 토큰에만 보여요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/connection" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/connection', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/mysql/{name}/backups
MySQL 백업 목록 MySQL 데이터베이스의 백업(매일 밤 자동, 직접 만든 것, 복원 직전 것)과 복원 기록을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/backups" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/backups', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/mysql/{name}/backups
MySQL 지금 백업 MySQL 데이터베이스를 지금 백업해요. 플러그인 업데이트나 대량 변경 전에 만드세요. 7일 보관돼요. 매일 밤 백업은 따로 자동으로 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/backups" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/backups', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/mysql/{name}/restore
MySQL 백업으로 복원 MySQL 데이터베이스를 백업 시점으로 되돌려요. 그 뒤 변경은 사라지니 사용자가 요청할 때만 쓰고 confirm에 데이터베이스 이름을 넣으세요. 직전 상태를 백업하니 undo_backup_id로 되돌릴 수 있어요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/restore" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"backup_id":"BACKUP_ID","confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/mysql/my-name/restore', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"backup_id": "BACKUP_ID",
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/extensions
DB 확장 목록 켤 수 있는 PostgreSQL 확장(vector, postgis, citext 등)과 available·enabled·버전이에요. extensions 스키마에 설치되고 SQL에서 vector(1536)처럼 바로 써요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/extensions" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/extensions', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/extensions/{name}
DB 확장 켜기 확장 하나를 켜요(create extension ... with schema extensions). 임베딩 검색은 vector, 지도·거리 계산은 postgis. 목록 밖의 확장은 거절돼요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/extensions/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/extensions/my-name', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/extensions/{name}
DB 확장 끄기 확장을 꺼요. 쓰는 열·인덱스·함수가 남아 있으면 거절돼요. 다른 프로젝트가 쓰면 설치는 남고 이 프로젝트 기록만 지워요(note). pg_trgm·unaccent는 못 꺼요. confirm에 확장 이름이 필요해요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/extensions/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/extensions/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/database/move
전용 데이터베이스로 옮기기 상태 전용 데이터베이스에 있는지(dedicated), 요금제 포함 여부(plan_allows), 옮기는 상태(stopped, last_error)를 봐요. size_bytes가 auto_move_max_bytes보다 크면 move_to_dedicated_database로 요청하세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/move" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/move', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/database/move
전용 데이터베이스로 옮기기 프로젝트를 전용 데이터베이스로 옮기도록 요청해요(콘솔 "지금 옮기기"). 옮기는 동안 쓰기는 멈추고 읽기는 돼요. 직전 상태를 백업하고, 실패하면 그대로예요. Pro부터, 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/move" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/move', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/database/dedicated-disk
전용 디스크 전용 디스크와 Postgres를 봐요: size_gb, 쓴 공간, 한 달 비용, 30일 기록, 하고 있는 요청, 줄이기 제안(shrink). 공용 디스크면 옮기는 기준(threshold_gb)과 지금 크기를 보여 줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/dedicated-disk" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/dedicated-disk', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/database/dedicated-disk
전용 디스크로 옮기기 데이터베이스를 전용 디스크(max(1.2 × 데이터베이스, 20GB))로 옮기도록 요청해요. GB당 월 ₩1,200(75¢)이고, 옮기는 동안 쓰기는 실패해요. Enterprise는 언제든, 다른 유료 요금제는 기준을 넘으면 돼요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/dedicated-disk" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/dedicated-disk', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/database/dedicated-disk/shrink
디스크 줄이기 전용 디스크를 줄여요: 작은 디스크(1.2 × 데이터베이스, 최소 20GB)로 옮기고 원래 것을 지워요. 7일 동안 25% 아래로 쓴 디스크만 돼요(shrink.suggested). 옮기는 동안 쓰기는 실패하고 읽기는 돼요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/dedicated-disk/shrink" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/database/dedicated-disk/shrink', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/realtime
실시간 켠 표 변경을 실시간으로 알리는 표 목록. 여기 없는 표를 구독하면 아무것도 오지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/realtime" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/realtime', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/realtime/{table}
표의 실시간 켜기·끄기 표 하나의 변경 알림을 켜거나 꺼요. 알림도 접근 규칙을 통과한 줄만 가요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/realtime/notes" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/realtime/notes', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
인증과 사용자
GET /api/v1/projects/{ref}/users
서비스 가입자 목록 이 프로젝트 서비스의 가입자예요(플랫폼 계정과 별개). 한 번에 200명까지 오고 total이 전체 인원이에요. has_more가 true면 offset을 올려 다시 부르세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users?limit=1&offset=0" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users?limit=1&offset=0', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/users/{id}/links
로그인 링크 만들기 메일로 가는 링크를 메일 없이 만들어요: invite(없으면 가입자 생성), magiclink, recovery, signup(password 필요). action_link를 열면 그 가입자로 로그인되니 비밀번호처럼 다뤄요: 사용자가 요청할 때만 만들고 그 사람에게만 전하세요. redirect_to는 add_redirect_url로 등록한 주소만 돼요. 소유자·관리자·개발자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/ID/links" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"type":"invite"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/ID/links', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"type": "invite"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/users/{id}
서비스 가입자 바꾸기 가입자 한 명의 이메일, 비밀번호, 이메일 확인, 정지, 메타데이터(합쳐짐)를 바꿔요. 비밀번호를 바꾸거나 정지하면 로그인이 모두 끊겨요. 비밀번호는 10자 이상, 유출된 것은 거절돼요. 사용자가 요청할 때만 쓰세요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"email":"[email protected]","password":"a-long-passphrase","email_confirm":true,"ban_duration":"value","user_metadata":{},"app_metadata":{}}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/ID', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"email": "[email protected]",
"password": "a-long-passphrase",
"email_confirm": true,
"ban_duration": "value",
"user_metadata": {},
"app_metadata": {}
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/users/import
서비스 가입자 한꺼번에 가져오기 다른 서비스(Supabase auth.users 내보내기 등)의 가입자를 한 번에 500명까지 가져와요. id와 bcrypt 비밀번호 해시를 그대로 지켜서 비밀번호를 다시 정하지 않아도 로그인돼요. 목록 전체를 먼저 검사해 틀린 줄 번호를 알려 주고 하나도 가져오지 않아요. 이미 있는 계정은 건너뛰어서 다시 불러도 안전해요. dry_run=true면 검사만 해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/import" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"users":[{"email":"[email protected]","id":"ID","encrypted_password":"value","email_confirmed":"value","user_metadata":"value","app_metadata":"value"}]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/import', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"users": [
{
"email": "[email protected]",
"id": "ID",
"encrypted_password": "value",
"email_confirmed": "value",
"user_metadata": "value",
"app_metadata": "value"
}
]
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/users
서비스 가입자 추가 이 프로젝트의 서비스에 가입자를 하나 만들어요. 비밀번호는 10자 이상이어야 해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"email":"[email protected]","password":"a-long-passphrase"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"email": "[email protected]",
"password": "a-long-passphrase"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/providers
소셜 로그인 설정 보기 로그인할 수 있는 제공자를 모두 봐요(설정 전이면 configured: false). 직접 등록한 custom:<이름>은 custom 항목(주소, scopes, 필드 매핑)과 함께 나와요. callback_url은 제공자 콘솔에 붙여 넣을 주소예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/auth/providers/{provider}
소셜 로그인 켜기 제공자 하나의 클라이언트 ID와 시크릿을 저장하고 켜요(시크릿은 암호화해 저장하고 뒤 네 자리만 보여요). 먼저 제공자 콘솔에 list_auth_providers의 callback_url을 등록하세요. ID만 고치려면 client_secret을 빈 문자열로 둬요. provider를 custom:<이름>으로 주면 목록에 없는 OAuth 2.0·OpenID Connect 제공자를 등록해요: issuer(OIDC) 또는 authorize_url·token_url(·userinfo_url)이 필요하고, scopes와 claims(id·email·email_verified·name·avatar·phone이 응답의 어느 필드인지, 점 경로)를 줄 수 있어요. 앱에서는 signInWithOAuth({ provider: "custom:<이름>" })로 부르고, 로그인 직후 세션에 provider_token이 한 번 와요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers/google" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"client_id":"CLIENT_ID","client_secret":"CLIENT_SECRET","enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers/google', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"client_id": "CLIENT_ID",
"client_secret": "CLIENT_SECRET",
"enabled": true
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/auth/providers/{provider}
소셜 로그인 껐다 켜기 저장된 자격증명은 두고 제공자만 껐다 켜요. 다시 켤 때 시크릿을 새로 넣지 않아도 돼요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers/google" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers/google', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/auth/providers/{provider}
소셜 로그인 지우기 제공자 설정을 자격증명째로 지워요(다시 쓰려면 시크릿을 새로 받아야 해요). 잠시 끄려면 set_auth_provider_enabled를 쓰세요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers/google" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/providers/google', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/redirect-urls
로그인 후 돌아갈 주소 목록 로그인이 끝난 사람을 돌려보낼 수 있는 주소예요. 여기 없는 주소로는 돌려보내지 않아요. 로그인은 되는데 아무 데도 안 간다면 여기부터 보세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/redirect-urls" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/redirect-urls', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/auth/redirect-urls
돌아갈 주소 추가 주소 하나를 허용 목록에 넣어요. 스킴·호스트·포트가 모두 같아야 하고 경로는 보지 않아서 https://app.example.com/callback을 넣으면 https://app.example.com이 저장돼요. 모바일 앱은 자기 스킴(co.example.app://callback)을 넣으면 co.example.app://callback이 저장돼요. 점이 들어간 앱 스킴만 받아요. 응답에 실제로 저장된 목록이 와요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/redirect-urls" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"url":"https://example.com/hook"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/redirect-urls', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"url": "https://example.com/hook"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/auth/redirect-urls
돌아갈 주소 제거 허용 목록에서 주소 하나를 빼요. list_redirect_urls가 돌려준 그대로 넣으세요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/redirect-urls" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"url":"https://example.com/hook"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/redirect-urls', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"url": "https://example.com/hook"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/sms
문자 로그인 설정 보기 전화번호 인증번호 로그인에 쓰는 문자 계정을 봐요: 제공자, 발신 번호, 허용 국가, 인증번호 길이·유효 시간, 시간당 한도. 자격증명은 뒤 네 자리만 보여요. platform_available이면 플랫폼 계정(1건 ₩100, 국내만)도 돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sms" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sms', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/auth/sms
문자 로그인 설정 문자 계정을 저장하고 켜요. 직접 계약한 제공자면 key·secret·account와 등록한 발신 번호가 필요해요(Solapi: API Key·API Secret, NHN Cloud: App Key·Secret Key, Aligo: API Key·User ID(account), Twilio·Twilio Verify: Account SID(account)·Auth Token(secret), MessageBird·Textlocal: key, Vonage: key·secret. MessageBird·Textlocal·Vonage는 11자 이하 발신자 ID, Twilio Verify는 VA로 시작하는 Verify Service SID도 돼요). 나머지 설정은 update_auth_config의 SMS_* 키로 바꿔요. 비운 자격증명은 그대로예요. allowed_countries는 기본 82(한국)만이고, 모르는 나라를 넣으면 해외 유료 번호 문자 사기에 노출돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sms" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"provider":"platform"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sms', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"provider": "platform"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/auth/sms
문자 로그인 지우기 문자 계정 설정을 자격증명째로 지워요. 이후 전화번호 로그인은 phone_provider_disabled로 거부돼요. 잠시 끄려면 set_sms_settings에 enabled: false를 주세요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sms" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sms', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/smtp
SMTP 설정 보기 인증 메일을 보내는 SMTP 서버와 보내는 사람을 봐요. 비밀번호는 password_hint(뒤 네 자리)만 와요. configured가 false거나 last_error가 있으면(그 서버가 거부) 플랫폼 주소로 보내요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/auth/smtp
SMTP 설정 인증 메일을 이 프로젝트의 SMTP 서버와 보내는 사람으로 보내요. 처음엔 sender_email, host, username, password가 필요하고, 그 뒤엔 바꿀 값만 줘요(password를 비우면 그대로). 공인 주소와 TLS(465 또는 STARTTLS)가 필요해요. 서버가 거부하면 플랫폼 주소로 대신 보내고 last_error에 남겨요. 저장 후 test_smtp_settings로 확인하세요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"sender_email":"value","sender_name":"value","host":"value","port":25,"username":"value","password":"a-long-passphrase","minimum_interval_seconds":0,"rate_limit_per_hour":1,"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"sender_email": "value",
"sender_name": "value",
"host": "value",
"port": 25,
"username": "value",
"password": "a-long-passphrase",
"minimum_interval_seconds": 0,
"rate_limit_per_hour": 1,
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/auth/smtp
SMTP 설정 지우기 SMTP 설정을 비밀번호째로 지워요. 이후 인증 메일은 플랫폼 발신 주소로 나가요. 잠시 멈추려면 set_smtp_settings에 enabled: false를 주세요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/auth/smtp/test
SMTP 시험 메일 보내기 저장된 SMTP 서버로 시험 메일 한 통을 보내요. 플랫폼으로 대신 보내지 않아서, 실패하면 그 서버가 준 이유가 그대로 나와요. to를 빼면 호출한 사람의 주소로 보내요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp/test" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"to":"https://example.com"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/smtp/test', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"to": "https://example.com"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/templates
이메일 템플릿 보기 인증 메일 여섯 종류(confirmation, invite, magic_link, recovery, email_change, reauthentication)의 제목과 HTML 본문이에요. custom이 false면 기본 문구(한국어·영어·일본어)를 써요. type을 주면 그 하나만 봐요. 변수는 Supabase와 같아요: {{ .ConfirmationURL }}, {{ .Token }}, {{ .TokenHash }}, {{ .SiteURL }}, {{ .Email }}, {{ .NewEmail }}, {{ .RedirectTo }}, {{ .Data.<key> }}.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/templates/{type}
이메일 템플릿 보기 인증 메일 여섯 종류(confirmation, invite, magic_link, recovery, email_change, reauthentication)의 제목과 HTML 본문이에요. custom이 false면 기본 문구(한국어·영어·일본어)를 써요. type을 주면 그 하나만 봐요. 변수는 Supabase와 같아요: {{ .ConfirmationURL }}, {{ .Token }}, {{ .TokenHash }}, {{ .SiteURL }}, {{ .Email }}, {{ .NewEmail }}, {{ .RedirectTo }}, {{ .Data.<key> }}.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/auth/templates/{type}
이메일 템플릿 저장 한 종류의 제목과 HTML 본문을 정해요(Supabase 템플릿 그대로 돼요). 제목은 한 줄, {{ if }} 같은 문법은 거부돼요. reauthentication은 아직 보내지 않아요. 저장 전에 preview_email_template로 확인하세요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"subject":"value","body":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"subject": "value",
"body": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/auth/templates/{type}
이메일 템플릿 되돌리기 한 종류의 템플릿을 지우고 기본 문구(한국어·영어·일본어)로 돌아가요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/auth/templates/{type}/preview
이메일 템플릿 미리보기 예시 값을 넣어 메일이 어떻게 보일지 돌려줘요(제목, HTML, 텍스트). subject와 body를 주면 저장하지 않고 그 내용을, 빼면 저장된 템플릿이나 기본 문구를 보여 줘요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation/preview" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"subject":"value","body":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/templates/confirmation/preview', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"subject": "value",
"body": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/auth/sso
SAML SSO 보기 이 프로젝트에 등록된 SAML IdP와 이메일 도메인, 그리고 IdP에 넣어야 하는 두 주소(acs_url, entity_id)를 봐요. 앱에서는 supabase.auth.signInWithSSO({ domain })로 로그인해요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sso" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sso', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/auth/sso/{id}
SAML SSO 지우기 IdP 하나를 지워요. 그 IdP로 가입한 사용자 계정은 남지만 더는 SSO로 로그인할 수 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sso/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/sso/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/auth/anonymous
익명 로그인 켜기·끄기 이메일 없이 바로 세션을 받는 익명 로그인을 켜거나 꺼요. 지금 상태는 list_auth_providers의 anonymous_sign_in이에요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/anonymous" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/auth/anonymous', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/users/{id}
가입자 삭제 프로젝트의 가입자 한 명을 지워요. 되돌릴 수 없어요. id는 list_users가 돌려준 값이에요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 그 가입자의 이메일(또는 id)을 그대로 넣어야 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/users/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
파일 저장소
POST /api/v1/projects/{ref}/buckets/{bucket}/empty
버킷 비우기 버킷 안의 파일을 모두 지워요. 버킷은 남아요. 되돌릴 수 없으니 사용자가 분명히 요청했을 때만 쓰고, confirm에 버킷 이름을 그대로 넣어야 해요. removed가 지운 파일 수예요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/empty" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/empty', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/buckets/{bucket}/objects
파일 목록 버킷 안의 한 폴더를 봐요: 하위 폴더와 파일의 이름, 크기, 형식. prefix로 폴더를 고르고(예: avatars/2024/), search로 이름을 찾아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/objects?prefix=value&search=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/objects?prefix=value&search=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/buckets/{bucket}/objects
파일 올리기 파일 하나를 버킷에 올려요(2MB까지). 바이너리는 encoding: base64로 보내요. 같은 이름은 거절하고 upsert: true면 덮어써요. 버킷의 크기·형식 제한을 따라요. 더 크면 create_upload_url을 쓰세요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/objects" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"content":"value","name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/objects', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"content": "value",
"name": "my-name"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/buckets/{bucket}/object
파일 내려받기 파일 하나의 내용을 돌려줘요(2MB까지). 텍스트는 utf-8로, 바이너리는 base64로 줘요. 더 큰 파일은 create_signed_url로 주소를 만들어 받으세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/object?name=my-name&encoding=utf-8" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/object?name=my-name&encoding=utf-8', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/buckets/{bucket}/object
파일 삭제 버킷에서 파일 하나를 지워요. 되돌릴 수 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/object?name=my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/object?name=my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/buckets/{bucket}/upload-urls
파일 올리기 주소 만들기 2MB보다 큰 파일 하나를 올릴 주소를 만들어요(내용은 이 도구로 보내지 않아요). 받은 url에 파일 바이트를 그대로 PUT하고 content-type을 넣으세요(example의 curl). 주소는 2시간 동안 그 이름 하나에만 써요. max_bytes를 넘거나 allowed_mime_types에 없으면 거절돼요: 더 크면 blackwall://storage의 이어 올리기(TUS)를 쓰세요. 공개 버킷이면 public_url이 공개 주소예요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/upload-urls" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/upload-urls', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/buckets/{bucket}/signed-urls
서명 주소 만들기 비공개 버킷의 파일 하나를 정해진 시간 동안 누구나 받을 수 있는 주소를 만들어요(기본 1시간, 최대 7일). 주소를 가진 사람은 로그인 없이 받으니 필요한 만큼만 쓰세요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/signed-urls" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value/signed-urls', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/buckets/{bucket}
버킷 설정 바꾸기 버킷의 공개 여부, 파일 하나의 최대 크기, 받을 형식을 바꿔요. 준 것만 바뀌고 나머지는 그대로예요. 공개로 바꾸면 그 안의 파일을 누구나 받을 수 있게 되니 사용자가 분명히 요청했을 때만 쓰세요. 이미 있는 파일은 그대로 둬요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"public":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"public": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/buckets/{bucket}
버킷 삭제 빈 버킷을 지워요. 파일이 남아 있으면 거절하니 먼저 empty_bucket으로 비우세요. 되돌릴 수 없어요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 버킷 이름을 그대로 넣어야 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets/value', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/buckets
버킷 목록 파일 저장소의 버킷과 각각의 파일 수·용량을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/buckets
버킷 만들기 공개 버킷은 누구나 읽을 수 있고, 비공개 버킷은 올린 사람만 읽어요. file_size_limit와 allowed_mime_types로 파일 하나의 크기와 받을 형식을 처음부터 정할 수 있어요(나중에는 update_bucket).
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"id":"ID"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/buckets', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"id": "ID"
}),
})
const result = await response.json()
배포와 저장소
POST /api/v1/projects/{ref}/deployments/sources/upload-urls
배포할 압축 파일 올리기 주소 만들기 3MB 넘는 사이트를 저장소 없이 배포할 때, 압축 파일(.zip, .tar, .tar.gz) 하나를 올릴 주소를 만들어요. url에 그대로 PUT하면(토큰 없이, example의 curl) source가 오니 deploy_source를 부르세요. 주소는 1시간, max_bytes까지예요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/sources/upload-urls" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/sources/upload-urls', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/deployments/sources
배포할 파일 올리기 저장소 없이 배포할 파일을 압축 파일(.zip, .tar, .tar.gz) 하나로 본문에 그대로 보내요. 내용의 해시(digest)로 저장되고, 배포는 그다음 POST /deployments에 {"source": "<digest>"}로 만들어요. 한 번 올린 것을 프리뷰와 프로덕션에 같은 바이트로 배포할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/sources" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/octet-stream" \
--data-binary @file
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/sources', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/octet-stream' },
body: bytes,
})
const result = await response.json()
POST /api/v1/projects/{ref}/deployments
배포 만들기 본문에 무엇이 있느냐에 따라 세 가지예요. source는 POST /deployments/sources로 올린 압축 파일의 digest, files(또는 files_base64)는 경로별 파일 내용, 둘 다 없으면 app·branch·commit으로 저장소의 커밋을 빌드해요. target이 production이면 프로덕션, 아니면 프리뷰예요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"source":"export default async () => new Response(\"ok\")","files":"value","files_base64":"value","app":"owner/repo","branch":"main","commit":"0123456789abcdef0123456789abcdef01234567","wait":0,"block_on_advisors":true,"prebuilt":true,"target":"preview","message":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"source": "export default async () => new Response(\"ok\")",
"files": "value",
"files_base64": "value",
"app": "owner/repo",
"branch": "main",
"commit": "0123456789abcdef0123456789abcdef01234567",
"wait": 0,
"block_on_advisors": true,
"prebuilt": true,
"target": "preview",
"message": "value"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/deployments/{id}/redeploy
다시 배포 배포와 같은 커밋을 같은 환경에 다시 빌드해요. 환경 변수를 나중에 넣었거나 패키지 저장소가 잠시 죽어 실패한 빌드에 써요. 프로덕션은 소유자·관리자만 돼요. 답에 새 주소와 보안 점검(advisors)이 와요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/redeploy" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/redeploy', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/deployments/{id}/rollback
프로덕션 되돌리기 프로덕션 주소를 예전에 서비스했던 프로덕션 배포로 바로 돌려놓아요. 다시 빌드하지 않고, 몇 초 안에 바뀌어요. 커스텀 도메인도 함께 따라가요. 그 뒤 프로덕션은 보류돼요(production_held): 새 프로덕션 빌드는 만들어지지만 promote_deployment로 올리기 전까지 나가지 않아요. 소유자·관리자만 할 수 있어요. 답에 그 배포의 url과 production_url이 와요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/rollback" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/rollback', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/deploy-hooks
배포 훅 목록 배포 훅과 그 주소를 봐요. 주소로 POST하면 그 브랜치의 최신 커밋을 빌드하니 주소 자체가 비밀이에요. 읽기 권한 토큰에는 주소의 끝 네 자리만 보여줘요(secret_hidden). 쓰기 권한 토큰이면 전부 보여요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deploy-hooks" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deploy-hooks', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/deploy-hooks
배포 훅 만들기 push 없이 다시 빌드하게 하는 주소를 만들어요. CMS에서 글을 발행하거나 예약 작업이 돌 때 부르게 해요. 프로덕션 브랜치의 훅은 소유자·관리자만 만들 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deploy-hooks" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"app":"owner/repo","branch":"main"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deploy-hooks', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"app": "owner/repo",
"branch": "main"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/deploy-hooks/{id}
배포 훅 삭제 배포 훅을 지워요. 그 주소를 부르던 곳에서는 더 배포가 일어나지 않아요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deploy-hooks/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deploy-hooks/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/deployments/deleted
최근 삭제한 배포 3일 안에 삭제된 배포(직접 삭제했거나 보관 기간이 지난 것)와 되돌릴 수 있는 마감(restorable_until)을 돌려줘요. 그동안 그 배포의 주소는 410으로 답해요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/deleted" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/deleted', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/deployments/{id}
배포 삭제 배포 하나를 삭제해요(서비스 중·빌드 중인 배포는 안 돼요). 3일 동안 restore_deployment로 되돌릴 수 있고, 그 뒤 파일과 빌드 로그를 지워요. 프로덕션은 프로젝트 관리자, 나머지는 개발자 이상이 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/deployments/{id}/restore
배포 되돌리기 3일 안에 삭제된 배포를 되돌려요. 주소가 다시 응답하고 롤백·승격도 할 수 있어요. 프로덕션 배포는 프로젝트 관리자, 나머지는 개발자 이상이 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/restore" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/restore', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/deployments
배포 목록 최근 배포를 최신순으로 봐요: 상태(queued, building, ready, error), 환경, 주소, 브랜치, 커밋, 실패 이유. 삭제한 배포는 빠져요(list_deleted_deployments). next_before가 있으면 before에 넣어 다음 쪽을 봐요. url은 그 배포만의 dpl- 주소, production_url·preview_url은 프로덕션·브랜치 주소예요. preview_protection은 프리뷰를 누가 여는지예요(members 기본, password, off). 프로덕션 주소는 늘 공개지만, 보호가 켜지면 dpl- 주소는 보호돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments?limit=1&before=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments?limit=1&before=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/deployments/{id}
배포 하나와 빌드 로그 배포 하나의 상태, 주소, 빌드 로그 끝부분을 봐요(실패 이유는 대개 로그 끝). 환경 변수 값은 가려져요. 주소 필드는 list_deployments와 같아요. wait(초)를 주면 빌드가 끝날 때까지 기다려요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID?tail=1&wait=0" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID?tail=1&wait=0', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/branch-previews
브랜치 미리보기 보기 이 프로젝트가 속한 조직에서 프로덕션 브랜치가 아닌 브랜치에 푸시할 때 미리보기를 빌드하는지 봐요(branch_previews). false면 프로덕션 브랜치(보통 main)에 들어온 것만 빌드해요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branch-previews" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branch-previews', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/branch-previews
브랜치 미리보기 바꾸기 조직 전체에서 브랜치 푸시마다 미리보기를 빌드할지 정해요. false면 프로덕션 브랜치(보통 main)에 들어온 것만 빌드하고, 건너뛴 푸시는 배포 기록에 건너뜀으로 남아요. redeploy, 직접 올린 배포, 배포 훅은 그대로 빌드해요. 이 조직의 모든 프로젝트에 적용돼요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branch-previews" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branch-previews', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/preview-protection
프리뷰 보호 보기 프로덕션이 아닌 배포(브랜치 프리뷰, 배포마다의 주소)를 누가 열 수 있는지 봐요: off, members(조직 멤버만), password. 보호하는 주소(scope), 로그인 없이 들이는 IP(trusted_ips), 그냥 통과시키는 경로(options_paths), 우회 키(bypass_secrets, 값은 끝 네 글자만), 공유 링크(share_links)도 함께 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/preview-protection" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/preview-protection', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/preview-protection
프리뷰 보호 바꾸기 프리뷰를 누가 여는지 바꿔요: members(로그인한 조직 멤버), password(처음 켤 때 8자 이상 password 필요), off(누구나). 프로덕션 주소와 연결한 도메인은 늘 공개예요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/preview-protection" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"mode":"off"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/preview-protection', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"mode": "off"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/apps
연결된 저장소와 빌드 설정 배포하는 저장소마다 프로덕션 브랜치, root_directory, framework(null이면 자동 감지), build_command·output_directory·install_command(null이면 프리셋 기본값)를 봐요. detected_framework는 최근 빌드가 쓴 것, frameworks는 고를 수 있는 프리셋이에요. 저장소는 첫 push 때 생겨요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/apps" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/apps', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/apps/{name}
앱 삭제 프로젝트의 앱 하나를 지워요(모노레포에서 폴더를 없앤 앱). 주소는 바로 내려가고, 진행 중인 빌드는 취소되고, 배포는 복원 없이 지워져 파일이 몇 분 안에 사라져요. 저장소에 폴더가 남아 있어도 다시 빌드하지 않아요. 되돌릴 수 없어요. 프로젝트의 기본 사이트, 도메인이 연결된 앱, 디스크가 있는 앱은 거절하고 먼저 할 일을 알려줘요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 앱 이름을 그대로 넣어야 해요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/apps/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/apps/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/apps/{name}
빌드 설정 바꾸기 저장소 하나의 프로덕션 브랜치, 빌드할 폴더, 프리셋, 빌드·출력·설치 명령을 바꿔요. 모노레포면 root_directory에 앱 폴더(예: apps/web)를 넣어요. 뺀 값은 그대로, null은 자동 감지, 빈 문자열 명령은 그 단계를 건너뛰어요. blackwall.json 값이 있으면 그걸 써요. 다음 배포부터 적용되고, port만 1분 안에 서버를 다시 시작해 적용해요. 소유자·관리자만 돼요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/apps/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"production_branch":"main","root_directory":".","run_as":"platform","port":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/apps/my-name', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"production_branch": "main",
"root_directory": ".",
"run_as": "platform",
"port": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/env
환경 변수 보기 배포한 앱이 빌드·실행 때 받는 환경 변수예요. 같은 이름이 production과 preview에 따로 있을 수 있어요. 민감한 값은 value_hint(뒤 네 자리)만 줘요. readable이 false면 빌드에서 빠지니 다시 저장하세요. automatic은 저장하지 않아도 들어가는 변수예요(SUPABASE_URL, NEXT_PUBLIC_SUPABASE_URL, SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, SUPABASE_SERVICE_ROLE_KEY). available_in은 들어가는 곳으로, SUPABASE_SERVICE_ROLE_KEY는 실행(runtime)에만 들어가요. 같은 이름으로 저장한 값이 먼저이고 빌드에도 들어가요(overridden_in).
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/env" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/env', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/env
환경 변수 저장 환경 변수를 저장해요. variables로 하나씩, 또는 dotenv에 .env 내용을 통째로 줘요. 같은 이름은 덮어쓰고, 하나라도 틀리면 아무것도 저장하지 않아요. 단, dotenv에서 플랫폼이 정하는 이름의 줄은 건너뛰고 skipped에 알려 줘요. PORT, HOST, HOSTNAME, HOME과 BLACKWALL_로 시작하는 이름은 못 써요. CI는 빌드에 기본 1이고, 직접 정하면(CI=false 등) 그 값을 써요. 다음 배포부터 적용돼요. sensitive를 빼면 비밀 같은 이름(API_KEY, STRIPE_SECRET, DATABASE_URL 등)은 민감한 값으로 저장돼 다시 못 읽어요(sensitive_keys). production 값은 소유자·관리자만 바꿔요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/env" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"targets":["production"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/env', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"targets": [
"production"
]
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/env/{target}/{key}
환경 변수 삭제 환경 변수 하나를 production이나 preview 중 한 곳에서 지워요. 민감한 값이었다면 되살릴 수 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/env/production/API_URL?app=owner%2Frepo&branch=main" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/env/production/API_URL?app=owner%2Frepo&branch=main', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/git
Git 연결 배포하는 저장소(connected), 연결한 GitHub 계정(github_accounts), 비공개 저장소를 받을 방법(토큰 끝 네 글자, GitHub App 설치), GitHub 저장소마다 검사를 One Server에서 실행하는지(checks_on_server: available, enabled, state, permission_url, workflows_using)를 봐요. 비공개 저장소 빌드가 받기에서 실패하면 여기부터 보세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/git/tokens/{provider}
저장소 토큰 저장 비공개 저장소를 받을 접근 토큰을 저장해요(읽기 권한이면 충분해요). 암호화해 저장하고 다시 보여 주지 않아요. 자체 GitLab이면 gitlab_base를 넣으세요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/tokens/github" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"token":"ghp_xxxxxxxxxxxxxxxxxxxx"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/tokens/github', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"token": "ghp_xxxxxxxxxxxxxxxxxxxx"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/git/tokens/{provider}
저장소 토큰 삭제 저장한 토큰을 지워요. 연결한 GitHub App 설치는 그대로 둬요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/tokens/github" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/tokens/github', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/git/repos
저장소 추가 첫 push 전에 저장소를 이 프로젝트에 붙여요. 그러면 push가 이 프로젝트로 오고 create_deploy_hook도 쓸 수 있어요. repo는 owner/name(GitLab은 group/name)이에요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/repos" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"provider":"github","repo":"owner/repo"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/repos', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"provider": "github",
"repo": "owner/repo"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/git/github-app
GitHub 계정 연결 해제 이 프로젝트와 GitHub 계정(App 설치)의 연결을 해제해요. installation을 주면 그 계정만, 비우면 모두예요. 저장한 토큰과 GitHub의 App 설치는 그대로예요. 다시 연결은 콘솔에서만 돼요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/github-app" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/github-app', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/git/github-app/{installation}
GitHub 계정 연결 해제 이 프로젝트와 GitHub 계정(App 설치)의 연결을 해제해요. installation을 주면 그 계정만, 비우면 모두예요. 저장한 토큰과 GitHub의 App 설치는 그대로예요. 다시 연결은 콘솔에서만 돼요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/github-app/value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/github-app/value', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/git/importable
가져올 저장소 찾기 GitHub App이 볼 수 있는 저장소를 최근 푸시 순으로 50개까지 봐요. query를 주면 전체에서 찾고, 방금 추가했다면 refresh: true. 계정이 여럿이면 installation으로 골라요. 소유자·관리자만 돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/importable?query=value&installation=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/importable?query=value&installation=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/git/import
저장소 가져오기 콘솔의 [연결하고 배포]와 같아요. 저장소를 연결하고 프로덕션 브랜치(비우면 기본 브랜치)의 최신 커밋으로 바로 배포해요. 빌드 설정과 환경 변수(dotenv)를 첫 빌드 전에 함께 저장해요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/import" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"repo":"owner/repo","branch":"main","root_directory":".","installation":1,"dotenv":"API_URL=https://example.com","sensitive":true,"app":"owner/repo"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/import', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"repo": "owner/repo",
"branch": "main",
"root_directory": ".",
"installation": 1,
"dotenv": "API_URL=https://example.com",
"sensitive": true,
"app": "owner/repo"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/git/checks/{repo}/{repo}
검사를 One Server에서 실행 연결한 GitHub 저장소의 GitHub Actions 검사를 One Server의 머신에서 실행하도록 켜거나 꺼요. 콘솔의 Git 연결 → [검사를 One Server에서 실행]과 같아요. 켜면 저장소 변수 POOL_RUNNER를 저장하고, 작업이 runs-on: ${{ vars.POOL_RUNNER || 'ubuntu-latest' }}를 쓰면 One Server에서 돌아요. 끄면 변수를 지워 GitHub의 머신으로 돌아가요. state가 needs_permission이면 permission_url에서 GitHub App의 새 권한을 승인하면 저절로 켜져요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/checks/owner%2Frepo/owner%2Frepo" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/checks/owner%2Frepo/owner%2Frepo', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/git/repos/{name}
저장소 연결 해제 저장소 연결을 해제해 푸시해도 배포하지 않아요. 서비스 중인 배포, 배포 기록, 빌드 설정, 환경 변수는 그대로이고 import_repository로 다시 연결돼요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/repos/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/git/repos/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/volumes
볼륨 목록 앱의 볼륨(서버를 다시 시작하거나 새로 배포해도 남는 디스크)과 백업, 요금제가 허용하는 합계(max_gb)와 지금 쓰는 양(used_gb), 앱마다 서버가 듣는 포트(apps[].listens_on)를 돌려줘요. 볼륨은 프로덕션 서버에만 붙어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/volumes
볼륨 만들기 앱의 프로덕션 서버 mount_path에 볼륨을 붙여요(WordPress는 /var/www/html). 크기가 상한이고 /etc·/usr 같은 시스템 경로는 안 돼요. 1분 안에 서버가 다시 시작해요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"app":"owner/repo","mount_path":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"app": "owner/repo",
"mount_path": "value"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/volumes/{id}
볼륨 늘리기 볼륨을 더 크게 해요. 서버를 멈추지 않고 늘리고, 줄일 수는 없어요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"size_gb":1}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"size_gb": 1
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/volumes/{id}
볼륨 지우기 볼륨과 그 파일, 백업을 모두 지우고 프로덕션 서버를 볼륨 없이 다시 시작해요. 되돌릴 수 없으니 사용자가 요청할 때만 쓰고 confirm에 mount_path를 넣으세요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/volumes/{id}/backups
볼륨 백업 볼륨의 파일을 지금 묶어 30일 동안 보관해요. 몇 분 안에 끝나고, list_volumes의 backups에 나타나요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID/backups" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID/backups', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/volumes/{id}/restore
볼륨 복원 볼륨의 지금 파일을 백업의 파일로 바꿔요. 백업 뒤에 바뀐 파일은 사라지지만, 바꾸기 전에 지금 파일을 7일 동안 백업해 두니 그 백업으로 되돌릴 수 있어요. 사용자가 요청했을 때만 쓰고, 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID/restore" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"backup_id":"BACKUP_ID"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/volumes/ID/restore', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"backup_id": "BACKUP_ID"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/server-memory
서버 메모리 서버 배포의 메모리(MB)·CPU 수, 요금제 최대값, 1GB·시간 요금과 한 달 금액이에요. 프로덕션과 브랜치 서버는 늘 켜져 있어(최소 1대) 그 금액이 서버 하나의 한 달 요금이에요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server-memory" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server-memory', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/server-memory
서버 메모리 바꾸기 서버 배포(Node 서버, 작업자)의 메모리를 512·1024·2048·4096MB 중에서 골라요(1024MB 넘으면 CPU 2개). 쓴 만큼 runtime_gb_hour로 사용량을 재요. 1분 안에 새 크기로 다시 시작해요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server-memory" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"memory_mb":512}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server-memory', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"memory_mb": 512
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/gpu
GPU 작업과 서버 GPU 작업(최근 50개), 서버, 저장소, 장비별 시간 요금과 저장소 1GB·월 요금, 고를 수 있는 지역·데이터센터, 조직의 동시 GPU 한도와 지금 쓰는 수예요. 무료 요금제는 GPU를 못 써요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/gpu/jobs
GPU 작업 만들기 GPU를 빌려 공개 이미지에서 명령을 끝까지 실행해요. 끝나거나 max_minutes가 지나면 반납하고, 쓴 초만큼(이미지 받는 시간 포함) 청구해요. 결과는 바깥에 올려야 남아요. 이미지에 curl, wget, python3 중 하나가 필요해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/jobs" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"gpu":"rtx4090","image":"value","command":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/jobs', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"gpu": "rtx4090",
"image": "value",
"command": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/gpu/jobs/{id}
GPU 작업 보기 GPU 작업 하나의 상태, 쓴 시간과 금액, 종료 코드, 출력의 마지막 부분(최대 64KB)을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/jobs/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/jobs/ID', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/gpu/jobs/{id}/cancel
GPU 작업 멈추기 GPU 작업을 멈춰요. 아직 시작 전이면 시작하지 않고, 실행 중이면 GPU를 돌려줘요. 돌려줄 때까지 쓴 시간은 청구돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/jobs/ID/cancel" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/jobs/ID/cancel', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/gpu/servers
GPU 서버 만들기 공개 이미지로 모델을 띄울 GPU 서버를 만들어요. https://<ref>.<zone>/gpu/v1/servers/<name>/ 에 secret 키로 부르면 꺼져 있을 땐 켜고(그동안 503) 요청을 넘겨요. idle_minutes 동안 요청이 없으면 꺼요(0은 계속 켬). 켜기 시작부터 꺼질 때까지(이미지 받기 포함) 초 단위로 청구해요. 서버는 x-oneend-gpu-token 헤더 값을 ONEEND_GPU_TOKEN으로 받아요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/servers" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","gpu":"rtx4090","image":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/servers', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"gpu": "rtx4090",
"image": "value"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/gpu/servers/{name}/stop
GPU 서버 멈추기 GPU 서버를 지금 멈춰요. 꺼질 때까지 쓴 시간은 청구돼요. 다음 요청 때 다시 켜져요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/servers/my-name/stop" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/servers/my-name/stop', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/gpu/servers/{name}
GPU 서버 지우기 GPU 서버를 지워요. 켜져 있으면 먼저 멈춘 뒤 지워요. 되돌릴 수 없으니 confirm에 GPU 서버 이름을 그대로 넣어야 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/servers/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/servers/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/gpu/volumes
GPU 저장소 만들기 모델·데이터를 남길 GPU 저장소를 한 데이터센터에 만들어요(작업·서버의 /workspace에 붙어요). 쓰지 않아도 1GB·월 요금이 청구되고, 이걸 쓰면 그 데이터센터에서만 GPU를 빌려요. 유료 요금제만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/volumes" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","datacenter":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/volumes', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"datacenter": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/gpu/volumes/{name}
GPU 저장소 지우기 GPU 저장소와 그 안의 파일을 모두 지워요. 쓰는 작업이나 서버가 있으면 지우지 않아요. 되돌릴 수 없어요. 지울 때까지의 저장 요금은 청구돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/volumes/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/gpu/volumes/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/concurrent-builds
동시 빌드 이 프로젝트의 빌드가 한꺼번에 몇 개까지 도는지예요. null이면 빌더가 허락하는 만큼 돌아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/concurrent-builds" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/concurrent-builds', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/concurrent-builds
동시 빌드 바꾸기 이 프로젝트의 빌드가 한꺼번에 몇 개까지 돌지 1~20으로 정하거나, null로 한도를 없애요. 넘는 빌드는 대기열에서 기다리고, 기다리는 동안은 청구되지 않아요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/concurrent-builds" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"concurrent_builds":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/concurrent-builds', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"concurrent_builds": "value"
}),
})
const result = await response.json()
함수
GET /api/v1/projects/{ref}/functions
함수 목록 배포한 함수와 각 호출 주소, 공개 여부를 봐요. egress는 외부 요청이 켜졌는지, outbound_requests_per_minute은 함수·pg_net·HTTP 작업이 함께 쓰는 분당 외부 요청 한도예요(자기 API 호출은 세지 않아요).
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/functions/{name}
함수 코드 보기 배포된 함수의 코드와 버전을 봐요. 고치기 전에 먼저 읽으세요. deploy_function이 "building"으로 답했으면 build.status(building·deployed·failed)와 build.error를 확인해요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/functions/{name}
함수 배포 함수 하나를 배포해요. 같은 이름이 있으면 통째로 바꾸고 다음 호출부터 새 코드가 돌아요. 코드는 TypeScript 파일 하나로, export default로 (request, { sql }) => 응답 을 내보내요. request에는 method, headers, claims(role: anon·authenticated·service_role, 키 없이 부른 공개 함수는 null), text(), json()이 있어요. sql(text, values)은 service_role 권한으로 한 문장을 실행해 행 배열을 돌려줘요. 응답은 객체(JSON), 문자열, { status, headers, body } 중 하나예요. npm 패키지는 dependencies({"zod":"^3.23.8"})나 package_json(문자열)으로 보내요. 배포할 때 설치해 ESM 파일 하나로 묶어요(5MB까지, 설치 스크립트 실행 안 함, 네이티브 모듈 불가). 40초 안에 안 끝나면 status "building"으로 답하고 이어서 배포해요: get_function으로 build.status가 deployed나 failed가 될 때까지 확인하세요. 여러 파일은 files({"lib/util.ts": "..."})로 보내고 상대 경로로 import해요. 폴더째 보내려면 source를 비우고 files에 index.ts까지 넣으세요. ../_shared/cors.ts 같은 옆 폴더 파일은 files에 "../_shared/cors.ts"로 넣어요. deno.json·import_map.json의 imports와 npm:·jsr:·URL import(npm:zod@3, https://esm.sh/…, https://deno.land/[email protected]/http/server.ts 등)도 돼요. 모두 배포할 때 받아 묶고(주소와 SHA-256은 get_function의 remote_imports, deno.lock이 있으면 맞아야 해요) 실행 중에는 받지 않아요. 호출 하나는 150초까지예요(set_function_limits로 바꿔요). 네트워크는 기본으로 꺼져 있어요(set_function_egress). 호출한 사람의 Authorization 헤더가 그대로 들어오니 createClient(url, anonKey, { global: { headers: { Authorization: req.headers.get('Authorization') } } })가 그 사람으로 동작해요. 번들된 함수를 고칠 때는 get_function의 package_json·files를 그대로 다시 보내세요. 빼면 파일 하나짜리가 돼요. 프로덕션 환경 변수가 process.env로 들어와요. 소유자·관리자만 배포할 수 있어요. 기본은 비공개라 이 프로젝트의 키(공개 키, 사용자 토큰, 비밀 키)가 있어야 해요(Supabase verify_jwt와 같아요). 로그인한 사용자만 받으려면 request.claims.role을 확인하세요. public이 true면 키 없이 누구나 부르니 결제사 웹훅 같은 경우에만 쓰세요. 호출: POST https://<ref>.<zone>/functions/v1/<name>, 헤더 Authorization: Bearer <공개 키, 사용자 토큰 또는 비밀 키>.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"source":"export default async () => new Response(\"ok\")","public":true,"package_json":"value","package_lock":"value","dependencies":{},"files":{},"entry":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"source": "export default async () => new Response(\"ok\")",
"public": true,
"package_json": "value",
"package_lock": "value",
"dependencies": {},
"files": {},
"entry": "value"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/functions/{name}
함수 시간 한도 호출 하나(timeout_seconds)와 SQL 한 문장(sql_timeout_seconds)의 시간 한도를 초로 정해요. 기본 150초·8초, 최대는 get_function의 timeout_cap_seconds예요. null은 기본값, 빼면 그대로예요. 넘긴 호출은 504로 끊겨요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"public":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"public": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/functions/{name}
함수 삭제 함수를 지워요. 그 주소는 404가 되고, 이 함수를 부르는 예약 작업은 실패해요. 되돌릴 수 없으니 사용자가 분명히 요청했을 때만 쓰고, confirm에 함수 이름을 그대로 넣어야 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/functions/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/function-egress
함수의 외부 요청 함수 안에서 fetch()로 공개 HTTPS 주소를 부를 수 있게 하거나 막아요. 지금 상태는 list_functions의 egress예요. 30초 안에 적용돼요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-egress" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-egress', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/function-secrets
함수 시크릿 목록 함수만 보는 시크릿의 이름과 바꾼 때예요. 값은 어떤 도구로도 다시 읽을 수 없어요. readable이 false면 값이 열리지 않아 함수에 들어가지 않으니 다시 저장하세요. 소유자·관리자만 볼 수 있어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/function-secrets
함수 시크릿 저장 함수만 읽는 시크릿을 저장해요(웹훅 서명 키 등). 빌드에는 안 들어가고 같은 이름의 환경 변수보다 먼저 쓰여요. 다음 호출부터 process.env로 읽어요. 하나라도 틀리면 아무것도 저장하지 않고, 저장한 값은 다시 못 봐요. SUPABASE_·BLACKWALL로 시작하는 이름과 NODE_ENV·HOME·PATH·NODE_OPTIONS·TZ는 못 써요. 프로젝트에 100개, 값 하나 32KB까지예요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"secrets":{},"dotenv":"API_URL=https://example.com"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"secrets": {},
"dotenv": "API_URL=https://example.com"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/function-secrets/copy
함수 시크릿 복사 내 다른 프로젝트(from)에 있는 함수 시크릿을 이 프로젝트(ref)로 이름만 대서 복사해요. 값은 서버 안에서만 옮겨지고 답에는 이름만 와요. 같은 키를 다시 붙여 넣지 않아도 돼요. 이 프로젝트에 이미 있는 이름은 건너뛰고(skipped) overwrite: true면 바꿔요. from에 없는 이름은 missing으로 알려 주고 나머지는 복사해요. 한 번에 50개까지예요. 두 프로젝트 모두에서 소유자·관리자여야 해요(조직이 달라도 돼요).
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets/copy" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"from":"value","names":["my-name"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets/copy', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"from": "value",
"names": [
"my-name"
]
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/function-secrets/{name}
함수 시크릿 삭제 함수 시크릿 하나를 지워요. 값은 되살릴 수 없고, 함수는 다음 호출부터 이 값 없이 실행돼요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/function-secrets/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
도메인과 엣지
GET /api/v1/projects/{ref}/domains
도메인 보기 이 프로젝트에 연결한 도메인과 각각의 용도(site/api), 따르는 브랜치, 리디렉트 대상, 확인 상태(아직이면 넣어야 할 TXT 레코드), 인증서 상태를 봐요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/domains
도메인 연결 도메인을 연결해요. 받은 verification_record(TXT)를 DNS에 넣으면 몇 분 안에 확인돼요. target=api면 프로젝트 API로, branch를 주면 그 프리뷰로 답해요. *.example.com도 돼요. pair_www=true면 www도 연결해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"hostname":"app.example.com"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"hostname": "app.example.com"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/domains/{hostname}
도메인 연결 해제 도메인 연결을 끊어요. 그 주소는 몇 초 안에 더 이상 답하지 않아요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 도메인을 그대로 넣어야 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/domains/{hostname}/redirect
도메인 리디렉트 이 도메인을 같은 프로젝트의 다른 도메인으로 넘기거나, to를 비워 다시 사이트를 열게 해요. to에 경로를 붙이면(example.com/vision) 방문한 경로가 그 뒤에 붙고 질의 문자열은 그대로 따라가요: vision.example.com/x?y=1 → example.com/vision/x?y=1, 첫 화면은 example.com/vision. to의 도메인은 이 프로젝트에 연결한, 리디렉트가 아닌 도메인이어야 해요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com/redirect" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"to":"https://example.com","status":308}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com/redirect', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"to": "https://example.com",
"status": 308
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/edge
방화벽·캐시 보기 이 프로젝트의 IP 차단·허용 목록, 주소 하나당 분당 요청 한도, 적용 범위, 마지막 캐시 비우기 시각을 봐요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/edge
방화벽 바꾸기 IP 차단(deny)·허용(allow, 비우면 모두 허용) 목록과 분당 요청 한도(10~100000, null이면 플랫폼 기본값), 적용 범위(all/site/api)를 바꿔요. 준 항목만 바뀌어요. 소유자·관리자만.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"deny":["value"],"allow":["value"],"rate_per_minute":1,"scope":"all"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"deny": [
"value"
],
"allow": [
"value"
],
"rate_per_minute": 1,
"scope": "all"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/edge/purge
캐시 비우기 서버 배포가 s-maxage로 공유를 허락해 엣지에 저장된 응답을 모두 버려요. 다음 요청부터 배포가 다시 답해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge/purge" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge/purge', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/domains/{hostname}/certificate
인증서 올리기 연결한 도메인에 직접 가진 TLS 인증서를 써요. certificate는 PEM 체인(서버 인증서가 먼저), key는 PEM 개인 키. 도메인 이름이 인증서에 들어 있어야 해요. 1분 안에 적용돼요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com/certificate" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"certificate":"-----BEGIN CERTIFICATE-----\n…","key":"API_URL"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com/certificate', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"certificate": "-----BEGIN CERTIFICATE-----\n…",
"key": "API_URL"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/domains/{hostname}/certificate
올린 인증서 삭제 올린 인증서를 지우고 자동 발급 인증서로 돌아가요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com/certificate" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/domains/app.example.com/certificate', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
네트워크
GET /api/v1/projects/{ref}/network
네트워크 주소 요청을 받는 주소(inbound, 커스텀 도메인 A 레코드)와, 고정 아웃바운드 IP를 켰다면 나가는 고정 주소(outbound.addresses)예요. 켜지 않았으면 나가는 주소는 공유라 돌려주지 않으니 허용 목록에 넣지 마세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/network/ips
네트워크 주소 요청을 받는 주소(inbound, 커스텀 도메인 A 레코드)와, 고정 아웃바운드 IP를 켰다면 나가는 고정 주소(outbound.addresses)예요. 켜지 않았으면 나가는 주소는 공유라 돌려주지 않으니 허용 목록에 넣지 마세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network/ips" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network/ips', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/network/static-outbound-ip
고정 아웃바운드 IP 유료 부가 서비스인 고정 아웃바운드 IP를 켜거나 꺼요. 켜면 서버 배포, 함수 fetch(), 데이터베이스 웹훅이 고정 주소로 나가고 월 요금을 쓴 날만큼 청구해요. Pro 이상, 소유자·관리자·결제 담당자만 돼요. 요금이 드니 사용자가 요청할 때만 쓰세요. 가격·상태는 get_network에 있어요. outcome이 provisioning이면 주소를 만들고 있고(보통 1시간 안) 그 전엔 요금이 없어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network/static-outbound-ip" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network/static-outbound-ip', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/network/static-outbound-ip
고정 아웃바운드 IP 유료 부가 서비스인 고정 아웃바운드 IP를 켜거나 꺼요. 켜면 서버 배포, 함수 fetch(), 데이터베이스 웹훅이 고정 주소로 나가고 월 요금을 쓴 날만큼 청구해요. Pro 이상, 소유자·관리자·결제 담당자만 돼요. 요금이 드니 사용자가 요청할 때만 쓰세요. 가격·상태는 get_network에 있어요. outcome이 provisioning이면 주소를 만들고 있고(보통 1시간 안) 그 전엔 요금이 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network/static-outbound-ip" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network/static-outbound-ip', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
예약 작업
GET /api/v1/projects/{ref}/jobs
예약 작업 목록 예약 작업(cron)과 일정, 다음 실행 시각, 마지막 결과를 봐요. SQL의 cron.schedule로 만든 작업은 source가 sql이에요. limit은 요금제의 작업 수 한도예요. 시각은 모두 UTC예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/jobs/{job}
예약 작업 만들기·바꾸기 정해진 일정마다 함수를 부르거나 SQL 한 문장을 실행해요. 같은 이름이면 그 작업을 바꿔요. schedule은 다섯 칸 cron(분 시 일 월 요일), UTC 기준이에요(한국 자정 = "0 15 * * *"). kind가 function이면 target은 함수 이름(본문 {}로 POST), sql이면 서비스 역할로 실행할 SQL이에요. 외부 URL은 못 불러요: 함수나 SQL의 net.http_post를 쓰세요. SQL은 timeout_seconds(기본 120초) 안에 끝나야 해요(statement_timeout을 늘리면 그만큼). 최대는 Free 300초, Pro·Enterprise 3600초예요. SQL의 cron.schedule로 만든 작업도 source=sql로 나와요. 프로젝트당 작업 수 한도는 list_jobs의 limit이에요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"schedule":"0 3 * * *","kind":"function","target":"hello"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"schedule": "0 3 * * *",
"kind": "function",
"target": "hello"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/jobs/{job}
예약 작업 켜기·끄기 예약 작업을 끄거나 다시 켜요. 다시 켜면 놓친 실행을 몰아서 하지 않고 다음 일정부터 돌아요. job은 id나 이름이에요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/jobs/{job}/run
예약 작업 지금 실행 일정을 기다리지 않고 1분 안에 한 번 실행해요. 결과는 list_job_runs로 봐요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly/run" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly/run', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/jobs/{job}/runs
예약 작업 실행 기록 예약 작업의 최근 실행과 결과, 실패했다면 그 오류를 최신순으로 봐요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly/runs?limit=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly/runs?limit=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/jobs/{job}
예약 작업 삭제 예약 작업 하나와 그 실행 기록을 지워요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/jobs/nightly', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
데이터베이스 웹훅
GET /api/v1/projects/{ref}/webhooks
데이터베이스 웹훅 목록 표의 변경을 알리는 웹훅과 최근 전달 결과를 봐요. attached가 false면 표가 지워져 멈춘 것이에요. 서명 키(signing_secret)는 만들 때(create_db_webhook) 한 번만 보여주고, 목록에는 signing_secret_set과 끝 네 글자(signing_secret_last4)만 실어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/webhooks
데이터베이스 웹훅 만들기 표에 줄이 추가·수정·삭제되면 커밋 후 몇 초 안에 POST로 알려요. kind가 url이면 target은 공개 https 주소(사설 주소 불가, 리다이렉트 안 따라감), function이면 이 프로젝트의 함수 이름이에요. 본문: { type: "INSERT"|"UPDATE"|"DELETE", table, schema: "public", record, old_record, hook, delivery, occurred_at }. 서명 헤더: x-blackwall-signature: t=<초>,v1=<HMAC-SHA256(signing_secret, "<t>.<본문>") 16진수>. signing_secret은 이 응답에만 실려요. 다시 볼 수 없으니 받는 쪽에 바로 저장하세요. 실패(2xx 아님, 10초 초과)하면 10초·1분·5분·30분 뒤 다시 보내고 다섯 번째에 버려요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","table":"notes","events":["insert"],"kind":"url","target":"hello"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"table": "notes",
"events": [
"insert"
],
"kind": "url",
"target": "hello"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/webhooks/{webhook}
데이터베이스 웹훅 켜기·끄기 웹훅을 끄거나 켜요. 꺼진 동안의 변경은 나중에도 보내지 않아요. webhook은 id나 이름이에요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks/orders" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks/orders', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/webhooks/{webhook}
데이터베이스 웹훅 삭제 웹훅과 그 전달 기록, 아직 보내지 못한 변경을 지워요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks/orders" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks/orders', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/webhooks/{webhook}/deliveries
데이터베이스 웹훅 전달 기록 웹훅의 최근 전달과 응답 상태, 실패 이유를 최신순으로 봐요. 7일간 보관해요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks/orders/deliveries?limit=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/webhooks/orders/deliveries?limit=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
백업과 복원
GET /api/v1/projects/{ref}/backups
백업 목록 프로젝트 백업(매일 밤 프로젝트 리전 시각 03:00~05:00에 자동, 직접 만든 것, 복원 직전 것)과 복원 기록을 봐요. 보관 기간은 retention_days예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/backups
지금 백업 표·가입자·파일을 지금 백업해요. 큰 변경(마이그레이션, 대량 삭제) 전에 만드세요. 7일 보관돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/backups/{backup_id}/restore
백업으로 복원 표·가입자·파일을 백업 시점으로 되돌려요. backup_id 대신 at(ISO 시각)을 주면 초 단위로 되돌려요(Pro 이상, list_backups의 point_in_time 안. 파일은 파일 버킷 서버에서만, 지난 14일 안에 지운 것까지). 그 뒤 변경은 모두 사라지니 사용자가 요청할 때만 쓰세요. 직전 상태를 백업하니 undo_backup_id로 되돌릴 수 있어요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups/BACKUP_ID/restore" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups/BACKUP_ID/restore', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/backups/restore-to-time
백업으로 복원 표·가입자·파일을 백업 시점으로 되돌려요. backup_id 대신 at(ISO 시각)을 주면 초 단위로 되돌려요(Pro 이상, list_backups의 point_in_time 안. 파일은 파일 버킷 서버에서만, 지난 14일 안에 지운 것까지). 그 뒤 변경은 모두 사라지니 사용자가 요청할 때만 쓰세요. 직전 상태를 백업하니 undo_backup_id로 되돌릴 수 있어요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups/restore-to-time" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"at":"2026-10-01T14:59:00+09:00"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/backups/restore-to-time', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"at": "2026-10-01T14:59:00+09:00"
}),
})
const result = await response.json()
로그와 관측
GET /api/v1/projects/{ref}/logs
로그 보기 로그를 최신순으로 봐요: 사이트·API·인증·함수 요청(메서드, 경로, 상태, 시간)과 서버·함수 출력. 500이 나면 level: error로 먼저 보세요. 다음 쪽은 next_before를 before로 넘겨요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/logs?source=site&level=warn" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/logs?source=site&level=warn', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/log-drains
로그 내보내기 목록 로그를 보내는 곳(https 또는 datadog), 보내는 출처, 마지막 전송과 오류. 서명 키(signing_secret)는 만들 때(create_log_drain) 한 번만 보여주고, 목록에는 signing_secret_set과 소유자·관리자에게 끝 네 글자(signing_secret_last4)만 실어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/log-drains
로그 내보내기 추가 이 프로젝트의 로그를 외부로 보내요. 만든 뒤에 쌓이는 로그부터 보내요. kind=https는 서명한 JSON을 POST하고, kind=datadog는 secret에 API 키가 필요해요. https 드레인의 signing_secret은 이 응답에만 실리니 받는 쪽에 바로 저장하세요. 프로젝트마다 5개까지. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","kind":"https","url":"https://example.com/hook"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"kind": "https",
"url": "https://example.com/hook"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/log-drains/{id}
로그 내보내기 끄기·켜기 설정은 두고 보내기만 멈추거나 다시 시작해요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains/ID', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/log-drains/{id}
로그 내보내기 삭제 로그 내보내기를 지워요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/log-drains/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/metrics
지표 요청 수·실패 수·지연(p50/p95/p99)을 표면별·시간대별로, 그리고 데이터베이스 크기·연결·캐시 적중률을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/metrics?range=1h" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/metrics?range=1h', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/audit
감사 기록 tab=activity는 누가 무엇을 바꿨는지, tab=access는 누가 개인정보에 접근했는지예요. 최신순 200개씩, has_more면 offset을 늘려요. from·to는 YYYY-MM-DD(한국 날짜). 소유자·관리자만 돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/audit?tab=activity&from=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/audit?tab=activity&from=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
팀과 알림
GET /api/v1/projects/{ref}/team
팀 구성원 이 프로젝트를 가진 조직의 구성원과 역할, 2단계 인증 여부, 아직 수락하지 않은 초대.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/team/invitations
구성원 초대 이메일로 초대 링크를 보내요. 받은 사람이 링크를 열어야 참여해요. 이미 구성원인 주소는 역할만 바뀌어요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/invitations" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"email":"[email protected]"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/invitations', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"email": "[email protected]"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/team/invitations/{id}
초대 취소 보낸 초대를 취소해요. 그 링크는 바로 열리지 않게 돼요. id는 list_team의 invitations에 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/invitations/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/invitations/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/team/members/{email}
구성원 역할 바꾸기 이미 구성원인 사람의 역할을 바꿔요. 소유자의 역할은 바꿀 수 없어요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/members/person%40example.com" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"role":"admin"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/members/person%40example.com', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"role": "admin"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/team/members/{email}
구성원 내보내기 조직에서 내보내요. 소유자는 내보낼 수 없어요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/members/person%40example.com" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/members/person%40example.com', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/team/mfa
2단계 인증 요구 조직의 모든 구성원에게 2단계 인증을 요구하거나 그만둬요. 켜려면 이 토큰의 주인이 먼저 2단계 인증을 켜야 해요. 켜지 않은 구성원은 켤 때까지 이 조직을 열 수 없고 응답의 without_mfa에 나와요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/mfa" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"required":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/team/mfa', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"required": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/channels
알림 채널 목록 배포·도메인·사용량·결제 소식을 받는 채널(Slack·카카오워크·웹훅)과 마지막 전송 결과예요(조직 단위). 웹훅 채널의 서명 키(signing_secret)는 만들 때(create_channel) 한 번만 보여주고, 목록에는 signing_secret_set과 끝 네 글자(signing_secret_last4)만 실어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/channels
알림 채널 추가 Slack·카카오워크(웹훅 주소)·서명 웹훅·메일(emails에 1~10개)로 알림을 보내요. 메일은 확인 링크를 연 주소에만 보내요. notices를 비우면 모든 종류를 받아요. 웹훅 채널의 signing_secret은 이 응답에만 실리니 받는 쪽에 바로 저장하세요. 만든 뒤 test_channel로 확인하세요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"kind":"slack","name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"kind": "slack",
"name": "my-name"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/channels/{id}/test
알림 채널 시험 그 채널 하나에만 시험 메시지를 보내요. 메일 채널이면 확인된 주소에만 보내고, 확인을 기다리는 주소에는 확인 메일을 다시 보내요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels/ID/test" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels/ID/test', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/channels/{id}
알림 채널 끄기·켜기 설정은 두고 알림만 멈추거나 다시 받아요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels/ID', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/channels/{id}
알림 채널 삭제 알림 채널을 지워요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/channels/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
요금과 사용량
GET /api/v1/projects/{ref}/usage
사용량 표·줄·가입자·파일 수와 저장 용량, 이번 달 사용량, 그리고 분당 한도(limits.outbound_requests_per_minute: 함수·pg_net·HTTP 작업이 함께 쓰는 외부 요청 수, 자기 API 호출은 세지 않음)를 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/usage" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/usage', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/billing/plan
요금제 조직의 요금제, 예약된 변경, 고를 수 있는 요금제와 월 요금, 켜 둔 부가 서비스(addons)예요. 무료면 free에 한도와 Pro 전용 기능이 있어요. 요금제 변경은 콘솔에서만 돼요. 소유자·관리자·결제 담당만 돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/plan" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/plan', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/billing/spend
지출 한도 지출 상한(spend cap: 켜면 포함량을 넘는 사용을 막고 초과 요금을 받지 않음), 월 초과 요금 한도와 알림 웹훅, 이번 달 사용량을 봐요. 소유자·관리자·결제 담당만 볼 수 있어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/spend" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/spend', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/billing/spend-cap
지출 상한 켜기·끄기 유료 요금제의 지출 상한을 켜고 꺼요. 켜면 포함량에서 멈춰 초과 요금이 없어요. 끄면 넘는 만큼 청구되니 끌 때 confirm에 프로젝트 이름(list_projects의 name)이 필요해요. 소유자·관리자·결제 담당만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/spend-cap" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/spend-cap', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/billing/spend-limit
월 지출 한도 지출 상한이 꺼졌을 때 한 달 초과 요금 한도(원 단위)와 알림 웹훅을 정해요. spend_limit_minor가 null이면 무제한, webhook_url을 빼면 그대로예요. 알림은 create_channel이 더 좋아요. 소유자·관리자·결제 담당만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/spend-limit" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"spend_limit_minor":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing/spend-limit', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"spend_limit_minor": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/billing
청구서와 사용량 한 달 청구서(항목별 사용량·포함량·금액)와 날짜별 사용량이에요. period를 비우면 이번 달(UTC). 금액은 currency의 가장 작은 단위예요(KRW는 원, USD는 센트). amount_minor·total_minor는 청구액, list_amount_minor·list_total_minor는 정가(Pro 기준)예요. included는 이번 달 실제로 쓴 요금제의 포함량(바꾼 날까지 날짜로 나눔), list_included는 Pro 포함량이에요. billing_exempt면 청구액이 0이에요. 카드·결제 내역은 콘솔에만 있어요. 소유자·관리자·결제 담당만 돼요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing?period=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/billing?period=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
기타
GET /api/v1/projects/{ref}/transfer
옮길 수 있는 조직 이 프로젝트를 옮길 수 있는 다른 조직(내가 소유자나 관리자인 조직)의 id·이름·요금제예요. can_transfer는 내가 지금 조직의 소유자라서 옮길 수 있는지예요. transfer_project의 organisation에 id를 넣어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/transfer" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/transfer', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/transfer
프로젝트 옮기기 프로젝트를 다른 조직으로 옮겨요. 지금 조직의 소유자이면서 받는 조직의 소유자나 관리자여야 하고, 받는 조직의 요금제에 프로젝트 자리가 있어야 해요. 옮긴 뒤 사용량은 받는 조직에 청구되고 이번 달 청구는 옮긴 시점에서 나뉘어요. 원래 조직 구성원에게 따로 준 접근은 사라지고, 되돌리려면 받는 조직의 소유자가 다시 옮겨야 해요. 주소·키·데이터·배포는 그대로예요. 사용자가 분명히 요청했을 때만 쓰고 confirm에 프로젝트 이름을 그대로 넣으세요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/transfer" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"organisation":"My team","confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/transfer', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"organisation": "My team",
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/server
전용 서버 프로젝트의 전용 서버를 봐요: 크기(tier), 위치, 상태, 주소, 한 달 금액, 대기 서버, 자동 전환, 되돌리기 기간, 다음 위치 옮기기 날짜, 진행 중인 작업(jobs). server가 null이면 공용 서버를 써요. offered가 false면 아직 열리지 않았어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/server
전용 서버 빌리기 이 프로젝트만 쓰는 서버를 빌려요. 크기와 위치별 월 금액은 list_server_sizes로 먼저 보여 주고 사용자가 고른 것만 넣으세요. 보통 10분 안에 준비되고 데이터베이스와 앱을 옮긴 뒤 주소를 바꿔요. Pro부터, 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"tier":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"tier": "value"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/server
서버 크기 바꾸기 전용 서버의 크기를 바꿔요. when=now는 지금, tonight는 서버 위치 시간 새벽 3~5시. 대기 서버가 없으면 3~5분 응답하지 않고, 있으면 전환하는 몇 초만 멈춰요. 크기 바꾸기는 무료이고 월 금액은 새 크기 값이에요(list_server_sizes). 소유자·관리자만 돼요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"tier":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"tier": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/server
전용 서버 반납 전용 서버를 반납해요: 마지막 백업을 받고 데이터베이스와 앱을 공용 서버로 옮긴 뒤 서버(와 대기 서버)를 지워요. 옮기는 동안 쓰기가 멈춰요. 사용자가 요청할 때만 쓰고 confirm에 ref를 그대로 넣으세요. 소유자·관리자만 돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/server/standby
대기 서버 같은 위치·같은 크기의 대기 서버를 켜거나 꺼요. 데이터베이스를 계속 복제하고, 월 금액은 그 크기 값과 같아요(list_server_sizes). auto_failover=true면 주 서버가 60초 응답하지 않을 때 대기 서버로 저절로 바꿔요(대기 서버가 있어야 해요). 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server/standby" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"standby":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server/standby', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"standby": true
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/server/move
서버 위치 옮기기 전용 서버를 다른 위치로 옮겨요. 무료이고 한 달에 한 번이에요(next_move_at). 새 위치에 서버를 만들어 복제하고 주소를 바꾸는 순간 쓰기가 몇 초 멈춰요. 옛 서버는 7일 남겨요. 월 금액은 새 위치 값이에요(list_server_sizes). 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server/move" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"region":"kr"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server/move', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"region": "kr"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/server/restore-days
되돌리기 기간 특정 시각으로 되돌릴 수 있는 기간을 7일 또는 28일로 정해요. 28일은 전용 서버에서만 되고 월 추가 요금이 있어요(get_server의 options, get_billing). 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server/restore-days" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"days":7}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/server/restore-days', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"days": 7
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/s3-keys
S3 접근 키 목록 S3 엔드포인트(endpoint, region, force_path_style)와 TUS 이어 올리기 주소, 그리고 S3 접근 키의 이름·접근 키 ID·마지막 사용 시각·폐기 여부예요. 비밀 접근 키는 돌려주지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/s3-keys" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/s3-keys', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/s3-keys
S3 접근 키 만들기 AWS SDK·aws CLI·rclone이 /storage/v1/s3에 쓸 접근 키를 만들어요. 접근 규칙을 무시하니 서버에만 두세요. 비밀 접근 키는 이 응답에서만 보여요. 소유자·관리자만, 프로젝트마다 20개까지예요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/s3-keys" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/s3-keys', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/s3-keys/{id}
S3 접근 키 폐기 S3 접근 키 하나를 폐기해요. 30초 안에 그 키로 서명한 요청이 거부돼요. 다른 키는 그대로예요. 되돌릴 수 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/s3-keys/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/s3-keys/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/storage/policies
파일 접근 규칙 만들기 파일 표(objects)에 접근 규칙 하나를 더해요. name·command(select·insert·update·delete·all)·roles·using·check를 받아요. 프로젝트 로그인은 파일 표의 주인이 아니라 SQL로는 규칙을 만들 수 없어서 이 경로를 써요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/storage/policies" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/storage/policies', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/storage/copy-from-import
파일 가져오기 import_sources에 연결한 Supabase 계정으로 그 프로젝트의 버킷과 파일을 이 서버의 프로젝트(ref)에 복사해요. 여기 없는 버킷은 Supabase와 같은 공개 여부·크기 한도·형식으로 만들고, 파일은 upload_object와 같은 저장소에 같은 한도로 올려요. 여기 있는 파일과 크기가 같으면 건너뛰어서 다시 불러도 돼요. 한 번에 파일 200개(max_files)·45초까지 옮기고, 남으면 답의 next를 넘겨 다시 불러요(done이 true가 될 때까지). 답은 버킷마다 created, copied, skipped, failed, bytes와 실패한 파일 몇 개예요. Supabase 키는 대화에 나오지 않아요. 버킷의 접근 규칙은 옮기지 않아요. dry_run이면 아무것도 바꾸지 않고 수만 보여줘요. 소유자·관리자·개발자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/storage/copy-from-import" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"buckets":["value"],"rename":{},"dry_run":true,"max_files":1}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/storage/copy-from-import', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"buckets": [
"value"
],
"rename": {},
"dry_run": true,
"max_files": 1
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/deployment-retention
배포 보관 기간 배포를 종류별로 며칠 남기는지예요: days(적용 값), project_days(null은 요금제), plan_days. 늘 남기는 배포(always_kept)와 삭제 후 되돌릴 수 있는 날(restore_days)도 와요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployment-retention" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployment-retention', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/deployment-retention
배포 보관 기간 바꾸기 배포 종류별 보관 기간을 바꿔요. 기간이 지난 배포는 삭제되고 3일 동안 restore_deployment로 되돌릴 수 있어요. 최근 배포와 서비스 중인 배포는 기간과 상관없이 남아요. 프로젝트 관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployment-retention" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"canceled_days":"value","error_days":"value","preview_days":"value","production_days":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployment-retention', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"canceled_days": "value",
"error_days": "value",
"preview_days": "value",
"production_days": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/schemas
프로젝트 스키마 프로젝트가 SQL로 만든 스키마(public 제외)와 데이터 API 노출 여부(exposed)를 봐요. 데이터베이스 안 이름은 app_<ref>_이름이지만 SQL과 클라이언트에선 만든 이름을 그대로 써요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/schemas" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/schemas', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/schemas/exposed
노출 스키마 정하기 데이터 API가 public 말고도 답할 스키마 목록을 통째로 정해요(빈 목록은 public만). Accept-Profile 헤더나 supabase-js의 .schema()로 써요. RLS와 권한은 public과 같아요. 30초 안에 적용돼요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/schemas/exposed" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"exposed":["value"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/schemas/exposed', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"exposed": [
"value"
]
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/data-api
데이터 API 설정 보기 데이터 API(/rest/v1)가 켜졌는지, 최대 행 수(max_rows, null은 제한 없음), 노출 스키마, search_path를 봐요. search_path_choices는 넣을 수 있는 스키마예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/data-api" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/data-api', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/data-api
데이터 API 설정 바꾸기 데이터 API(/rest/v1)를 켜고 끄고, 최대 행 수와 search_path를 정해요. 준 것만 바꿔요. search_path의 스키마는 요청 스키마 뒤에 붙어 이름 없이 찾을 수 있어요. 30초 안에 적용돼요. 소유자·관리자만 돼요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/data-api" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true,"max_rows":1,"search_path":["value"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/data-api', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true,
"max_rows": 1,
"search_path": [
"value"
]
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/{param0}/{param1}
SAML SSO 추가 IdP 메타데이터(https 주소나 XML)로 SAML IdP를 등록해요(HTTP-Redirect 로그인 주소와 서명 인증서 필요). domains의 이메일로 signInWithSSO를 부르면 이 IdP로 가요(도메인 하나에 IdP 하나). 새 IdP는 엔터프라이즈 요금제에서만 추가돼요(new_providers_allowed). 이미 등록한 IdP는 그대로 동작해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/value/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"metadata_url":"value","metadata_xml":"value","domains":["value"],"attribute_mapping":{}}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/value/value', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"metadata_url": "value",
"metadata_xml": "value",
"domains": [
"value"
],
"attribute_mapping": {}
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/{param0}/{param1}/{param2}
SAML SSO 추가 IdP 메타데이터(https 주소나 XML)로 SAML IdP를 등록해요(HTTP-Redirect 로그인 주소와 서명 인증서 필요). domains의 이메일로 signInWithSSO를 부르면 이 IdP로 가요(도메인 하나에 IdP 하나). 새 IdP는 엔터프라이즈 요금제에서만 추가돼요(new_providers_allowed). 이미 등록한 IdP는 그대로 동작해요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/value/value/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"metadata_url":"value","metadata_xml":"value","domains":["value"],"attribute_mapping":{}}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/value/value/value', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"metadata_url": "value",
"metadata_xml": "value",
"domains": [
"value"
],
"attribute_mapping": {}
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/config/auth
로그인 설정 전체 보기 로그인 설정 전체를 Supabase auth config와 같은 소문자 키로 돌려줘요: 가입(disable_signup, mailer_autoconfirm 등), 이메일·비밀번호 규칙, 전화·문자(sms_*), SAML(saml_*), Web3, 소셜 제공자별 external_<제공자>_*. 비밀 값은 ••••abcd처럼 뒤 네 자리만 오고, 그대로 update_auth_config에 돌려주면 바뀌지 않아요. callback_url은 제공자 콘솔에 붙여 넣을 주소예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/config/auth
로그인 설정 바꾸기 준 키만 바꿔요(대문자 GoTrue 이름도 돼요). 콘솔 로그인 화면과 같은 규칙으로 확인해요: 켠 제공자는 필요한 값이 다 있어야 하고(예: external_google_client_id), Apple 시크릿은 7일 넘게 남은 ES256 JWT, 문자 내용엔 {{ .Code }}가 있어야 해요. 하나라도 틀리면 아무것도 저장하지 않고 키마다 이유를 줘요. 카카오 동의 항목은 external_kakao_scopes(쉼표로), 네이버는 external_naver_scopes, Google·GitHub 추가 스코프는 external_<제공자>_additional_scopes예요. 비밀 값을 빈 문자열로 주면 지워요. 소유자·관리자·개발자만 돼요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/config/auth/custom-providers
사용자 정의 로그인 제공자 보기 프로젝트가 직접 정의한 OAuth·OIDC 제공자(custom:<ID>)와 요금제 한도(max_providers), 스위치(enabled)를 봐요. 앱에서는 signInWithOAuth({ provider: "custom:<ID>" })로 불러요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/config/auth/custom-providers
사용자 정의 로그인 제공자 만들기 OAuth·OIDC 제공자(custom:<ID>)를 만들고 켜요(set_auth_provider와 같은 저장소). oidc는 issuer만 주면 {issuer}/.well-known/openid-configuration에서 주소와 jwks_uri를 읽고, id_token의 서명·issuer·대상·만료·nonce를 확인해요. oauth2는 issuer나 authorization_url·token_url이 필요하고, 빈 주소는 {issuer}/oauth/authorize, /oauth/token, /oauth/userinfo예요. claim_map은 id·email·email_verified·name·avatar·phone이 응답의 어느 필드인지(점 경로)예요. PKCE는 기본으로 켜져요. 요금제 한도를 넘으면 거부돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"identifier":"value","name":"my-name","provider_type":"oidc","client_id":"CLIENT_ID","client_secret":"CLIENT_SECRET"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"identifier": "value",
"name": "my-name",
"provider_type": "oidc",
"client_id": "CLIENT_ID",
"client_secret": "CLIENT_SECRET"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/config/auth/custom-providers/{identifier}
사용자 정의 로그인 제공자 수정 사용자 정의 제공자 하나를 고쳐요. ID는 바꿀 수 없어요. client_secret을 빈 문자열로 두면 저장된 시크릿을 그대로 써요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"identifier":"value","name":"my-name","provider_type":"oidc","client_id":"CLIENT_ID"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers/value', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"identifier": "value",
"name": "my-name",
"provider_type": "oidc",
"client_id": "CLIENT_ID"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/config/auth/custom-providers/{identifier}
사용자 정의 로그인 제공자 껐다 켜기 사용자 정의 제공자 하나를 끄거나 켜요. 끄면 지금 세션은 그대로지만 새 로그인은 다시 켤 때까지 실패해요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers/value', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/config/auth/custom-providers/{identifier}
사용자 정의 로그인 제공자 삭제 사용자 정의 제공자 하나를 지워요. 되돌릴 수 없고, 이 제공자로 로그인하던 사용자는 들어올 수 없어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers/value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/custom-providers/value', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/config/auth/copy-from-import
로그인 설정 가져오기 import_sources에 연결한 Supabase 계정으로 그 프로젝트의 로그인 설정을 이 서버의 프로젝트(ref)에 복사해요: 켜 둔 소셜 제공자(Client ID·시크릿 등, update_auth_config와 같은 확인), 돌아갈 주소 목록(uri_allow_list, add_redirect_url과 같아요), 비어 있을 때만 site_url. 시크릿은 대화에 나오지 않아요. 답은 제공자마다 copied와 이유예요. 답의 callback_url을 각 제공자 콘솔에 등록하기 전에는 로그인이 실패해요. dry_run이면 아무것도 바꾸지 않고 보여만 줘요. 소유자·관리자·개발자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/copy-from-import" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"providers":["google"],"dry_run":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/copy-from-import', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"providers": [
"google"
],
"dry_run": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/config/auth/third-party-auth
서드파티 인증 보기 Data API가 받는 다른 인증 서비스(Firebase, Clerk, WorkOS, Auth0, Amazon Cognito, OIDC issuer)의 토큰 목록이에요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/third-party-auth" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/third-party-auth', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/config/auth/third-party-auth
서드파티 인증 추가 다른 인증 서비스의 JWT로 로그인하게 해요. value는 type마다 달라요: firebase는 프로젝트 ID, clerk는 https://clerk.<도메인>이나 https://<이름>.clerk.accounts.dev, workos·oidc는 issuer URL, auth0은 테넌트 이름(<이름>.auth0.com의 앞부분), cognito는 사용자 풀 ID(region도 함께). Auth0·Cognito는 audiences도 넣으세요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/third-party-auth" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"type":"firebase","value":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/third-party-auth', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"type": "firebase",
"value": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/config/auth/third-party-auth/{id}
서드파티 인증 삭제 서드파티 인증 하나를 지워요. 그 서비스로 로그인한 사용자의 요청은 30초 안에 401로 거부돼요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/third-party-auth/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/config/auth/third-party-auth/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/analytics
웹 분석 페이지뷰와 방문자를 날짜별로, 많이 본 페이지·유입 경로·국가·기기·브라우저·운영체제와 함께 돌려줘요. 개인을 알아볼 수 있는 값은 저장하지 않아서 합계만 있어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics?days=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics?days=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/analytics/breakdown
웹 분석 세부 캠페인(utm_source·utm_medium·utm_campaign), 라우트, 사용자 정의 이벤트와 걸러낸 봇의 수를 돌려줘요. event를 주면 그 이벤트의 속성별 값을 함께 돌려줘요. 합계만 있어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/breakdown?days=1&event=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/breakdown?days=1&event=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/analytics/previews
프리뷰 방문 세기 프리뷰 배포와 dpl- 주소의 방문을 웹 분석에 셀지 정해요. 끄면(기본) 프리뷰에는 스크립트를 넣지 않고 보내온 것도 버려요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/previews" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"include_previews":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/previews', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"include_previews": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/analytics/export
웹 분석 내보내기 기간의 합계를 날짜·항목·값별 CSV 문자열로 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/export?days=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/export?days=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/analytics/reports
맞춤 리포트 목록 저장한 웹 분석 리포트와 넣을 수 있는 차트 이름을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/analytics/reports/{id}
맞춤 리포트 보기 저장한 리포트 하나를 그 기간의 합계, 세부, 속도와 함께 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports/ID', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/analytics/reports
맞춤 리포트 저장 리포트를 만들거나, id를 주면 그 리포트를 바꿔요. 개발자 이상만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","widgets":["views"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"widgets": [
"views"
]
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/analytics/reports
맞춤 리포트 저장 리포트를 만들거나, id를 주면 그 리포트를 바꿔요. 개발자 이상만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","widgets":["views"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"widgets": [
"views"
]
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/analytics/reports/{id}
맞춤 리포트 삭제 리포트만 지워요. 분석 기록은 그대로예요. 개발자 이상만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/analytics/reports/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/speed-insights
속도 인사이트 실제 방문자의 브라우저가 잰 Core Web Vitals(LCP, INP, CLS, FCP, TTFB)의 75번째 백분위와 평가, 느린 페이지를 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/speed-insights?days=1&device=all" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/speed-insights?days=1&device=all', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/insights
분석 켜기·끄기 웹 분석과 속도 인사이트를 켜고 꺼요. 켜면 HTML에 /_oneend/insights/script.js가 들어가고, @vercel/analytics·@vercel/speed-insights도 그대로 집계돼요. 쿠키와 IP는 저장하지 않아요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/insights" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"analytics":true,"speed_insights":true,"vitals_sample_percent":1}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/insights', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"analytics": true,
"speed_insights": true,
"vitals_sample_percent": 1
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/remote-cache
원격 캐시 Turborepo 원격 캐시의 주소, 저장된 결과 수와 용량, 최근 30일 적중·업로드, 이번 달 저장 사용량(remote_cache_gb_hour)과 단가를 돌려줘요. 내려받은 데이터는 egress_gb로 세요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/remote-cache" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/remote-cache', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/remote-cache/artifacts
원격 캐시 비우기 저장된 결과를 모두 지워요. 다음 빌드부터 다시 채워지고, 지운 만큼 저장 용량 사용량이 줄어요. 개발자 이상만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/remote-cache/artifacts" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/remote-cache/artifacts', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/flags
기능 플래그 목록 기능 플래그와, 엣지 설정에 둔 플래그 모양의 값을 함께 돌려줘요. source는 어디에 있는지, shadows는 같은 키의 엣지 설정 값을 가리는지 알려 줘요. 키가 같으면 플래그를 따라요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/flags" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/flags', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/flags/evaluate
기능 플래그 값 보기 앱이 받을 값을 돌려줘요. 컨텍스트(예: {"user": {"id": "u1"}})와 환경을 주면 플래그 규칙을, 플래그가 없으면 엣지 설정 값을 따라요. source가 어느 쪽인지 알려 줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/flags/evaluate?key=API_URL&environment=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/flags/evaluate?key=API_URL&environment=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/flags/{key}/environments/{environment}
기능 플래그 켜기·끄기 한 환경에서 플래그를 켜거나 꺼요. 프로덕션은 소유자·관리자, 그 밖의 환경은 개발자 이상이 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/flags/API_URL/environments/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/flags/API_URL/environments/value', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/edge-config
엣지 설정 읽기 프로젝트의 엣지 설정(배포 없이 바꾸는 값과 기능 플래그) 전체와 버전, 크기, 한도를 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/edge-config/tokens
엣지 설정 읽기 토큰 다른 프로젝트가 이 프로젝트의 엣지 설정을 읽는 읽기 토큰과 연결된 프로젝트(변수 이름, 환경), 이 프로젝트에 연결된 다른 프로젝트의 엣지 설정을 돌려줘요. 토큰 값은 돌려주지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/edge-config/tokens
엣지 설정 읽기 토큰 만들기 읽기 토큰을 만들어요. connect를 주면 같은 조직의 프로젝트에 연결해, 다음 배포부터 연결 문자열(https://<ref>.<zone>/config/v1?token=…)을 변수로 받아요. 토큰은 이때만 보여요. 프로젝트 관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/edge-config/tokens/{id}
읽기 토큰 폐기 읽기 토큰을 폐기해요. 바로 읽지 못하고, 연결된 프로젝트의 다음 배포부터 변수가 빠져요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/edge-config/tokens/{id}/connections/{ref}
읽기 토큰을 프로젝트에 연결 읽기 토큰을 같은 조직의 다른 프로젝트 배포에 변수로 연결해요. 이미 연결돼 있으면 변수 이름과 환경을 바꿔요. 그 프로젝트의 개발자 이상(프로덕션은 소유자·관리자)이어야 해요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens/ID/connections/abcdefghijklmnopqrst" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"variable":"value","targets":["production"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens/ID/connections/abcdefghijklmnopqrst', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"variable": "value",
"targets": [
"production"
]
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/edge-config/tokens/{id}/connections/{ref}
읽기 토큰 연결 끊기 읽기 토큰을 한 프로젝트에서 떼요. 그 프로젝트의 다음 배포부터 변수가 빠져요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens/ID/connections/abcdefghijklmnopqrst" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/tokens/ID/connections/abcdefghijklmnopqrst', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/edge-config/history
엣지 설정 변경 기록 누가 언제 어떤 키를 무엇에서 무엇으로 바꿨는지, 최근 것부터 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/history?limit=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config/history?limit=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/edge-config
엣지 설정 바꾸기 키를 저장하거나 지워요. 몇 초 안에 모든 서버에 적용돼요. 플래그는 true/false, {"enabled": true, "percent": 20}, {"enabled": true, "allow": ["user-1"]} 모양이에요. 개발자 이상만 돼요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"set":{},"delete":["value"]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/edge-config', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"set": {},
"delete": [
"value"
]
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/rolling-releases
점진적 배포 상태 점진적 배포 설정과, 진행 중인 배포(새 배포가 받는 방문자 비율)와 최근 기록을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rolling-releases" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rolling-releases', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/rolling-releases
점진적 배포 설정 새 프로덕션 배포를 단계별 비율(stages, 예: [10, 50])로 내보낼지 정해요. auto_advance가 false면 단계마다 승인해요. abort_error_rate(0.05 = 5%)를 넘으면 자동으로 되돌려요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rolling-releases" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true,"stages":["value"],"stage_minutes":1,"auto_advance":true,"abort_error_rate":0.001}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rolling-releases', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true,
"stages": [
"value"
],
"stage_minutes": 1,
"auto_advance": true,
"abort_error_rate": 0.001
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/rolling-releases/{action}
점진적 배포 다음 단계로 진행 중인 배포를 다음 단계 비율로 올려요. 마지막 단계였다면 모두에게 배포해요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rolling-releases/value" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"reason":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/rolling-releases/value', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"reason": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/kv
KV 키 목록 KV 저장소의 키를 접두어로, 50개씩 돌려줘요. 사용량과 한도, REST 주소도 함께예요. 비밀을 볼 수 있는 역할만 할 수 있어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv?prefix=value&cursor=value" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv?prefix=value&cursor=value', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/kv/{id}
KV 값 읽기 키 하나의 값과 남은 초(ttl, -1은 만료 없음)를 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv/ID', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/kv/{id}
KV 값 저장 키에 JSON 값을 저장해요. ttl은 만료까지 초예요. 개발자 이상만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"value":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv/ID', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"value": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/kv/{id}
KV 키 삭제 키를 지워요. 개발자 이상만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/kv/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/ai-gateway
AI 게이트웨이 AI 게이트웨이 주소(OpenAI 호환), 설정, 공급자(키는 끝 네 자리만), 최근 30일 사용량을 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/ai-gateway
AI 게이트웨이 설정 AI 게이트웨이의 켜기, 로그인 사용자 허용, 캐시, 분당 한도, 플랫폼 공급자 대체(토큰 요금), 사용자별 하루 한도를 정해요. 사용자는 로그인한 id나 x-oneend-user 헤더예요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true,"allow_users":true,"cache_seconds":0,"rate_per_minute":1,"platform_fallback":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true,
"allow_users": true,
"cache_seconds": 0,
"rate_per_minute": 1,
"platform_fallback": true
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/ai-gateway/logs
AI 게이트웨이 호출 기록 최근 호출의 공급자, 모델, 상태, 토큰, 지연, 대체 여부를 돌려줘요. 대화 내용은 저장하지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/logs?limit=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/logs?limit=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/ai-gateway/providers
AI 공급자 추가 공급자를 키와 함께 추가해요: OpenAI 호환, Anthropic(Messages API로 바꿔 줌), Google Gemini. 주소는 공개 https만 돼요. 키는 암호화해 저장하고 다시 보여 주지 않아요. 소유자·관리자만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/providers" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","kind":"openai"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/providers', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"kind": "openai"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/ai-gateway/providers/{id}
AI 공급자 끄기·켜기 설정과 키는 두고 공급자를 쓰지 않거나 다시 써요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/providers/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/providers/ID', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/ai-gateway/providers/{id}
AI 공급자 삭제 공급자와 저장한 키를 지워요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/providers/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/providers/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/ai-gateway/budgets
AI 게이트웨이 예산 프로젝트의 AI 게이트웨이 예산을 달러로 정해요(하루·주·달, UTC). 다 쓰면 다음 기간까지 호출을 거절해요. 적지 않은 값은 그대로 둬요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/budgets" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"daily_usd":"value","weekly_usd":"value","monthly_usd":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/budgets', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"daily_usd": "value",
"weekly_usd": "value",
"monthly_usd": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/ai-gateway/keys
AI 게이트웨이 키 목록 게이트웨이 키의 이름, 앞부분, 예산, 이번 달 지출, 마지막 사용 시각을 돌려줘요. 키 자체는 돌려주지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/ai-gateway/keys
AI 게이트웨이 키 만들기 앱 하나, 또는 프로젝트가 AI를 되파는 고객 한 명에게 줄 게이트웨이 키(bwai_…)를 예산·꼬리표·분당 한도와 함께 만들어요. 키는 이 응답에서 한 번만 보여요. 꼬리표(external_ref)를 단 키는 프로젝트당 50개 제한에 들지 않아요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/ai-gateway/keys/{id}/limits
AI 게이트웨이 키 한도 게이트웨이 키 하나의 분당 요청 수와 분당 토큰 수 한도를 바꿔요. 모든 서버가 같은 수를 세요. 적지 않은 값은 그대로 두고, null이면 한도를 없애요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys/ID/limits" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"rate_per_minute":"value","tokens_per_minute":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys/ID/limits', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"rate_per_minute": "value",
"tokens_per_minute": "value"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/ai-gateway/aliases
AI 모델 별칭 부르는 사람이 쓰는 모델 이름(별칭)과 실제로 보낼 모델을 정해요. 별칭마다 맨 앞에 넣을 시스템 지침을 둘 수 있어요. 응답의 model은 별칭으로 나가요. 보낸 목록이 지금 목록을 통째로 바꿔요. aliases_only를 켜면 별칭 말고는 부를 수 없고 /models도 별칭만 보여요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/aliases" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"aliases":[{"alias":"value","target":"hello","system_prompt":"value"}]}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/aliases', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"aliases": [
{
"alias": "value",
"target": "hello",
"system_prompt": "value"
}
]
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/ai-gateway/hooks
AI 게이트웨이 훅 게이트웨이 키로 부른 호출마다 물어보고 알려 줄 https 주소를 정해요. ai.before에 2xx가 아니거나 timeout_ms 안에 답이 없으면 호출을 거절해요(402는 잔액 부족으로 그대로 전해요). ai.after에는 사용량·비용·상태를 보내고, 받지 못하면 하루 동안 다시 보내요. 응답에 서명 비밀이 있어요. url을 null로 하면 꺼요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/hooks" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"url":"https://example.com/hook","timeout_ms":200}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/hooks', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"url": "https://example.com/hook",
"timeout_ms": 200
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/ai-gateway/keys/{id}
AI 게이트웨이 키 예산 게이트웨이 키 하나의 예산을 바꿔요. 적지 않은 값은 그대로 둬요. 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"daily_usd":"value","weekly_usd":"value","monthly_usd":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys/ID', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"daily_usd": "value",
"weekly_usd": "value",
"monthly_usd": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/ai-gateway/keys/{id}
AI 게이트웨이 키 폐기 게이트웨이 키를 폐기해요. 30초 안에 모든 서버에서 거절돼요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys/ID" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/keys/ID', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/ai-gateway/spend
AI 게이트웨이 지출 오늘·이번 주·이번 달 지출과 예산, 하루별·모델별·키별 지출을 달러로 돌려줘요. 자기 키로 부른 공급자는 정가로 계산한 추정이에요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/spend?days=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/ai-gateway/spend?days=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/middleware
미들웨어 설정 사이트 미들웨어(middleware.ts)를 실행하는지와 시간 한도를 돌려줘요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/middleware" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/middleware', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/middleware
미들웨어 설정 바꾸기 사이트 미들웨어를 끄거나 켜고, 시간 한도(100~5000ms)를 정해요. 끄면 다시 배포하지 않아도 미들웨어 없이 서빙해요. 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/middleware" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"enabled":true,"timeout_ms":100}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/middleware', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"enabled": true,
"timeout_ms": 100
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/branches
DB 브랜치 목록 데이터베이스 브랜치 목록이에요: 이름, 브랜치의 ref(다른 도구에 그대로 써요), git 브랜치, 상태(creating·ready·merging·resetting·failed·deleting), 크기, 만료 시각. 자동 브랜치 설정도 와요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/branches
DB 브랜치 만들기 마이그레이션(apply_migrations 기록)을 다시 실행하고 시드를 넣어 미리보기 데이터베이스를 만들어요. 데이터는 with_data일 때만 복사해요. 브랜치는 ref가 따로 있어 모든 도구에 그 ref를 써요. git_branch를 주면 그 프리뷰 배포가 이걸 써요. Pro부터 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","git_branch":"value","with_seed":true,"with_data":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"git_branch": "value",
"with_seed": true,
"with_data": true
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/branching
자동 DB 브랜치 설정 미리보기로 배포되는 git 브랜치마다 DB 브랜치를 자동으로 만들지, 모든 브랜치에 넣을 시드 SQL, 쓰지 않는 브랜치를 남겨 둘 날짜(1~90일, 배포할 때마다 연장). 소유자·관리자만 할 수 있어요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branching" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"automatic":true,"seed_sql":"value","lifetime_days":1}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branching', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"automatic": true,
"seed_sql": "value",
"lifetime_days": 1
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/branches/{name}/merge
DB 브랜치 병합 브랜치에만 있는 마이그레이션을 버전 순으로 운영 프로젝트에 적용해요. 하나씩 트랜잭션으로 실행하고 실패하면 그것만 되돌리고 멈춰요. 데이터는 안 옮겨요. 브랜치 스키마는 apply_migrations로 바꿔야 병합돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches/my-name/merge" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches/my-name/merge', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/branches/{name}/reset
DB 브랜치 초기화 브랜치의 데이터베이스를 지우고 프로젝트의 마이그레이션과 시드로 다시 만들어요. 브랜치의 데이터와 사용자는 모두 사라지고 백업은 남지 않아요. confirm에 브랜치 이름을 그대로 넣어야 해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches/my-name/reset" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches/my-name/reset', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/branches/{name}
DB 브랜치 삭제 브랜치와 그 데이터베이스·키를 지워요. 되돌릴 수 없으니 confirm에 브랜치 이름을 그대로 넣어야 해요. git 브랜치를 지우거나 풀 리퀘스트를 닫으면 자동으로 지워져요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/branches/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/queues
대기열 목록 대기열마다 메시지 수, 지금 읽을 수 있는 수, 보관된 수, 가장 오래된 메시지 나이예요. enabled는 pgmq 설치 여부, exposed는 데이터 API(pgmq_public)로 부를 수 있는지예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/queues/metrics
큐 지표 5분마다 잰 기록으로 큐마다 지금 대기 수·읽을 수 있는 메시지·가장 오래 기다린 시간·보관 수와, 전체의 시간별 대기·보낸·처리된 수를 돌려줘요. 기본 24시간, 최대 168시간.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/metrics?hours=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/metrics?hours=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/queues
대기열 만들기 대기열을 만들어요(pgmq.create, 처음이면 pgmq도 설치). 메시지는 pgmq.q_<이름> 표에 있고, SQL에서 pgmq.send(이름, 메시지)로 넣고 pgmq.read(이름, 초, 개수)로 읽어요. 전용 데이터베이스에서만 돼요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name"
}),
})
const result = await response.json()
PUT /api/v1/projects/{ref}/queues/api
대기열을 데이터 API로 열기 true면 pgmq_public 스키마를 만들어 supabase.schema("pgmq_public").rpc("send", …)로 부르게 해요. 부른 사람 권한으로 실행되니 대기열 표에 권한과 접근 규칙을 주세요. 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/api" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"exposed":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/api', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"exposed": true
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/queues/{name}
대기열 삭제 대기열과 그 메시지, 보관함을 지워요(pgmq.drop_queue). 되돌릴 수 없으니 confirm에 대기열 이름을 그대로 넣어야 해요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/queues/{name}/purge
대기열 비우기 대기열의 메시지를 모두 지워요(pgmq.purge_queue). 보관함은 그대로 둬요. 되돌릴 수 없으니 confirm에 대기열 이름을 그대로 넣어야 해요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name/purge" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"confirm":"my-project"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name/purge', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"confirm": "my-project"
}),
})
const result = await response.json()
POST /api/v1/projects/{ref}/queues/{name}/messages
대기열에 메시지 넣기 메시지(JSON) 하나를 대기열에 넣어요(pgmq.send). delay초 동안은 읽히지 않아요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name/messages" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"message":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name/messages', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"message": "value"
}),
})
const result = await response.json()
GET /api/v1/projects/{ref}/queues/{name}/messages
대기열 메시지 보기 대기열의 앞쪽 메시지를 가져가지 않고 봐요. 읽음 횟수도 가시성 시간도 바꾸지 않아서 작업자가 받을 메시지를 가로채지 않아요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name/messages?limit=1" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/queues/my-name/messages?limit=1', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/vault
Vault 비밀 목록 Vault에 저장한 비밀의 이름과 설명. 값은 돌려주지 않아요. 프로젝트의 코드는 비밀 키로 select decrypted_secret from vault.decrypted_secrets where name = …로 읽어요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
POST /api/v1/projects/{ref}/vault
Vault 비밀 저장 비밀 하나를 암호화해 프로젝트 데이터베이스의 vault.secrets에 저장해요(vault.create_secret). 키는 플랫폼이 갖고 있어 덤프·백업에는 암호문만 남아요. 처음이면 Vault를 켜요. 소유자·관리자만 할 수 있어요.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"name":"my-name","value":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"name": "my-name",
"value": "value"
}),
})
const result = await response.json()
PATCH /api/v1/projects/{ref}/vault/{name}
Vault 비밀 바꾸기 비밀의 값이나 설명을 바꿔요(vault.update_secret). 소유자·관리자만 할 수 있어요.
curl -X PATCH "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"value":"value","description":"value"}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault/my-name', {
method: 'PATCH',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"value": "value",
"description": "value"
}),
})
const result = await response.json()
DELETE /api/v1/projects/{ref}/vault/{name}
Vault 비밀 삭제 비밀 하나를 지워요. 소유자·관리자만 할 수 있어요.
curl -X DELETE "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault/my-name" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/vault/my-name', {
method: 'DELETE',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
GET /api/v1/projects/{ref}/network-restrictions
DB 접속 제한 보기 데이터베이스 직접 연결(5432·6543)에 접속할 수 있는 주소와 TLS 강제 여부. restricted가 false면 모든 주소가 접속할 수 있어요. your_address_allowed는 이 요청을 보낸 주소가 허용되는지예요.
curl "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network-restrictions" \
-H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network-restrictions', {
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()
PUT /api/v1/projects/{ref}/network-restrictions
DB 접속 제한 바꾸기 직접 연결을 허용할 주소(CIDR, 100개까지)와 TLS 강제를 바꿔요. allow_all이면 모두 허용해요. 지금 요청한 주소가 목록에 없으면 confirm이 필요해요(콘솔·API는 영향 없어요). 소유자·관리자만 돼요.
curl -X PUT "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network-restrictions" \
-H "Authorization: Bearer $ONEEND_TOKEN" \
-H "content-type: application/json" \
-d '{"allowed_cidrs":["value"],"allow_all":true,"enforce_ssl":true,"confirm":true}'
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/network-restrictions', {
method: 'PUT',
headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}`, 'content-type': 'application/json' },
body: JSON.stringify({
"allowed_cidrs": [
"value"
],
"allow_all": true,
"enforce_ssl": true,
"confirm": true
}),
})
const result = await response.json()