One Server

문서 · 레퍼런스

관리 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을 받아요.

권한가진 역할
audit.read소유자·관리자
billing.manage소유자·관리자·결제 담당
data.write소유자·관리자·개발자
project.admin소유자·관리자
secrets.read소유자·관리자·개발자
team.manage소유자·관리자

언어

오류 문장과 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": "…" } }
상태 코드설명
200성공. 본문은 결과 JSON이에요.
400요청이 올바르지 않거나 작업이 거절됐어요. error.message에 이유가 있어요.
401토큰이 없거나, 올바르지 않거나, 만료됐어요.
402
403토큰의 범위(read/write)나 조직 안의 역할이 모자라거나, 조직이 2단계 인증을 요구해요.
404프로젝트나 대상이 없거나, 이 토큰으로는 보이지 않아요.
409지금은 할 수 없어요. 예를 들어 프로젝트 데이터베이스를 아직 만드는 중이에요.
413본문이 이 경로의 한도보다 커요.
422
429
500서버가 결과를 다시 읽지 못했어요. 잠시 뒤 다시 시도하세요.
502

note가 있으면 다음에 할 일을 알려 주는 문장이에요.

계정과 리전

메서드경로설명
GET/API 버전
GET/me내 계정
GET/regions리전 목록
POST/regions/requests리전 요청
GET/server-sizes서버 크기와 가격
GET/imports/sources가져올 곳
POST/imports가져오기 시작
GET/imports/{id}가져오기 진행 상황

GET /api/v1/

API 버전 이 API의 이름과 버전을 돌려줘요. 토큰이 맞는지 확인할 때 써요.

이름설명
토큰 범위없음
역할조직의 모든 구성원
응답객체: name, version
상태 코드200 · 400 · 401
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)예요. 무엇부터 할지 모를 때 먼저 부르세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구whoami
응답객체: email, organisation, projects, scopes, zone, read_only, next
상태 코드200 · 400 · 401 · 403
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 전에 확인하세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_regions
응답객체 배열: code, name, country, status, is_default, can_create
상태 코드200 · 400 · 401 · 403
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로 바로 만드세요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구request_region
본문 한도256 KiB
응답객체: region, name, recorded
상태 코드200 · 400 · 401 · 403 · 413
이름위치형식필수설명
region본문string예list_regions가 can_create=false로 알려준 코드.
note본문string아니요거기에 무엇을 두려는지, 왜 그 리전이어야 하는지. 선택 사항이지만 담당자가 연락할 때 이것부터 읽어요.
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가 비어 있어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_server_sizes
응답객체: note
상태 코드200 · 400 · 401 · 403
이름위치형식필수설명
region쿼리string아니요한 지역만 볼 때 그 코드(list_regions의 code). 비우면 모든 지역.
currency쿼리string, KRW | USD아니요KRW 또는 USD. 비우면 조직의 결제 통화.
curl "https://end.blackall.ai/api/v1/server-sizes?region=kr&currency=KRW" \
  -H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/server-sizes?region=kr&currency=KRW', {
  headers: { authorization: `Bearer ${process.env.ONEEND_TOKEN}` },
})
const result = await response.json()

GET /api/v1/imports/sources

가져올 곳 이 조직에 연결한 원본 계정(Supabase, Vercel, PostgreSQL)마다 프로젝트 목록과 지금까지의 가져오기를 봐요. 계정 연결은 토큰이 대화에 남지 않게 콘솔(connect_url)에서 해요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구import_sources
응답객체: organisation, connect_url, sources, imports
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
org쿼리string아니요조직의 id나 이름. 비우면 이 토큰이 닿는 첫 조직.
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에 세션 풀러 연결 문자열이 필요해요(쓰고 지워요). 다시 시작하면 바뀐 것만 옮겨요. 소유자·관리자·개발자만 돼요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구start_import
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
org쿼리string아니요조직의 id나 이름. 비우면 이 토큰이 닿는 첫 조직.
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}

가져오기 진행 상황 콘솔의 가져오기 진행 화면과 같아요. 옮길 곳마다 단계(스키마, 로그인 사용자, 데이터, 파일, 예약 작업…)의 상태와 수, 옮기지 않는 것과 이유, 확인할 것을 보여줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_import
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
id경로string예가져오기 id.
org쿼리string아니요조직의 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/projects프로젝트 목록
POST/projects프로젝트 만들기
GET/projects/{ref}프로젝트 하나
PATCH/projects/{ref}이름 바꾸기
POST/projects/{ref}/pause프로젝트 일시정지
POST/projects/{ref}/resume프로젝트 다시 시작
GET/projects/{ref}/archive데이터베이스 보관 상태
POST/projects/{ref}/archive/restore보관한 데이터베이스 복원
POST/projects/{ref}/archive/download보관 파일 내려받기 주소
DELETE/projects/{ref}프로젝트 삭제
POST/projects/{ref}/retry-provisioning준비 실패한 프로젝트 다시 시도

GET /api/v1/projects

프로젝트 목록 이 계정의 프로젝트와 각각의 API 주소를 돌려줘요. status는 ready(쓸 수 있음), provisioning(데이터베이스를 만드는 중, 몇 초), failed(retry_provisioning), paused예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_projects
응답객체 배열: ref, name, organisation, organisation_id, region, api_url, paused, archive_at, archive_purge_at, created_at
상태 코드200 · 400 · 401 · 403
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가 된 뒤 표·키를 쓰세요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구create_project
본문 한도256 KiB
응답객체: ref, name, organisation, region, api_url, status, created_at
상태 코드200 · 400 · 401 · 403 · 404 · 413 · 502
이름위치형식필수설명
wait쿼리integer, min 0, max 120아니요데이터베이스가 준비될(status: ready) 때까지 기다릴 초. 기본 0은 바로 답해요. 보통 몇 초면 돼요.
name본문string아니요사람이 읽는 이름.
region본문string아니요어디에 둘지. list_regions가 쓸 수 있는 값을 알려줘요. 비우면 기본 리전.
org본문string아니요만들 조직의 id나 이름(list_projects의 organisation_id·organisation). 비우면 프로젝트를 만들 수 있는 첫 조직.
wait본문integer, min 0, max 120아니요데이터베이스가 준비될(status: ready) 때까지 기다릴 초. 기본 0은 바로 답해요. 보통 몇 초면 돼요.
tier본문string아니요이 프로젝트만의 서버 크기. list_server_sizes가 알려준 값(예: 4gb)이나 default(요금제의 기본 크기)를 주면 만든 직후 서버를 요청해요. 비우면 공용 서버에서 시작해요.
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로 찾아 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_projects
응답객체 배열: ref, name, organisation, organisation_id, region, api_url, paused, archive_at, archive_purge_at, created_at
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예
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)와 주소는 바뀌지 않아요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구rename_project
본문 한도256 KiB
응답객체: ref, name, organisation
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string아니요새 프로젝트 이름.
organisation본문string아니요새 조직 이름.
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일 넘게 멈추면 데이터베이스를 보관 저장소로 옮겨요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구pause_project
응답객체: ref, paused, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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일 동안 쓰지 않아 멈춘 프로젝트도 이걸로(또는 새 배포로) 다시 켜요. 예약 작업은 놓친 실행을 몰아서 하지 않고 다음 일정부터 돌아요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구resume_project
응답객체: ref, paused
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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를 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_project_archive
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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). 보관 파일이 지워졌으면 빈 데이터베이스를 만들어요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구restore_project_archive
응답객체: ref, restore, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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시간 동안 내려받을 수 있는 서명 주소를 만들어요. 이유를 함께 적어야 하고, 개인정보 접속기록에 남아요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_archive_download_url
본문 한도256 KiB
응답객체: ref, url, expires_at, bytes, format
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
reason본문string, min length 4, max length 300예내려받는 이유. 접속기록에 남아요.
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에 프로젝트 이름을 넣으세요. 마지막 프로젝트는 못 지워요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구delete_project
본문 한도256 KiB
응답객체: ref, deleted
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
confirm본문string예프로젝트 이름. list_projects의 name과 정확히 같아야 해요.
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

준비 실패한 프로젝트 다시 시도 데이터베이스를 만들지 못한 프로젝트를 다시 준비해요. 다른 도구가 "만들지 못했어요"로 거절할 때 쓰세요. 프로젝트를 새로 만들지 마세요. 요금만 두 배가 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구retry_provisioning
응답객체: ref, retried, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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/projects/{ref}/keysAPI 키 가져오기
GET/projects/{ref}/api-keys이름 붙은 API 키 목록
POST/projects/{ref}/api-keysAPI 키 만들기
DELETE/projects/{ref}/api-keys/{id}API 키 폐기
GET/projects/{ref}/signing토큰 서명 방식
PUT/projects/{ref}/signing토큰 서명 방식 바꾸기
POST/projects/{ref}/signing/rotate키 교체
DELETE/projects/{ref}/signing/keys/{kid}예전 키 폐기

GET /api/v1/projects/{ref}/keys

API 키 가져오기 프로젝트 주소와 두 키예요. 비밀 키는 접근 규칙을 무시하니 서버에서만 쓰세요(쓰기 권한 토큰 필요). 프론트엔드용이면 only: "publishable"로 부르세요: 주소와 공개 키만 오고 읽기 권한 토큰으로도 돼요.

이름설명
토큰 범위write
역할secrets.read 소유자·관리자·개발자
MCP 도구get_project_keys
응답객체: ref, api_url, publishable_key, secret_key, key_version
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
only쿼리string, publishable아니요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_ 키의 이름, 종류, 앞부분, 마지막 사용 시각, 폐기 여부예요. 비밀 키의 값은 돌려주지 않아요. 공개 키는 값도 줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_api_keys
응답객체 배열: id, name, kind, prefix, publishable_key, created_at, created_by, last_used_at, revoked_at
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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개까지예요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_api_key
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
kind본문string, publishable | secret예publishable for browsers, secret for servers.
name본문string, min length 1, max length 60예어디에 쓰는 키인지. 예: 결제 서버
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초 안에 그 키로 오는 요청이 거부돼요. 다른 키는 그대로예요. 되돌릴 수 없어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구revoke_api_key
응답객체: revoked, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_api_keys의 id
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 중 무엇으로 서명하는지와, 지금 받아 주는 예전 키(유예 중인 키)를 보여줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_jwt_signing
응답객체: ref, alg, keys, grace_hours
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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)로 토큰을 확인할 수 있어요. 이미 받은 토큰은 만료될 때까지 그대로 통해요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_jwt_signing
본문 한도256 KiB
응답객체: ref, alg, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
alg본문string, HS256 | ES256예HS256 or ES256.
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에 프로젝트 이름이 필요해요. 사용자가 요청할 때만, 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구rotate_signing_key
본문 한도256 KiB
응답객체: ref, key_version, grace_hours, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
grace_hours본문integer, 0 | 1 | 24 | 168아니요How many hours the old key is still accepted: 0, 1, 24 or 168.
confirm본문string아니요grace_hours가 0(또는 비움)일 때만: 프로젝트 이름. list_projects의 name과 정확히 같아야 해요.
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인 것이에요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구retire_signing_key
응답객체: ref, kid, retired, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
kid경로string예The kid from get_jwt_signing.
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/projects/{ref}/advisors보안·성능 점검
GET/projects/{ref}/tables/{table}/csv표를 CSV로 내보내기
POST/projects/{ref}/tables/{table}/csvCSV를 표로 가져오기
GET/projects/{ref}/tables표 목록
GET/projects/{ref}/policies접근 규칙 목록
GET/projects/{ref}/rows/{table}표 내용 보기
GET/projects/{ref}/migrations마이그레이션 기록
POST/projects/{ref}/migrations마이그레이션 적용
DELETE/projects/{ref}/migrations/{version}마이그레이션 기록 지우기
GET/projects/{ref}/schema스키마를 SQL로
GET/projects/{ref}/types/typescriptTypeScript 타입 만들기
POST/projects/{ref}/sql/querySQL 조회 (읽기 전용)
POST/projects/{ref}/sqlSQL 실행 (변경)
GET/projects/{ref}/database데이터베이스 연결 정보
POST/projects/{ref}/database/password데이터베이스 비밀번호 새로 만들기
GET/projects/{ref}/mysqlMySQL 데이터베이스 목록
POST/projects/{ref}/mysqlMySQL 데이터베이스 만들기
PATCH/projects/{ref}/mysql/{name}MySQL 데이터베이스를 앱에 연결
DELETE/projects/{ref}/mysql/{name}MySQL 데이터베이스 지우기
GET/projects/{ref}/mysql/{name}/connectionMySQL 연결 정보
GET/projects/{ref}/mysql/{name}/backupsMySQL 백업 목록
POST/projects/{ref}/mysql/{name}/backupsMySQL 지금 백업
POST/projects/{ref}/mysql/{name}/restoreMySQL 백업으로 복원
GET/projects/{ref}/extensionsDB 확장 목록
PUT/projects/{ref}/extensions/{name}DB 확장 켜기
DELETE/projects/{ref}/extensions/{name}DB 확장 끄기
GET/projects/{ref}/database/move전용 데이터베이스로 옮기기 상태
POST/projects/{ref}/database/move전용 데이터베이스로 옮기기
GET/projects/{ref}/database/dedicated-disk전용 디스크
POST/projects/{ref}/database/dedicated-disk전용 디스크로 옮기기
POST/projects/{ref}/database/dedicated-disk/shrink디스크 줄이기
GET/projects/{ref}/realtime실시간 켠 표
PUT/projects/{ref}/realtime/{table}표의 실시간 켜기·끄기

GET /api/v1/projects/{ref}/advisors

보안·성능 점검 데이터베이스 구조의 보안·성능 문제를 찾아요: RLS가 꺼진 표, 누구나 쓰는 규칙, 규칙을 무시하는 뷰, search_path 없는 security definer 함수, 사용자 표를 내보내는 뷰, 인덱스 없는 외래 키, 기본 키 없는 표, 중복 인덱스, 행마다 uid()를 부르는 규칙. 고칠 SQL(remedy)도 줘요. 표나 규칙을 바꾼 뒤 부르세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_advisors
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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, ""는 빈 문자열이에요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구export_table_csv
응답객체: ref, table, rows, bytes, truncated, csv
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
table경로string예표 이름 (list_tables).
sort쿼리string아니요이 열 순서로. 비우면 표의 기본 순서.
desc쿼리boolean아니요true면 큰 것부터.
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이나 기본값이에요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구import_table_csv
본문 한도4096 KiB
응답객체: ref, table, inserted, columns
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
table경로string예표 이름 (list_tables).
csv본문string예CSV 내용. 첫 줄은 열 이름.
columns본문array<string>아니요CSV의 열마다 넣을 표의 열 이름, 건너뛸 열은 "". 첫 줄과 길이가 같아야 해요. 비우면 같은 이름끼리.
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이면 공개 키로는 아무것도 보이지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_tables
응답객체 배열: name, approximate_rows, row_level_security, policies, columns
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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

접근 규칙 목록 어떤 표의 어떤 동작이 누구에게 열려 있는지 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_policies
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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을 쓰세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구read_rows
응답객체: columns, rows
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
table경로string예표 이름.
limit쿼리integer, min 1, max 200아니요기본 50줄.
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 표에 있어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_migrations
응답객체: ref, ledger, migrations
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 알려 줘요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구apply_migrations
본문 한도8192 KiB
응답객체: ref, applied, recorded_only, already_applied, drifted
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
migrations본문array<object>, max items 500예The migrations, each with version, name and sql.
include_all본문boolean아니요이미 적용된 마지막 버전보다 앞선 버전도 적용해요. 기본 false.
record_only본문boolean아니요실행하지 않고 적용한 것으로 기록만 해요. 기본 false.
dry_run본문boolean아니요무엇이 적용될지만 알려줘요.
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}

마이그레이션 기록 지우기 마이그레이션 하나를 적용하지 않은 것으로 되돌려요. 기록만 지우고 그 마이그레이션이 만든 것은 그대로 둬요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_migration_record
응답객체: ref, version, removed, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
version경로string, pattern ^[0-9]{1,32}$예The version from list_migrations.
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로 돌려줘요. 행 데이터와 권한은 들어 있지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구dump_schema
응답객체: ref, sql, objects
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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 타입을 만들어요. 스키마를 바꾼 뒤 다시 부르세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구generate_typescript_types
응답객체: ref, schema, types
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
schema쿼리string아니요기본 public. 프로젝트가 만든 스키마(list_schemas의 name)도 돼요.
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

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구query_sql
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
sql본문string예실행할 조회 한 문장.
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로 알려 줘요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구run_sql
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
sql본문string예실행할 SQL 한 문장.
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]로 나와요.

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구get_database_connection
응답객체: ref, available, host, database, user, password_set, direct, pooler, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 받아요(빌드 제외). 배포한 코드가 모든 행을 읽게 되니 사용자가 원할 때만 켜요. 빼면 넘기던 것도 멈춰요. 사용자가 요청할 때만 쓰고, 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구reset_database_password
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
keep_for_deploys본문boolean아니요true: 운영 배포에 DATABASE_URL로 넘겨요(암호화해 저장). 없거나 false: 보관하지 않고, 넘기던 것도 멈춰요.
confirm본문string예프로젝트 이름. list_projects의 name과 정확히 같아야 해요.
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이 없어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_mysql_databases
응답객체: ref, available, max, apps, databases
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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을 받아요(빌드 제외). 매일 밤 백업돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_mysql_database
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string, pattern ^[a-z][a-z0-9_]{0,31}$예영문 소문자로 시작하고 영문 소문자, 숫자, 밑줄(_)로 32자까지. 예: wordpress
app본문string아니요이 데이터베이스를 받을 앱 이름. 비우면 프로젝트 전체용
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이면 프로젝트 전체용이 돼요. 앱 하나에는 데이터베이스 하나만 연결돼요. 실행 중인 서버는 다시 시작하거나 다시 배포하면 바뀐 값을 받아요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구bind_mysql_database
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The MySQL database name
app본문string예앱 이름, 또는 프로젝트 전체용이면 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_*를 받지 않아요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구delete_mysql_database
본문 한도256 KiB
응답객체: ref, name, deleted, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The MySQL database name
confirm본문string예MySQL 데이터베이스 이름. name과 정확히 같아야 해요.
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)를 돌려줘요. 주소는 이 서버 안의 앱에서만 닿아요. 비밀번호는 쓰기 권한 토큰에만 보여요.

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구get_mysql_connection
응답객체: ref, name, host, port, database, user, password, url, variables
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The MySQL database name
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 데이터베이스의 백업(매일 밤 자동, 직접 만든 것, 복원 직전 것)과 복원 기록을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_mysql_backups
응답객체: ref, name, backups, restores
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The MySQL database name
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일 보관돼요. 매일 밤 백업은 따로 자동으로 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_mysql_backup
응답객체: ref, name, id, status, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The MySQL database name
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로 되돌릴 수 있어요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구restore_mysql_backup
본문 한도256 KiB
응답객체: ref, name, restore_id, status, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The MySQL database name
backup_id본문string예list_mysql_backups의 백업 id
confirm본문string예MySQL 데이터베이스 이름. name과 정확히 같아야 해요.
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)처럼 바로 써요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_extensions
응답객체: ref, extensions
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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. 목록 밖의 확장은 거절돼요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구enable_extension
응답객체: ref, extension
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예확장 이름: vector, postgis, citext, hstore, uuid-ossp, pgcrypto, ltree, fuzzystrmatch, btree_gin, btree_gist, intarray, tablefunc
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에 확장 이름이 필요해요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구disable_extension
본문 한도256 KiB
응답객체: ref, extension
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The extension name, as in list_extensions.
confirm본문string예확장 이름. name과 정확히 같아야 해요.
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로 요청하세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_database_move
응답객체: ref
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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부터, 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구move_to_dedicated_database
응답객체: ref, note
상태 코드200 · 400 · 401 · 402 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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)과 지금 크기를 보여 줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_dedicated_disk
응답객체: ref
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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는 언제든, 다른 유료 요금제는 기준을 넘으면 돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구request_dedicated_disk
응답객체: ref, note
상태 코드200 · 400 · 401 · 402 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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). 옮기는 동안 쓰기는 실패하고 읽기는 돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구shrink_dedicated_disk
응답객체: ref, note
상태 코드200 · 400 · 401 · 402 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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

실시간 켠 표 변경을 실시간으로 알리는 표 목록. 여기 없는 표를 구독하면 아무것도 오지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_realtime_tables
응답객체: ref, tables
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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}

표의 실시간 켜기·끄기 표 하나의 변경 알림을 켜거나 꺼요. 알림도 접근 규칙을 통과한 줄만 가요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_realtime
본문 한도256 KiB
응답객체: ref, tables
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
table경로string예The table name.
enabled본문boolean예true to turn it on, false to turn it off.
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/projects/{ref}/users서비스 가입자 목록
POST/projects/{ref}/users/{id}/links로그인 링크 만들기
PATCH/projects/{ref}/users/{id}서비스 가입자 바꾸기
POST/projects/{ref}/users/import서비스 가입자 한꺼번에 가져오기
POST/projects/{ref}/users서비스 가입자 추가
GET/projects/{ref}/auth/providers소셜 로그인 설정 보기
PUT/projects/{ref}/auth/providers/{provider}소셜 로그인 켜기
PATCH/projects/{ref}/auth/providers/{provider}소셜 로그인 껐다 켜기
DELETE/projects/{ref}/auth/providers/{provider}소셜 로그인 지우기
GET/projects/{ref}/auth/redirect-urls로그인 후 돌아갈 주소 목록
POST/projects/{ref}/auth/redirect-urls돌아갈 주소 추가
DELETE/projects/{ref}/auth/redirect-urls돌아갈 주소 제거
GET/projects/{ref}/auth/sms문자 로그인 설정 보기
PUT/projects/{ref}/auth/sms문자 로그인 설정
DELETE/projects/{ref}/auth/sms문자 로그인 지우기
GET/projects/{ref}/auth/smtpSMTP 설정 보기
PUT/projects/{ref}/auth/smtpSMTP 설정
DELETE/projects/{ref}/auth/smtpSMTP 설정 지우기
POST/projects/{ref}/auth/smtp/testSMTP 시험 메일 보내기
GET/projects/{ref}/auth/templates이메일 템플릿 보기
GET/projects/{ref}/auth/templates/{type}이메일 템플릿 보기
PUT/projects/{ref}/auth/templates/{type}이메일 템플릿 저장
DELETE/projects/{ref}/auth/templates/{type}이메일 템플릿 되돌리기
POST/projects/{ref}/auth/templates/{type}/preview이메일 템플릿 미리보기
GET/projects/{ref}/auth/ssoSAML SSO 보기
DELETE/projects/{ref}/auth/sso/{id}SAML SSO 지우기
PUT/projects/{ref}/auth/anonymous익명 로그인 켜기·끄기
DELETE/projects/{ref}/users/{id}가입자 삭제

GET /api/v1/projects/{ref}/users

서비스 가입자 목록 이 프로젝트 서비스의 가입자예요(플랫폼 계정과 별개). 한 번에 200명까지 오고 total이 전체 인원이에요. has_more가 true면 offset을 올려 다시 부르세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_users
응답객체: users, total, limit, offset, has_more
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
limit쿼리integer, min 1, max 200아니요한 번에 받을 인원. 기본값 50, 최대 200.
offset쿼리integer, min 0아니요건너뛸 인원. 기본값 0.
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()

PATCH /api/v1/projects/{ref}/users/{id}

서비스 가입자 바꾸기 가입자 한 명의 이메일, 비밀번호, 이메일 확인, 정지, 메타데이터(합쳐짐)를 바꿔요. 비밀번호를 바꾸거나 정지하면 로그인이 모두 끊겨요. 비밀번호는 10자 이상, 유출된 것은 거절돼요. 사용자가 요청할 때만 쓰세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구update_user
본문 한도256 KiB
응답객체: ref, user
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_users의 id (UUID).
email본문string아니요새 이메일.
password본문string아니요새 비밀번호 (10자 이상).
email_confirm본문boolean아니요true면 이메일을 확인된 것으로 표시해요.
ban_duration본문string아니요정지 기간. 예: 24h, 30m, 876000h(사실상 영구). none이면 정지를 풀어요.
user_metadata본문object아니요사용자가 바꿀 수 있는 메타데이터에 합칠 값.
app_metadata본문object아니요서버만 바꾸는 메타데이터에 합칠 값(역할, 요금제 등).
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면 검사만 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구import_users
본문 한도256 KiB
응답객체: ref, dry_run, found, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
users본문array<object>예The accounts: { email, id?, encrypted_password?, email_confirmed?, user_metadata?, app_metadata? }.
dry_run본문boolean아니요Check the list and import nothing.
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자 이상이어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구add_user
본문 한도256 KiB
응답객체: added
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
email본문string예The user's email address.
password본문string예At least 10 characters.
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은 제공자 콘솔에 붙여 넣을 주소예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_auth_providers
응답객체: ref, anonymous_sign_in, providers
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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이 한 번 와요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_auth_provider
본문 한도256 KiB
응답객체: provider, enabled, callback_url
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider경로string, pattern ^(google|kakao|naver|apple|github|gitlab|microsoft|facebook|line|discord|x|bitbucket|figma|linkedin_oidc|notion|twitch|slack_oidc|spotify|zoom|azure|keycloak|workos|twitter|slack|custom:[a-z0-9][a-z0-9_-]{0,39})$예로그인 제공자. google(구글), kakao(카카오), naver(네이버), apple(애플), github(GitHub), gitlab(GitLab), microsoft(Microsoft), facebook(Facebook), line(LINE), discord(Discord), x(X), bitbucket(Bitbucket), figma(Figma), linkedin_oidc(LinkedIn), notion(Notion), twitch(Twitch), slack_oidc(Slack), spotify(Spotify), zoom(Zoom), azure(Microsoft Entra ID), keycloak(Keycloak), workos(WorkOS), twitter(Twitter (OAuth 1.0a)), slack(Slack (legacy)), 또는 직접 등록하는 제공자 custom:<이름>(영문 소문자·숫자·-·_, 40자까지)
client_id본문string아니요The client ID from the provider's console.
client_secret본문string아니요빈 문자열이면 이미 저장된 시크릿을 그대로 둬요. 새 제공자에는 반드시 필요해요.
enabled본문boolean아니요기본값은 켜짐이에요.
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}

소셜 로그인 껐다 켜기 저장된 자격증명은 두고 제공자만 껐다 켜요. 다시 켤 때 시크릿을 새로 넣지 않아도 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_auth_provider_enabled
본문 한도256 KiB
응답객체: provider, enabled
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider경로string, pattern ^(google|kakao|naver|apple|github|gitlab|microsoft|facebook|line|discord|x|bitbucket|figma|linkedin_oidc|notion|twitch|slack_oidc|spotify|zoom|azure|keycloak|workos|twitter|slack|custom:[a-z0-9][a-z0-9_-]{0,39})$예로그인 제공자. google(구글), kakao(카카오), naver(네이버), apple(애플), github(GitHub), gitlab(GitLab), microsoft(Microsoft), facebook(Facebook), line(LINE), discord(Discord), x(X), bitbucket(Bitbucket), figma(Figma), linkedin_oidc(LinkedIn), notion(Notion), twitch(Twitch), slack_oidc(Slack), spotify(Spotify), zoom(Zoom), azure(Microsoft Entra ID), keycloak(Keycloak), workos(WorkOS), twitter(Twitter (OAuth 1.0a)), slack(Slack (legacy)), 또는 직접 등록하는 제공자 custom:<이름>(영문 소문자·숫자·-·_, 40자까지)
enabled본문boolean예true to turn it on, false to turn it off.
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를 쓰세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_auth_provider
응답객체: provider, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider경로string, pattern ^(google|kakao|naver|apple|github|gitlab|microsoft|facebook|line|discord|x|bitbucket|figma|linkedin_oidc|notion|twitch|slack_oidc|spotify|zoom|azure|keycloak|workos|twitter|slack|custom:[a-z0-9][a-z0-9_-]{0,39})$예로그인 제공자. google(구글), kakao(카카오), naver(네이버), apple(애플), github(GitHub), gitlab(GitLab), microsoft(Microsoft), facebook(Facebook), line(LINE), discord(Discord), x(X), bitbucket(Bitbucket), figma(Figma), linkedin_oidc(LinkedIn), notion(Notion), twitch(Twitch), slack_oidc(Slack), spotify(Spotify), zoom(Zoom), azure(Microsoft Entra ID), keycloak(Keycloak), workos(WorkOS), twitter(Twitter (OAuth 1.0a)), slack(Slack (legacy)), 또는 직접 등록하는 제공자 custom:<이름>(영문 소문자·숫자·-·_, 40자까지)
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

로그인 후 돌아갈 주소 목록 로그인이 끝난 사람을 돌려보낼 수 있는 주소예요. 여기 없는 주소로는 돌려보내지 않아요. 로그인은 되는데 아무 데도 안 간다면 여기부터 보세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_redirect_urls
응답객체: ref, urls
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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이 저장돼요. 점이 들어간 앱 스킴만 받아요. 응답에 실제로 저장된 목록이 와요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구add_redirect_url
본문 한도256 KiB
응답객체: ref, urls
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
url본문string예The address, for example https://app.example.com.
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가 돌려준 그대로 넣으세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_redirect_url
본문 한도256 KiB
응답객체: ref, urls
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
url본문string예The address, as list_redirect_urls returned it.
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, 국내만)도 돼요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_sms_settings
응답객체: ref, configured, provider, enabled, sender, allowed_countries, otp_length, otp_ttl_seconds, hourly_limit, template, key_hint, secret_hint, account_hint, credentials_readable, platform_available, providers, updated_at
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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(한국)만이고, 모르는 나라를 넣으면 해외 유료 번호 문자 사기에 노출돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_sms_settings
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider본문string, platform | solapi | nhn | aligo | twilio | messagebird | textlocal | vonage | twilio_verify예platform (the platform account, paid plans only), solapi, nhn, aligo, twilio, messagebird, textlocal, vonage or twilio_verify.
key본문string아니요Solapi API Key, NHN Cloud App Key or Aligo API Key. Empty keeps the stored one.
secret본문string아니요Solapi API Secret, NHN Cloud Secret Key or Twilio Auth Token. Empty keeps the stored one.
account본문string아니요Aligo User ID or Twilio Account SID. Empty keeps the stored one.
sender본문string아니요발신 번호. 예: 01012345678. Twilio는 +1… 번호나 MG로 시작하는 Messaging Service SID.
allowed_countries본문array<string>아니요국가 번호 목록. 예: ["82"].
otp_length본문integer, min 6, max 10아니요Digits in a code, 6 to 10. Default 6.
otp_ttl_seconds본문integer, min 60, max 3600아니요How long a code is valid, 60 to 3600 seconds. Default 300.
hourly_limit본문integer, min 1, max 100000아니요Most messages the whole project may send in an hour. Default 200.
template본문string아니요{{code}}나 {{ .Code }}가 들어간 문구. null이면 기본 문구.
enabled본문boolean아니요On by default.
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를 주세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_sms_settings
응답객체: ref, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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가 있으면(그 서버가 거부) 플랫폼 주소로 보내요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_smtp_settings
응답객체: ref, configured, enabled, sender_email, sender_name, host, port, username, password_hint, password_readable, minimum_interval_seconds, rate_limit_per_hour, last_sent_at, last_error, last_error_at, updated_at
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 확인하세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_smtp_settings
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
sender_email본문string아니요보내는 메일 주소(Sender email). 예: [email protected].
sender_name본문string아니요보내는 사람 이름(Sender name). 예: 우리 가게.
host본문string아니요SMTP 서버 주소(Host). 예: smtp.sendgrid.net.
port본문integer, 25 | 465 | 587 | 2465 | 2525아니요포트(Port). 기본 587.
username본문string아니요SMTP 사용자 이름(Username).
password본문string아니요SMTP 비밀번호(Password). 비우면 저장된 값을 써요.
minimum_interval_seconds본문integer, min 0, max 3600아니요같은 주소로 다시 보내기까지의 최소 간격(초). 기본 60.
rate_limit_per_hour본문integer, min 1, max 10000아니요프로젝트 전체가 한 시간에 보낼 수 있는 메일 수. 기본 100. 넘으면 over_email_send_rate_limit(429)로 거부돼요.
enabled본문boolean아니요false면 설정은 두고 플랫폼 발신 주소로 보내요.
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를 주세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_smtp_settings
응답객체: ref, removed, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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를 빼면 호출한 사람의 주소로 보내요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구test_smtp_settings
본문 한도256 KiB
응답객체: ref, sent, to, sender_email
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
to본문string아니요받을 주소. 빼면 내 주소.
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> }}.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_email_templates
응답객체: ref, variables, templates
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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> }}.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_email_templates
응답객체: ref, variables, templates
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
type경로string, confirmation | invite | magic_link | recovery | email_change | reauthentication | password_changed | email_changed | mfa_enrolled | mfa_removed | identity_linked | identity_unlinked예confirmation, invite, magic_link, recovery, email_change or reauthentication.
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로 확인하세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_email_template
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
type경로string, confirmation | invite | magic_link | recovery | email_change | reauthentication | password_changed | email_changed | mfa_enrolled | mfa_removed | identity_linked | identity_unlinked예confirmation, invite, magic_link, recovery, email_change or reauthentication.
subject본문string, max length 200예The subject line, up to 200 characters.
body본문string, max length 50000예본문 HTML. 예: <a href="{{ .ConfirmationURL }}">가입 확인</a>
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}

이메일 템플릿 되돌리기 한 종류의 템플릿을 지우고 기본 문구(한국어·영어·일본어)로 돌아가요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_email_template
응답객체: ref, type, removed, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
type경로string, confirmation | invite | magic_link | recovery | email_change | reauthentication | password_changed | email_changed | mfa_enrolled | mfa_removed | identity_linked | identity_unlinked예confirmation, invite, magic_link, recovery, email_change or reauthentication.
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를 주면 저장하지 않고 그 내용을, 빼면 저장된 템플릿이나 기본 문구를 보여 줘요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구preview_email_template
본문 한도256 KiB
응답객체: ref, type, custom, subject, html, text
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
type경로string, confirmation | invite | magic_link | recovery | email_change | reauthentication | password_changed | email_changed | mfa_enrolled | mfa_removed | identity_linked | identity_unlinked예confirmation, invite, magic_link, recovery, email_change or reauthentication.
subject본문string아니요A subject to try without saving.
body본문string아니요A body to try without saving.
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 })로 로그인해요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_sso_providers
응답객체: ref, acs_url, entity_id, metadata_url, new_providers_allowed, providers
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 로그인할 수 없어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_sso_provider
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_sso_providers의 id
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이에요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_anonymous_sign_in
본문 한도256 KiB
응답객체: ref, anonymous_sign_in
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean예true to turn it on, false to turn it off.
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)을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_user
본문 한도256 KiB
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_users의 id(UUID).
confirm본문string예지울 가입자의 이메일 또는 id. list_users의 email이나 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/projects/{ref}/buckets/{bucket}/empty버킷 비우기
GET/projects/{ref}/buckets/{bucket}/objects파일 목록
POST/projects/{ref}/buckets/{bucket}/objects파일 올리기
GET/projects/{ref}/buckets/{bucket}/object파일 내려받기
DELETE/projects/{ref}/buckets/{bucket}/object파일 삭제
POST/projects/{ref}/buckets/{bucket}/upload-urls파일 올리기 주소 만들기
POST/projects/{ref}/buckets/{bucket}/signed-urls서명 주소 만들기
PATCH/projects/{ref}/buckets/{bucket}버킷 설정 바꾸기
DELETE/projects/{ref}/buckets/{bucket}버킷 삭제
GET/projects/{ref}/buckets버킷 목록
POST/projects/{ref}/buckets버킷 만들기

POST /api/v1/projects/{ref}/buckets/{bucket}/empty

버킷 비우기 버킷 안의 파일을 모두 지워요. 버킷은 남아요. 되돌릴 수 없으니 사용자가 분명히 요청했을 때만 쓰고, confirm에 버킷 이름을 그대로 넣어야 해요. removed가 지운 파일 수예요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구empty_bucket
본문 한도256 KiB
응답객체: ref, bucket, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
confirm본문string예버킷 이름. bucket과 정확히 같아야 해요.
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로 이름을 찾아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_objects
응답객체: ref, bucket, prefix, total, objects
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
prefix쿼리string아니요볼 폴더. 비우면 맨 위.
search쿼리string아니요이름에 이 말이 든 것만.
limit쿼리integer, min 1, max 1000아니요기본 100.
offset쿼리integer, min 0아니요건너뛸 개수.
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을 쓰세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구upload_object
본문 한도4096 KiB
응답객체: ref, bucket, name, size, mime, replaced
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
content본문string예파일 내용 (encoding이 base64면 base64).
name본문string예버킷 안의 경로. 예: docs/readme.txt
encoding본문string, utf-8 | base64아니요기본 utf-8.
content_type본문string아니요예: image/png. 비우면 텍스트 또는 application/octet-stream.
upsert본문boolean아니요true면 같은 이름의 파일을 바꿔요.
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로 주소를 만들어 받으세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구download_object
응답객체: ref, bucket, name, size, mime, encoding, content
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
name쿼리string아니요버킷 안의 경로.
encoding쿼리string, utf-8 | base64아니요비우면 내용에 맞게 골라요.
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

파일 삭제 버킷에서 파일 하나를 지워요. 되돌릴 수 없어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_object
응답객체: ref, bucket, name, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
name쿼리string아니요버킷 안의 경로.
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이 공개 주소예요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_upload_url
본문 한도256 KiB
응답객체: ref, bucket, name, method, url, expires_at, max_bytes, allowed_mime_types, public_url, example
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
name본문string예버킷 안의 경로. 예: videos/intro.mp4
upsert본문boolean아니요true면 같은 이름의 파일을 바꿔요. 기본은 거절해요.
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일). 주소를 가진 사람은 로그인 없이 받으니 필요한 만큼만 쓰세요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_signed_url
본문 한도256 KiB
응답객체: ref, bucket, name, url, expires_at
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
name본문string예버킷 안의 경로.
expires_in본문integer, min 1, max 604800아니요열려 있는 초. 기본 3600.
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}

버킷 설정 바꾸기 버킷의 공개 여부, 파일 하나의 최대 크기, 받을 형식을 바꿔요. 준 것만 바뀌고 나머지는 그대로예요. 공개로 바꾸면 그 안의 파일을 누구나 받을 수 있게 되니 사용자가 분명히 요청했을 때만 쓰세요. 이미 있는 파일은 그대로 둬요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구update_bucket
본문 한도256 KiB
응답객체: ref, bucket, public, file_size_limit, allowed_mime_types, files, bytes
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
public본문boolean아니요true면 공개, false면 비공개.
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에 버킷 이름을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_bucket
본문 한도256 KiB
응답객체: ref, bucket, deleted
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
bucket경로string예list_buckets의 버킷 이름.
confirm본문string예버킷 이름. bucket과 정확히 같아야 해요.
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

버킷 목록 파일 저장소의 버킷과 각각의 파일 수·용량을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_buckets
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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).

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_bucket
본문 한도256 KiB
응답객체: bucket, public, file_size_limit, allowed_mime_types
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id본문string, pattern ^[a-z0-9][a-z0-9._-]{1,62}$예The bucket name: 2 to 63 characters of lowercase letters, digits, ". _ -".
public본문boolean아니요기본값은 비공개예요.
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/projects/{ref}/deployments/sources/upload-urls배포할 압축 파일 올리기 주소 만들기
POST/projects/{ref}/deployments/sources배포할 파일 올리기
POST/projects/{ref}/deployments배포 만들기
POST/projects/{ref}/deployments/{id}/redeploy다시 배포
POST/projects/{ref}/deployments/{id}/promote프리뷰를 프로덕션으로
POST/projects/{ref}/deployments/{id}/rollback프로덕션 되돌리기
GET/projects/{ref}/deploy-hooks배포 훅 목록
POST/projects/{ref}/deploy-hooks배포 훅 만들기
DELETE/projects/{ref}/deploy-hooks/{id}배포 훅 삭제
GET/projects/{ref}/deployments/deleted최근 삭제한 배포
DELETE/projects/{ref}/deployments/{id}배포 삭제
POST/projects/{ref}/deployments/{id}/restore배포 되돌리기
GET/projects/{ref}/deployments배포 목록
GET/projects/{ref}/deployments/{id}배포 하나와 빌드 로그
GET/projects/{ref}/branch-previews브랜치 미리보기 보기
PUT/projects/{ref}/branch-previews브랜치 미리보기 바꾸기
GET/projects/{ref}/preview-protection프리뷰 보호 보기
PUT/projects/{ref}/preview-protection프리뷰 보호 바꾸기
GET/projects/{ref}/apps연결된 저장소와 빌드 설정
DELETE/projects/{ref}/apps/{name}앱 삭제
PATCH/projects/{ref}/apps/{name}빌드 설정 바꾸기
GET/projects/{ref}/env환경 변수 보기
POST/projects/{ref}/env환경 변수 저장
DELETE/projects/{ref}/env/{target}/{key}환경 변수 삭제
GET/projects/{ref}/gitGit 연결
PUT/projects/{ref}/git/tokens/{provider}저장소 토큰 저장
DELETE/projects/{ref}/git/tokens/{provider}저장소 토큰 삭제
POST/projects/{ref}/git/repos저장소 추가
DELETE/projects/{ref}/git/github-appGitHub 계정 연결 해제
DELETE/projects/{ref}/git/github-app/{installation}GitHub 계정 연결 해제
GET/projects/{ref}/git/importable가져올 저장소 찾기
POST/projects/{ref}/git/import저장소 가져오기
PUT/projects/{ref}/git/checks/{repo}/{repo}검사를 One Server에서 실행
DELETE/projects/{ref}/git/repos/{name}저장소 연결 해제
GET/projects/{ref}/volumes볼륨 목록
POST/projects/{ref}/volumes볼륨 만들기
PATCH/projects/{ref}/volumes/{id}볼륨 늘리기
DELETE/projects/{ref}/volumes/{id}볼륨 지우기
POST/projects/{ref}/volumes/{id}/backups볼륨 백업
POST/projects/{ref}/volumes/{id}/restore볼륨 복원
GET/projects/{ref}/server-memory서버 메모리
PUT/projects/{ref}/server-memory서버 메모리 바꾸기
GET/projects/{ref}/gpuGPU 작업과 서버
POST/projects/{ref}/gpu/jobsGPU 작업 만들기
GET/projects/{ref}/gpu/jobs/{id}GPU 작업 보기
POST/projects/{ref}/gpu/jobs/{id}/cancelGPU 작업 멈추기
POST/projects/{ref}/gpu/serversGPU 서버 만들기
POST/projects/{ref}/gpu/servers/{name}/stopGPU 서버 멈추기
DELETE/projects/{ref}/gpu/servers/{name}GPU 서버 지우기
POST/projects/{ref}/gpu/volumesGPU 저장소 만들기
DELETE/projects/{ref}/gpu/volumes/{name}GPU 저장소 지우기
GET/projects/{ref}/concurrent-builds동시 빌드
PUT/projects/{ref}/concurrent-builds동시 빌드 바꾸기

POST /api/v1/projects/{ref}/deployments/sources/upload-urls

배포할 압축 파일 올리기 주소 만들기 3MB 넘는 사이트를 저장소 없이 배포할 때, 압축 파일(.zip, .tar, .tar.gz) 하나를 올릴 주소를 만들어요. url에 그대로 PUT하면(토큰 없이, example의 curl) source가 오니 deploy_source를 부르세요. 주소는 1시간, max_bytes까지예요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_source_upload_url
응답객체: ref, method, url, expires_at, max_bytes, formats, example, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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>"}로 만들어요. 한 번 올린 것을 프리뷰와 프로덕션에 같은 바이트로 배포할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
본문 한도51200 KiB
응답객체: ref, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예
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이면 프로덕션, 아니면 프리뷰예요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구deploy_source
본문 한도4096 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
source본문string, pattern ^[0-9a-f]{64}$아니요올릴 때 받은 source (64자리 SHA-256).
files본문string아니요
files_base64본문string아니요
app본문string아니요배포할 앱 (list_apps의 name). 앱이 하나면 생략해요.
branch본문string아니요프리뷰의 이름. 프리뷰 주소가 돼요. 기본 preview.
commit본문string아니요
wait본문integer, min 0, max 120아니요빌드가 끝날(ready·error) 때까지 기다릴 초. 기본 0은 바로 답해요. 시간 안에 안 끝나면 still_running: true와 retry_after_seconds가 와요. MCP 클라이언트는 보통 60초쯤에 호출을 포기하니 45 정도가 안전해요.
block_on_advisors본문boolean아니요true면 get_advisors의 심각한 보안 문제(advisors.critical)가 하나라도 있을 때 프로덕션 배포를 하지 않고 거절해요. 기본 false: 배포하고 advisors에 개수와 상위 3개를 알려줘요. 프리뷰는 막지 않아요.
prebuilt본문boolean아니요true면 빌드하지 않고 그대로 서비스해요.
target본문string, preview | production아니요기본 preview.
message본문string아니요배포 목록에 남길 메모 (선택).
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)이 와요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구redeploy
응답객체: ref, id, status, environment, preview_protection, advisors
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예dpl-로 시작하는 배포 이름.
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}/promote

프리뷰를 프로덕션으로 빌드가 끝난 프리뷰 배포를 프로덕션으로 올려요. 같은 커밋을 프로덕션 환경 변수로 다시 빌드하고, 끝나면 프로덕션 주소가 그 결과를 가리켜요. 프리뷰용 키가 프로덕션에 들어가지 않게 프리뷰 빌드를 그대로 쓰지 않아요. 빌드가 끝난 프로덕션 배포를 주면 다시 빌드하지 않고 프로덕션 주소가 바로 그 배포를 가리키고, 되돌리기로 생긴 프로덕션 보류(production_held)가 풀려요. 지금 배포를 주면 보류만 풀려요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자, project.admin 소유자·관리자
MCP 도구promote_deployment
응답객체: ref, id, status, environment, preview_protection, advisors
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예올릴 배포의 dpl- 이름. 보통 프리뷰, 보류를 풀 때는 프로덕션 배포.
curl -X POST "https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/promote" \
  -H "Authorization: Bearer $ONEEND_TOKEN"
const response = await fetch('https://end.blackall.ai/api/v1/projects/abcdefghijklmnopqrst/deployments/ID/promote', {
  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이 와요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구rollback_deployment
응답객체: ref, id, status, production_held
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예되돌아갈 프로덕션 배포의 dpl- 이름.
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). 쓰기 권한 토큰이면 전부 보여요.

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구list_deploy_hooks
응답객체: ref, hooks
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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에서 글을 발행하거나 예약 작업이 돌 때 부르게 해요. 프로덕션 브랜치의 훅은 소유자·관리자만 만들 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_deploy_hook
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
app본문string예The name from list_apps.
branch본문string예The branch whose latest commit is built.
name본문string아니요A name to recognise the hook by.
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}

배포 훅 삭제 배포 훅을 지워요. 그 주소를 부르던 곳에서는 더 배포가 일어나지 않아요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_deploy_hook
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The id from list_deploy_hooks.
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으로 답해요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_deleted_deployments
응답객체: ref, deployments
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 되돌릴 수 있고, 그 뒤 파일과 빌드 로그를 지워요. 프로덕션은 프로젝트 관리자, 나머지는 개발자 이상이 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_deployment
응답객체: ref, id, deleted, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string, pattern ^dpl-[0-9a-f]{16}$예배포 id(dpl-…). list_deployments나 list_deleted_deployments로 확인해요.
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일 안에 삭제된 배포를 되돌려요. 주소가 다시 응답하고 롤백·승격도 할 수 있어요. 프로덕션 배포는 프로젝트 관리자, 나머지는 개발자 이상이 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구restore_deployment
응답객체: ref, id, restored, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string, pattern ^dpl-[0-9a-f]{16}$예배포 id(dpl-…). list_deployments나 list_deleted_deployments로 확인해요.
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- 주소는 보호돼요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_deployments
응답객체: ref, preview_protection, deployments
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
limit쿼리integer, min 1, max 100아니요기본 20.
before쿼리string, pattern ^dpl-[0-9a-f]{16}$아니요이 배포 다음부터(더 오래된 쪽). 앞 쪽 답의 next_before.
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(초)를 주면 빌드가 끝날 때까지 기다려요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_deployment
응답객체: preview_protection, build_log, build_log_lines
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예dpl-로 시작하는 배포 이름.
tail쿼리integer, min 1, max 5000아니요빌드 로그 마지막 몇 줄. 기본 200.
wait쿼리integer, min 0, max 120아니요빌드가 끝날(ready·error) 때까지 기다릴 초. 기본 0은 바로 답해요. 시간 안에 안 끝나면 still_running: true와 retry_after_seconds가 와요. MCP 클라이언트는 보통 60초쯤에 호출을 포기하니 45 정도가 안전해요.
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)에 들어온 것만 빌드해요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_branch_previews
응답객체: ref, organization, branch_previews
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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, 직접 올린 배포, 배포 훅은 그대로 빌드해요. 이 조직의 모든 프로젝트에 적용돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구set_branch_previews
본문 한도256 KiB
응답객체: ref, organization, branch_previews, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean예true면 브랜치 푸시마다 미리보기를 빌드해요.
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)도 함께 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_preview_protection
응답객체: ref, mode, has_password
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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(누구나). 프로덕션 주소와 연결한 도메인은 늘 공개예요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_preview_protection
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
mode본문string, off | members | password예off, members or password.
password본문string아니요mode가 password일 때. 비우면 이미 있는 비밀번호를 그대로 써요.
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 때 생겨요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_apps
응답객체: ref, apps, frameworks
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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에 앱 이름을 그대로 넣어야 해요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구delete_app
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예list_apps의 name.
confirm본문string예앱 이름. name과 정확히 같아야 해요.
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분 안에 서버를 다시 시작해 적용해요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구update_app
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예list_apps의 name.
production_branch본문string아니요The branch that deploys to production.
root_directory본문string아니요저장소 안의 상대 경로. 저장소 전체는 "."
run_as본문string, platform | image아니요서버를 누구로 실행할지. platform(기본)은 일반 사용자(10001), image는 이미지에 적힌 사용자(root 포함)로 gVisor 격리 환경에서 실행해요. WordPress 공식 이미지처럼 root로 시작해야 하는 Dockerfile 앱에만 image를 쓰세요. 빌드 없이 1분 안에 서버가 다시 시작해요.
port본문string, min 1, max 65535아니요서버가 컨테이너 안에서 듣는 포트. null이면 이미지의 EXPOSE, 없으면 3000. 바꾸면 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).

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구list_env_vars
응답객체: ref, automatic, variables, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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 값은 소유자·관리자만 바꿔요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_env_vars
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
variables본문array<object>아니요A list of { key, value }.
dotenv본문string아니요.env 파일 내용. 주석과 빈 줄은 건너뛰어요.
targets본문array<string>, production | preview | development, min items 1예preview는 프로덕션 브랜치가 아닌 모든 브랜치의 배포예요.
sensitive본문boolean아니요true면 저장한 뒤 값을 다시 읽을 수 없어요. 주지 않으면 이름에 SECRET, TOKEN, PASSWORD, PRIVATE, DSN, DATABASE_URL이 들어가거나 _KEY로 끝나거나 KEY_가 든 변수만 민감한 값으로 저장해요. false면 모두 다시 읽을 수 있어요.
app본문string아니요이 앱에만 넣을 때 앱 이름(list_apps의 name). 같은 이름의 프로젝트 변수보다 먼저예요. 비우면 프로젝트의 모든 앱.
branch본문string, max length 200아니요이 git 브랜치의 미리보기에만 넣을 때 브랜치 이름. targets는 preview 하나여야 해요. app과 함께 쓰면 그 앱의 그 브랜치에만 들어가요. 비우면 모든 미리보기.
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 중 한 곳에서 지워요. 민감한 값이었다면 되살릴 수 없어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_env_var
응답객체: key, target, app, branch, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
target경로string, production | preview | development예production or preview.
key경로string예The variable name.
app쿼리string아니요앱에만 넣은 변수를 지울 때 앱 이름. 비우면 프로젝트의 변수.
branch쿼리string, max length 200아니요한 git 브랜치의 미리보기에만 넣은 변수를 지울 때 브랜치 이름(list_env_vars의 branch).
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)를 봐요. 비공개 저장소 빌드가 받기에서 실패하면 여기부터 보세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_git_access
응답객체: ref, access, repositories
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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를 넣으세요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_repo_token
본문 한도256 KiB
응답객체: ref, provider, saved, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider경로string, github | gitlab | bitbucket예github or gitlab.
token본문string예The access token. Read access is enough.
gitlab_base본문string아니요자체 GitLab 주소. gitlab.com이면 비워요.
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 설치는 그대로 둬요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구remove_repo_token
응답객체: ref, provider, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider경로string, github | gitlab | bitbucket예github or gitlab.
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)이에요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구add_repository
본문 한도256 KiB
응답객체: ref, access, repositories
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
provider본문string, github | gitlab | bitbucket예github or gitlab.
repo본문string예owner/name for GitHub, group/name for GitLab.
branch본문string아니요프로덕션 브랜치. 비우면 main.
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 설치는 그대로예요. 다시 연결은 콘솔에서만 돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구unlink_github_app
응답객체: ref, unlinked
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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 설치는 그대로예요. 다시 연결은 콘솔에서만 돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구unlink_github_app
응답객체: ref, unlinked
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
installation경로integer예list_git_access의 github_accounts[].installation_id. 비우면 모두.
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으로 골라요. 소유자·관리자만 돼요.

이름설명
토큰 범위read
역할project.admin 소유자·관리자
MCP 도구list_importable_repositories
응답객체: ref, github_account, installation_id, other_accounts, repositories, shown, matched, total, searched, add_repositories_url, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
query쿼리string아니요저장소 이름의 일부. 비우면 최근에 푸시한 순서.
installation쿼리integer아니요어느 GitHub 계정의 설치인지. 비우면 기본 계정.
refresh쿼리boolean아니요GitHub에 다시 묻기(1분 캐시를 건너뜀).
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)를 첫 빌드 전에 함께 저장해요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구import_repository
본문 한도256 KiB
응답객체: ref, app, repo, branch, github_account, deployment, status, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
repo본문string아니요owner/name. list_importable_repositories의 repo.
branch본문string아니요프로덕션 브랜치. 비우면 저장소의 기본 브랜치.
root_directory본문string아니요모노레포의 앱 폴더(예: apps/web). 비우면 저장소 맨 위. 이미 연결한 저장소에서 다른 폴더를 주면 새 앱으로 추가해요.
installation본문integer아니요어느 GitHub 계정의 설치로 받을지. 비우면 저장소 주인의 계정.
dotenv본문string아니요.env 파일 내용. 프로덕션과 프리뷰 모두에 저장해요.
sensitive본문boolean아니요dotenv의 값을 저장한 뒤 다시 보여주지 않아요.
app본문string아니요앱 이름(콘솔의 "앱 이름"). 비우면 폴더 이름, 없으면 저장소 이름. 같은 이름의 앱이 있으면 그 앱의 설정을 바꿔요.
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의 새 권한을 승인하면 저절로 켜져요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_checks_on_server
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
repo경로string예list_git_access의 repositories[].repo (owner/name).
repo경로string예list_git_access의 repositories[].repo (owner/name).
enabled본문boolean예true면 켜고 false면 꺼요.
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로 다시 연결돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구disconnect_repository
응답객체: ref, name, repo, connected, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예list_git_access의 repositories[].name.
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)를 돌려줘요. 볼륨은 프로덕션 서버에만 붙어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_volumes
응답객체: ref, max_gb, used_gb, volumes
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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분 안에 서버가 다시 시작해요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_volume
본문 한도256 KiB
응답객체: ref, volume, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
app본문string예list_apps의 name.
mount_path본문string예컨테이너 안의 절대 경로. 예: /var/www/html
size_gb본문integer, min 1, max 500아니요크기(GB). 1부터 500까지, 기본 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}

볼륨 늘리기 볼륨을 더 크게 해요. 서버를 멈추지 않고 늘리고, 줄일 수는 없어요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구resize_volume
본문 한도256 KiB
응답객체: ref, volume, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_volumes의 볼륨 id.
size_gb본문integer, min 1, max 500예크기(GB). 1부터 500까지.
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를 넣으세요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구delete_volume
본문 한도256 KiB
응답객체: ref, volume, deleted, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_volumes의 볼륨 id.
confirm본문string예볼륨 경로. list_volumes의 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에 나타나요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_volume_backup
응답객체: ref, volume_id, backup, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_volumes의 볼륨 id.
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일 동안 백업해 두니 그 백업으로 되돌릴 수 있어요. 사용자가 요청했을 때만 쓰고, 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구restore_volume_backup
본문 한도256 KiB
응답객체: ref, volume, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_volumes의 볼륨 id.
backup_id본문string예list_volumes의 backups[].id. status가 ready인 것.
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대) 그 금액이 서버 하나의 한 달 요금이에요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_server_memory
응답객체: ref, server_memory_mb, cpus, max_server_memory_mb, sizes
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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분 안에 새 크기로 다시 시작해요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_server_memory
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
memory_mb본문integer, 512 | 1024 | 2048 | 4096예Memory in MB: 512, 1024, 2048 or 4096.
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를 못 써요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_gpu
응답객체: ref, prices, max_gpus, in_use, jobs, servers, volumes, volume_price, max_volume_gb, volume_gb, regions, datacenters
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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 중 하나가 필요해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_gpu_job
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
gpu본문string, rtx4090 | l40s | a100 | h100예rtx4090, l40s, a100 or h100
image본문string예공개 이미지, 예: pytorch/pytorch:2.4.0-cuda12.1-cudnn9-runtime
command본문string예sh로 실행할 명령
name본문string아니요A name
env본문object아니요환경 변수. 암호화해 저장해요.
max_minutes본문integer, min 1, max 10080아니요기본 60분
region본문string, auto | asia | us | eu아니요빌릴 지역. 기본 auto(빈 장비가 있는 곳 어디든). asia는 일본·인도예요. 저장소를 고르면 그 저장소의 데이터센터에서 빌려요.
volume본문string아니요/workspace에 붙일 GPU 저장소 이름(create_gpu_volume으로 만든 것)
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)을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_gpu_job
응답객체: id, name, gpu, image, command, max_minutes, status, created_at, started_at, ended_at, seconds, cost_minor, exit_code, error, region, volume
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The job id
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를 돌려줘요. 돌려줄 때까지 쓴 시간은 청구돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구cancel_gpu_job
응답객체: id, name, gpu, image, command, max_minutes, status, created_at, started_at, ended_at, seconds, cost_minor, exit_code, error, region, volume
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The job id
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으로 받아요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_gpu_server
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string예영문 소문자, 숫자, 하이픈
gpu본문string, rtx4090 | l40s | a100 | h100예rtx4090, l40s, a100 or h100
image본문string예공개 이미지, 예: vllm/vllm-openai:latest
command본문string아니요비우면 이미지의 기본 명령
env본문object아니요Environment variables, kept sealed
port본문integer, min 1, max 65535아니요기본 8000
idle_minutes본문integer, min 0, max 1440아니요기본 15분, 0은 계속 켜 둠
region본문string, auto | asia | us | eu아니요빌릴 지역. 기본 auto(빈 장비가 있는 곳 어디든). asia는 일본·인도예요. 저장소를 고르면 그 저장소의 데이터센터에서 빌려요.
volume본문string아니요/workspace에 붙일 GPU 저장소 이름(create_gpu_volume으로 만든 것)
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 서버를 지금 멈춰요. 꺼질 때까지 쓴 시간은 청구돼요. 다음 요청 때 다시 켜져요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구stop_gpu_server
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The server name
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 서버 이름을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_gpu_server
본문 한도256 KiB
응답객체: ref, name, deleted
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The server name
confirm본문string예GPU 서버 이름. name과 정확히 같아야 해요.
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를 빌려요. 유료 요금제만 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_gpu_volume
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string예영문 소문자, 숫자, 하이픈
size_gb본문integer, min 10, max 4000아니요기본 50GB
datacenter본문string예데이터센터, 예: AP-JP-1(일본). 고를 수 있는 목록은 list_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 저장소와 그 안의 파일을 모두 지워요. 쓰는 작업이나 서버가 있으면 지우지 않아요. 되돌릴 수 없어요. 지울 때까지의 저장 요금은 청구돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_gpu_volume
응답객체: ref, name, deleted, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The storage name
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이면 빌더가 허락하는 만큼 돌아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_concurrent_builds
응답객체: ref, concurrent_builds, max
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 한도를 없애요. 넘는 빌드는 대기열에서 기다리고, 기다리는 동안은 청구되지 않아요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_concurrent_builds
본문 한도256 KiB
응답객체: ref, concurrent_builds, max, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
concurrent_builds본문string, min 1, max 20예A whole number from 1 to 20, or null for no limit.
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/projects/{ref}/functions함수 목록
GET/projects/{ref}/functions/{name}함수 코드 보기
PUT/projects/{ref}/functions/{name}함수 배포
PATCH/projects/{ref}/functions/{name}함수 시간 한도
DELETE/projects/{ref}/functions/{name}함수 삭제
PUT/projects/{ref}/function-egress함수의 외부 요청
GET/projects/{ref}/function-secrets함수 시크릿 목록
POST/projects/{ref}/function-secrets함수 시크릿 저장
POST/projects/{ref}/function-secrets/copy함수 시크릿 복사
DELETE/projects/{ref}/function-secrets/{name}함수 시크릿 삭제

GET /api/v1/projects/{ref}/functions

함수 목록 배포한 함수와 각 호출 주소, 공개 여부를 봐요. egress는 외부 요청이 켜졌는지, outbound_requests_per_minute은 함수·pg_net·HTTP 작업이 함께 쓰는 분당 외부 요청 한도예요(자기 API 호출은 세지 않아요).

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_functions
응답객체: ref, functions
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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를 확인해요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_function
응답객체: ref, name, status, public, version, url, updated_at, bundled, bytes
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The function name.
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 <공개 키, 사용자 토큰 또는 비밀 키>.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구deploy_function
본문 한도4096 KiB
응답객체: ref, name, status, version, public, url, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413 · 429
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예영문 소문자로 시작, 소문자·숫자·하이픈. 호출 주소의 끝이 돼요.
source본문string아니요함수 코드 전체 (8MB까지). files가 있으면 entry 파일로 저장돼요. files에 entry가 있으면 생략해요.
public본문boolean아니요생략하면 기존 값을 유지하고, 새 함수는 비공개예요.
package_json본문string아니요package.json 전체 (선택). 있으면 설치 후 하나의 파일로 번들해요.
package_lock본문string아니요package-lock.json (선택). 있으면 npm ci로 정확히 그 버전을 설치해요.
dependencies본문object아니요쓸 npm 패키지와 버전. 예: {"zod": "^3.23.8"}. package_json의 dependencies에 합쳐져요.
files본문object아니요source 옆에 둘 다른 파일들, 상대 경로 → 내용 (최대 200개, 합쳐 8MB). 함수 폴더 옆 폴더는 "../_shared/cors.ts"처럼 써요.
entry본문string아니요source를 저장할 파일 이름. 기본 index.ts.
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로 끊겨요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_function_limits
본문 한도256 KiB
응답객체: ref, name
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413 · 429
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The function name.
public본문boolean아니요
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에 함수 이름을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_function
본문 한도256 KiB
응답객체: ref, name, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413 · 429
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예The function name.
confirm본문string예함수 이름. name과 정확히 같아야 해요.
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초 안에 적용돼요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_function_egress
본문 한도256 KiB
응답객체: ref, egress, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean예true to allow outbound requests, false to block them.
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면 값이 열리지 않아 함수에 들어가지 않으니 다시 저장하세요. 소유자·관리자만 볼 수 있어요.

이름설명
토큰 범위read
역할project.admin 소유자·관리자
MCP 도구list_function_secrets
응답객체: ref, secrets
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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까지예요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_function_secrets
본문 한도256 KiB
응답객체: ref, saved, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
secrets본문object아니요이름과 값. 예: {"STRIPE_WEBHOOK_SECRET": "whsec_…"}. 값은 다시 보여 주지 않아요.
dotenv본문string아니요.env 파일 내용을 통째로. 주석과 빈 줄은 건너뛰어요.
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개까지예요. 두 프로젝트 모두에서 소유자·관리자여야 해요(조직이 달라도 돼요).

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구copy_function_secrets
본문 한도256 KiB
응답객체: ref, from, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
from본문string예복사해 올 프로젝트의 ref. list_projects로 확인해요.
names본문array<string>, min items 1, max items 50예복사할 시크릿 이름. from 프로젝트의 list_function_secrets에 있는 name. 예: ["ANTHROPIC_API_KEY"]
overwrite본문boolean아니요이 프로젝트에 같은 이름이 있으면 바꿀지. 기본은 false(건너뜀).
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}

함수 시크릿 삭제 함수 시크릿 하나를 지워요. 값은 되살릴 수 없고, 함수는 다음 호출부터 이 값 없이 실행돼요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구delete_function_secret
응답객체: ref, name, deleted
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예list_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/projects/{ref}/domains도메인 보기
POST/projects/{ref}/domains도메인 연결
DELETE/projects/{ref}/domains/{hostname}도메인 연결 해제
PUT/projects/{ref}/domains/{hostname}/redirect도메인 리디렉트
GET/projects/{ref}/edge방화벽·캐시 보기
PUT/projects/{ref}/edge방화벽 바꾸기
POST/projects/{ref}/edge/purge캐시 비우기
PUT/projects/{ref}/domains/{hostname}/certificate인증서 올리기
DELETE/projects/{ref}/domains/{hostname}/certificate올린 인증서 삭제

GET /api/v1/projects/{ref}/domains

도메인 보기 이 프로젝트에 연결한 도메인과 각각의 용도(site/api), 따르는 브랜치, 리디렉트 대상, 확인 상태(아직이면 넣어야 할 TXT 레코드), 인증서 상태를 봐요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_domains
응답객체: ref, domains
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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도 연결해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구add_domain
본문 한도256 KiB
응답객체: ref, domains
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
hostname본문string예예: example.com, api.example.com, *.example.com
target본문string, site | api아니요site for the deployed site, api for the project API.
branch본문string아니요사이트만. 비우면 프로덕션.
pair_www본문boolean아니요Also connect the www address and redirect one to the other.
app본문string아니요앱 이름(list_apps의 name). 비우면 프로젝트의 사이트(project_site가 true인 앱).
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에 도메인을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_domain
본문 한도256 KiB
응답객체: ref, domains
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
hostname경로string예The connected domain.
confirm본문string예도메인. hostname과 같아야 해요(대소문자는 상관없어요).
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의 도메인은 이 프로젝트에 연결한, 리디렉트가 아닌 도메인이어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_domain_redirect
본문 한도256 KiB
응답객체: ref, domains
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
hostname경로string예넘길 도메인.
to본문string아니요도메인 또는 도메인/경로(예: example.com/vision). 비우면 리디렉트를 꺼요.
status본문integer, 308 | 307 | 301 | 302아니요응답 코드. 기본 308(영구, 메서드 유지). 빼면 지금 값을 그대로 둬요.
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 차단·허용 목록, 주소 하나당 분당 요청 한도, 적용 범위, 마지막 캐시 비우기 시각을 봐요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_edge
응답객체: ref, deny, allow, rate_per_minute, scope, cache_purged_at
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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)를 바꿔요. 준 항목만 바뀌어요. 소유자·관리자만.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_edge
본문 한도256 KiB
응답객체: ref, deny, allow, rate_per_minute, scope, cache_purged_at
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
deny본문array<string>아니요IP 또는 CIDR
allow본문array<string>아니요IP addresses or CIDR ranges to allow. Empty allows everyone.
rate_per_minute본문number아니요Requests per minute from one address, 10 to 100000. null for the platform default.
scope본문string, all | site | api아니요What the rules apply to: all, site or 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로 공유를 허락해 엣지에 저장된 응답을 모두 버려요. 다음 요청부터 배포가 다시 답해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구purge_edge_cache
응답객체: ref, deny, allow, rate_per_minute, scope, cache_purged_at
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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분 안에 적용돼요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구upload_certificate
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
hostname경로string예The connected domain.
certificate본문string예The PEM certificate chain, the server certificate first.
key본문string예The PEM private key.
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

올린 인증서 삭제 올린 인증서를 지우고 자동 발급 인증서로 돌아가요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구remove_certificate
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
hostname경로string예The connected domain.
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/projects/{ref}/network네트워크 주소
GET/projects/{ref}/network/ips네트워크 주소
POST/projects/{ref}/network/static-outbound-ip고정 아웃바운드 IP
DELETE/projects/{ref}/network/static-outbound-ip고정 아웃바운드 IP

GET /api/v1/projects/{ref}/network

네트워크 주소 요청을 받는 주소(inbound, 커스텀 도메인 A 레코드)와, 고정 아웃바운드 IP를 켰다면 나가는 고정 주소(outbound.addresses)예요. 켜지 않았으면 나가는 주소는 공유라 돌려주지 않으니 허용 목록에 넣지 마세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_network
응답객체: ref, region, inbound, outbound, static_outbound_ip, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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)예요. 켜지 않았으면 나가는 주소는 공유라 돌려주지 않으니 허용 목록에 넣지 마세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_network
응답객체: ref, region, inbound, outbound, static_outbound_ip, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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시간 안) 그 전엔 요금이 없어요.

이름설명
토큰 범위write
역할billing.manage 소유자·관리자·결제 담당
MCP 도구set_static_outbound_ip
응답객체: ref, active, status, outcome, addresses, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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시간 안) 그 전엔 요금이 없어요.

이름설명
토큰 범위write
역할billing.manage 소유자·관리자·결제 담당
MCP 도구set_static_outbound_ip
응답객체: ref, active, status, outcome, addresses, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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/projects/{ref}/jobs예약 작업 목록
PUT/projects/{ref}/jobs/{job}예약 작업 만들기·바꾸기
PATCH/projects/{ref}/jobs/{job}예약 작업 켜기·끄기
POST/projects/{ref}/jobs/{job}/run예약 작업 지금 실행
GET/projects/{ref}/jobs/{job}/runs예약 작업 실행 기록
DELETE/projects/{ref}/jobs/{job}예약 작업 삭제

GET /api/v1/projects/{ref}/jobs

예약 작업 목록 예약 작업(cron)과 일정, 다음 실행 시각, 마지막 결과를 봐요. SQL의 cron.schedule로 만든 작업은 source가 sql이에요. limit은 요금제의 작업 수 한도예요. 시각은 모두 UTC예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_jobs
응답객체: ref, timezone, limit, used, jobs
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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이에요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구save_job
본문 한도256 KiB
응답객체: ref, timezone, job
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
job경로string예The job name. Saving a name that exists changes that job.
schedule본문string예예: "*/5 * * * *" (5분마다), "0 15 * * *" (한국 자정).
kind본문string, function | sql예function to call a deployed function, sql to run SQL.
target본문string예The function name, or the SQL to run.
enabled본문boolean아니요Whether the job runs. On by default.
timeout_seconds본문number아니요SQL 작업이 실행될 수 있는 최대 시간(초). 기본 120, 최대는 요금제마다(Free 300, Pro·Enterprise 3600).
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나 이름이에요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_job_enabled
본문 한도256 KiB
응답객체: ref, id, enabled
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
job경로string예The job id or name.
enabled본문boolean예true to turn it on, false to turn it off.
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로 봐요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구run_job
응답객체: ref, id, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
job경로string예The job id or name.
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

예약 작업 실행 기록 예약 작업의 최근 실행과 결과, 실패했다면 그 오류를 최신순으로 봐요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_job_runs
응답객체: ref, id, runs
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
job경로string예The job id or name.
limit쿼리number아니요How many runs to show.
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}

예약 작업 삭제 예약 작업 하나와 그 실행 기록을 지워요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_job
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
job경로string예The job id or name.
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/projects/{ref}/webhooks데이터베이스 웹훅 목록
POST/projects/{ref}/webhooks데이터베이스 웹훅 만들기
PATCH/projects/{ref}/webhooks/{webhook}데이터베이스 웹훅 켜기·끄기
DELETE/projects/{ref}/webhooks/{webhook}데이터베이스 웹훅 삭제
GET/projects/{ref}/webhooks/{webhook}/deliveries데이터베이스 웹훅 전달 기록

GET /api/v1/projects/{ref}/webhooks

데이터베이스 웹훅 목록 표의 변경을 알리는 웹훅과 최근 전달 결과를 봐요. attached가 false면 표가 지워져 멈춘 것이에요. 서명 키(signing_secret)는 만들 때(create_db_webhook) 한 번만 보여주고, 목록에는 signing_secret_set과 끝 네 글자(signing_secret_last4)만 실어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_db_webhooks
응답객체: ref, webhooks
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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분 뒤 다시 보내고 다섯 번째에 버려요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_db_webhook
본문 한도256 KiB
응답객체: ref, webhook, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413 · 500
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string예A name to recognise the webhook by.
table본문string예list_tables의 표 이름.
events본문array<string>, insert | update | delete예Which changes to send: insert, update, delete.
kind본문string, url | function예url to POST to an address, function to call a function in this project.
target본문string예The https address, or the function name.
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나 이름이에요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_db_webhook_enabled
본문 한도256 KiB
응답객체: ref, id, enabled
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
webhook경로string예The webhook id or name.
enabled본문boolean예true to turn it on, false to turn it off.
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}

데이터베이스 웹훅 삭제 웹훅과 그 전달 기록, 아직 보내지 못한 변경을 지워요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_db_webhook
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
webhook경로string예The webhook id or name.
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일간 보관해요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_db_webhook_deliveries
응답객체: ref, id, deliveries
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
webhook경로string예The webhook id or name.
limit쿼리number아니요How many deliveries to show.
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/projects/{ref}/backups백업 목록
POST/projects/{ref}/backups지금 백업
POST/projects/{ref}/backups/{backup_id}/restore백업으로 복원
POST/projects/{ref}/backups/restore-to-time백업으로 복원

GET /api/v1/projects/{ref}/backups

백업 목록 프로젝트 백업(매일 밤 프로젝트 리전 시각 03:00~05:00에 자동, 직접 만든 것, 복원 직전 것)과 복원 기록을 봐요. 보관 기간은 retention_days예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_backups
응답객체: ref, retention_days, point_in_time, backups, restores
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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일 보관돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_backup
응답객체: ref, id, status, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 되돌릴 수 있어요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구restore_backup
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
backup_id경로string예The id from list_backups.
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로 되돌릴 수 있어요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구restore_backup
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
at본문string아니요예: 2026-10-01T14:59:00+09:00
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/projects/{ref}/logs로그 보기
GET/projects/{ref}/log-drains로그 내보내기 목록
POST/projects/{ref}/log-drains로그 내보내기 추가
PATCH/projects/{ref}/log-drains/{id}로그 내보내기 끄기·켜기
DELETE/projects/{ref}/log-drains/{id}로그 내보내기 삭제
GET/projects/{ref}/metrics지표
GET/projects/{ref}/audit감사 기록

GET /api/v1/projects/{ref}/logs

로그 보기 로그를 최신순으로 봐요: 사이트·API·인증·함수 요청(메서드, 경로, 상태, 시간)과 서버·함수 출력. 500이 나면 level: error로 먼저 보세요. 다음 쪽은 next_before를 before로 넘겨요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_logs
응답객체: ref, lines, next_before, retention_days
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
source쿼리string, site | server | api | auth | functions | build아니요Where the lines come from: site, server, api, auth, functions, build.
level쿼리string, warn | error아니요warn은 경고와 오류, error는 오류만이에요.
q쿼리string아니요
before쿼리string아니요이 시각보다 오래된 줄만. 이전 응답의 next_before.
deployment쿼리string아니요
limit쿼리integer, min 1, max 500아니요기본 100.
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)만 실어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_log_drains
응답객체: ref, sources, drains
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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개까지. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_log_drain
본문 한도256 KiB
응답객체: id, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string예A name to recognise the drain by.
kind본문string, https | datadog예https or datadog.
url본문string예공개된 https 주소.
secret본문string아니요Datadog API 키, 또는 https로 보낼 때 Authorization 헤더에 넣을 값.
sources본문array<string>, site | server | api | auth | functions | build아니요비우면 전부.
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}

로그 내보내기 끄기·켜기 설정은 두고 보내기만 멈추거나 다시 시작해요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_log_drain_enabled
본문 한도256 KiB
응답객체: ref, id, enabled
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The id from list_log_drains.
enabled본문boolean예true to send, false to stop.
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}

로그 내보내기 삭제 로그 내보내기를 지워요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구remove_log_drain
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The id from list_log_drains.
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)을 표면별·시간대별로, 그리고 데이터베이스 크기·연결·캐시 적중률을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_metrics
응답객체: ref, range, requests, failures, latency_ms, by_surface, points, database
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
range쿼리string, 1h | 24h | 7d아니요비우면 24h.
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(한국 날짜). 소유자·관리자만 돼요.

이름설명
토큰 범위read
역할audit.read 소유자·관리자
MCP 도구get_audit_log
응답객체: ref, tab, total, has_more, records
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
tab쿼리string, activity | access아니요activity for changes, access for access to personal data.
from쿼리string아니요The first date, YYYY-MM-DD.
to쿼리string아니요The last date, YYYY-MM-DD.
actor쿼리string아니요이메일 일부.
action쿼리string아니요이 말로 시작하는 동작. 예: member.
limit쿼리integer, min 1, max 200아니요How many entries to get, up to 200.
offset쿼리integer, min 0아니요How many entries to skip.
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/projects/{ref}/team팀 구성원
POST/projects/{ref}/team/invitations구성원 초대
DELETE/projects/{ref}/team/invitations/{id}초대 취소
PATCH/projects/{ref}/team/members/{email}구성원 역할 바꾸기
DELETE/projects/{ref}/team/members/{email}구성원 내보내기
PUT/projects/{ref}/team/mfa2단계 인증 요구
GET/projects/{ref}/channels알림 채널 목록
POST/projects/{ref}/channels알림 채널 추가
POST/projects/{ref}/channels/{id}/test알림 채널 시험
PATCH/projects/{ref}/channels/{id}알림 채널 끄기·켜기
DELETE/projects/{ref}/channels/{id}알림 채널 삭제

GET /api/v1/projects/{ref}/team

팀 구성원 이 프로젝트를 가진 조직의 구성원과 역할, 2단계 인증 여부, 아직 수락하지 않은 초대.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_team
응답객체: ref, mfa_required, members, invitations
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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

구성원 초대 이메일로 초대 링크를 보내요. 받은 사람이 링크를 열어야 참여해요. 이미 구성원인 주소는 역할만 바뀌어요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구invite_member
본문 한도256 KiB
응답객체: ref, id, email, role, outcome, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
email본문string예The email address to invite.
role본문string, admin | developer | billing | viewer아니요비우면 developer.
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에 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구cancel_invitation
응답객체: ref, id, cancelled
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The invitation id from list_team.
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}

구성원 역할 바꾸기 이미 구성원인 사람의 역할을 바꿔요. 소유자의 역할은 바꿀 수 없어요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구set_member_role
본문 한도256 KiB
응답객체: ref, email, role
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
email경로string예The member's email address.
role본문string, admin | developer | billing | viewer예The new role.
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}

구성원 내보내기 조직에서 내보내요. 소유자는 내보낼 수 없어요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구remove_member
응답객체: ref, email, removed
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
email경로string예The member's email address.
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에 나와요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구set_mfa_required
본문 한도256 KiB
응답객체: ref, mfa_required
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
required본문boolean예true to require it, false to stop requiring it.
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)만 실어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_channels
응답객체: ref, notices, channels
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 확인하세요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구create_channel
본문 한도256 KiB
응답객체: ref, id, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
kind본문string, slack | kakaowork | webhook | email예slack, kakaowork, webhook or email.
name본문string예A name to recognise the channel by.
url본문string아니요Slack·카카오워크·웹훅의 주소. 메일 채널에는 쓰지 않아요.
emails본문array<string>, max items 10아니요메일 채널의 받는 주소. 예: ["[email protected]"].
notices본문array<string>, deployments | domains | usage | billing아니요Which kinds to receive: deployments, domains, usage, billing. Empty means all.
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

알림 채널 시험 그 채널 하나에만 시험 메시지를 보내요. 메일 채널이면 확인된 주소에만 보내고, 확인을 기다리는 주소에는 확인 메일을 다시 보내요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구test_channel
응답객체: ref, id, sent, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The id from list_channels.
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}

알림 채널 끄기·켜기 설정은 두고 알림만 멈추거나 다시 받아요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구set_channel_enabled
본문 한도256 KiB
응답객체: ref, id, enabled
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The id from list_channels.
enabled본문boolean예true to send, false to stop.
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}

알림 채널 삭제 알림 채널을 지워요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할team.manage 소유자·관리자
MCP 도구remove_channel
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예The id from list_channels.
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/projects/{ref}/usage사용량
GET/projects/{ref}/billing/plan요금제
GET/projects/{ref}/billing/spend지출 한도
PUT/projects/{ref}/billing/spend-cap지출 상한 켜기·끄기
PUT/projects/{ref}/billing/spend-limit월 지출 한도
GET/projects/{ref}/billing청구서와 사용량

GET /api/v1/projects/{ref}/usage

사용량 표·줄·가입자·파일 수와 저장 용량, 이번 달 사용량, 그리고 분당 한도(limits.outbound_requests_per_minute: 함수·pg_net·HTTP 작업이 함께 쓰는 외부 요청 수, 자기 API 호출은 세지 않음)를 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구usage
응답객체: tables, approximate_rows, users, files, storage_bytes, database_bytes
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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 전용 기능이 있어요. 요금제 변경은 콘솔에서만 돼요. 소유자·관리자·결제 담당만 돼요.

이름설명
토큰 범위read
역할billing.manage 소유자·관리자·결제 담당
MCP 도구get_plan
응답객체: ref, currency, plan, scheduled, options, billed_by, addons, note
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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: 켜면 포함량을 넘는 사용을 막고 초과 요금을 받지 않음), 월 초과 요금 한도와 알림 웹훅, 이번 달 사용량을 봐요. 소유자·관리자·결제 담당만 볼 수 있어요.

이름설명
토큰 범위read
역할billing.manage 소유자·관리자·결제 담당
MCP 도구get_spend_controls
응답객체: ref, spend_cap, spend_cap_applies, spend_limit_minor, spend_limit_floor_minor, webhook_url, progress
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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)이 필요해요. 소유자·관리자·결제 담당만 돼요.

이름설명
토큰 범위write
역할billing.manage 소유자·관리자·결제 담당
MCP 도구set_spend_cap
본문 한도256 KiB
응답객체: ref, spend_cap
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean예true면 켜요.
confirm본문string아니요끌 때(enabled: false)만: 프로젝트 이름. 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이 더 좋아요. 소유자·관리자·결제 담당만 돼요.

이름설명
토큰 범위write
역할billing.manage 소유자·관리자·결제 담당
MCP 도구set_spend_limit
본문 한도256 KiB
응답객체: ref, spend_cap, spend_cap_applies, spend_limit_minor, spend_limit_floor_minor, webhook_url, progress
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
spend_limit_minor본문string, min 0예한도. null이면 없음.
webhook_url본문string아니요알림을 받을 https 주소. 빈 문자열이면 지워요.
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이에요. 카드·결제 내역은 콘솔에만 있어요. 소유자·관리자·결제 담당만 돼요.

이름설명
토큰 범위read
역할billing.manage 소유자·관리자·결제 담당
MCP 도구get_billing
응답객체: ref, period, plan, period_start, period_end, currency, list_total_minor, billing_exempt, lines, usage, months
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
period쿼리string아니요YYYY-MM
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/projects/{ref}/transfer옮길 수 있는 조직
POST/projects/{ref}/transfer프로젝트 옮기기
GET/projects/{ref}/server전용 서버
POST/projects/{ref}/server전용 서버 빌리기
PATCH/projects/{ref}/server서버 크기 바꾸기
DELETE/projects/{ref}/server전용 서버 반납
PUT/projects/{ref}/server/standby대기 서버
POST/projects/{ref}/server/move서버 위치 옮기기
PUT/projects/{ref}/server/restore-days되돌리기 기간
GET/projects/{ref}/s3-keysS3 접근 키 목록
POST/projects/{ref}/s3-keysS3 접근 키 만들기
DELETE/projects/{ref}/s3-keys/{id}S3 접근 키 폐기
POST/projects/{ref}/storage/policies파일 접근 규칙 만들기
POST/projects/{ref}/storage/copy-from-import파일 가져오기
GET/projects/{ref}/deployment-retention배포 보관 기간
PUT/projects/{ref}/deployment-retention배포 보관 기간 바꾸기
GET/projects/{ref}/schemas프로젝트 스키마
PUT/projects/{ref}/schemas/exposed노출 스키마 정하기
GET/projects/{ref}/data-api데이터 API 설정 보기
PATCH/projects/{ref}/data-api데이터 API 설정 바꾸기
POST/projects/{ref}/{param0}/{param1}SAML SSO 추가
PUT/projects/{ref}/{param0}/{param1}/{param2}SAML SSO 추가
GET/projects/{ref}/config/auth로그인 설정 전체 보기
PATCH/projects/{ref}/config/auth로그인 설정 바꾸기
GET/projects/{ref}/config/auth/custom-providers사용자 정의 로그인 제공자 보기
POST/projects/{ref}/config/auth/custom-providers사용자 정의 로그인 제공자 만들기
PUT/projects/{ref}/config/auth/custom-providers/{identifier}사용자 정의 로그인 제공자 수정
PATCH/projects/{ref}/config/auth/custom-providers/{identifier}사용자 정의 로그인 제공자 껐다 켜기
DELETE/projects/{ref}/config/auth/custom-providers/{identifier}사용자 정의 로그인 제공자 삭제
POST/projects/{ref}/config/auth/copy-from-import로그인 설정 가져오기
GET/projects/{ref}/config/auth/third-party-auth서드파티 인증 보기
POST/projects/{ref}/config/auth/third-party-auth서드파티 인증 추가
DELETE/projects/{ref}/config/auth/third-party-auth/{id}서드파티 인증 삭제
GET/projects/{ref}/analytics웹 분석
GET/projects/{ref}/analytics/breakdown웹 분석 세부
PUT/projects/{ref}/analytics/previews프리뷰 방문 세기
GET/projects/{ref}/analytics/export웹 분석 내보내기
GET/projects/{ref}/analytics/reports맞춤 리포트 목록
GET/projects/{ref}/analytics/reports/{id}맞춤 리포트 보기
POST/projects/{ref}/analytics/reports맞춤 리포트 저장
PATCH/projects/{ref}/analytics/reports맞춤 리포트 저장
DELETE/projects/{ref}/analytics/reports/{id}맞춤 리포트 삭제
GET/projects/{ref}/speed-insights속도 인사이트
PUT/projects/{ref}/insights분석 켜기·끄기
GET/projects/{ref}/remote-cache원격 캐시
DELETE/projects/{ref}/remote-cache/artifacts원격 캐시 비우기
GET/projects/{ref}/flags기능 플래그 목록
GET/projects/{ref}/flags/evaluate기능 플래그 값 보기
PUT/projects/{ref}/flags/{key}/environments/{environment}기능 플래그 켜기·끄기
GET/projects/{ref}/edge-config엣지 설정 읽기
GET/projects/{ref}/edge-config/tokens엣지 설정 읽기 토큰
POST/projects/{ref}/edge-config/tokens엣지 설정 읽기 토큰 만들기
DELETE/projects/{ref}/edge-config/tokens/{id}읽기 토큰 폐기
PUT/projects/{ref}/edge-config/tokens/{id}/connections/{ref}읽기 토큰을 프로젝트에 연결
DELETE/projects/{ref}/edge-config/tokens/{id}/connections/{ref}읽기 토큰 연결 끊기
GET/projects/{ref}/edge-config/history엣지 설정 변경 기록
PATCH/projects/{ref}/edge-config엣지 설정 바꾸기
GET/projects/{ref}/rolling-releases점진적 배포 상태
PUT/projects/{ref}/rolling-releases점진적 배포 설정
POST/projects/{ref}/rolling-releases/{action}점진적 배포 다음 단계로
GET/projects/{ref}/kvKV 키 목록
GET/projects/{ref}/kv/{id}KV 값 읽기
PUT/projects/{ref}/kv/{id}KV 값 저장
DELETE/projects/{ref}/kv/{id}KV 키 삭제
GET/projects/{ref}/ai-gatewayAI 게이트웨이
PUT/projects/{ref}/ai-gatewayAI 게이트웨이 설정
GET/projects/{ref}/ai-gateway/logsAI 게이트웨이 호출 기록
POST/projects/{ref}/ai-gateway/providersAI 공급자 추가
PATCH/projects/{ref}/ai-gateway/providers/{id}AI 공급자 끄기·켜기
DELETE/projects/{ref}/ai-gateway/providers/{id}AI 공급자 삭제
PUT/projects/{ref}/ai-gateway/budgetsAI 게이트웨이 예산
GET/projects/{ref}/ai-gateway/keysAI 게이트웨이 키 목록
POST/projects/{ref}/ai-gateway/keysAI 게이트웨이 키 만들기
PUT/projects/{ref}/ai-gateway/keys/{id}/limitsAI 게이트웨이 키 한도
PUT/projects/{ref}/ai-gateway/aliasesAI 모델 별칭
PUT/projects/{ref}/ai-gateway/hooksAI 게이트웨이 훅
PATCH/projects/{ref}/ai-gateway/keys/{id}AI 게이트웨이 키 예산
DELETE/projects/{ref}/ai-gateway/keys/{id}AI 게이트웨이 키 폐기
GET/projects/{ref}/ai-gateway/spendAI 게이트웨이 지출
GET/projects/{ref}/middleware미들웨어 설정
PUT/projects/{ref}/middleware미들웨어 설정 바꾸기
GET/projects/{ref}/branchesDB 브랜치 목록
POST/projects/{ref}/branchesDB 브랜치 만들기
PUT/projects/{ref}/branching자동 DB 브랜치 설정
POST/projects/{ref}/branches/{name}/mergeDB 브랜치 병합
POST/projects/{ref}/branches/{name}/resetDB 브랜치 초기화
DELETE/projects/{ref}/branches/{name}DB 브랜치 삭제
GET/projects/{ref}/queues대기열 목록
GET/projects/{ref}/queues/metrics큐 지표
POST/projects/{ref}/queues대기열 만들기
PUT/projects/{ref}/queues/api대기열을 데이터 API로 열기
DELETE/projects/{ref}/queues/{name}대기열 삭제
POST/projects/{ref}/queues/{name}/purge대기열 비우기
POST/projects/{ref}/queues/{name}/messages대기열에 메시지 넣기
GET/projects/{ref}/queues/{name}/messages대기열 메시지 보기
GET/projects/{ref}/vaultVault 비밀 목록
POST/projects/{ref}/vaultVault 비밀 저장
PATCH/projects/{ref}/vault/{name}Vault 비밀 바꾸기
DELETE/projects/{ref}/vault/{name}Vault 비밀 삭제
GET/projects/{ref}/network-restrictionsDB 접속 제한 보기
PUT/projects/{ref}/network-restrictionsDB 접속 제한 바꾸기

GET /api/v1/projects/{ref}/transfer

옮길 수 있는 조직 이 프로젝트를 옮길 수 있는 다른 조직(내가 소유자나 관리자인 조직)의 id·이름·요금제예요. can_transfer는 내가 지금 조직의 소유자라서 옮길 수 있는지예요. transfer_project의 organisation에 id를 넣어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_transfer_targets
응답객체: ref, name, organisation, organisation_id, targets
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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에 프로젝트 이름을 그대로 넣으세요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구transfer_project
본문 한도256 KiB
응답객체: ref, name, organisation, organisation_id, transferred, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
organisation본문string예받을 조직의 id. list_transfer_targets가 알려줘요. 이름이 하나뿐이면 이름도 돼요.
confirm본문string예프로젝트 이름. list_projects의 name과 정확히 같아야 해요.
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면 아직 열리지 않았어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_server
응답객체: ref, offered, server, standby, options, next_move_at, jobs
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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부터, 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구request_server
본문 한도256 KiB
응답객체: job, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
tier본문string, pattern ^[0-9]+gb$예서버 크기. list_server_sizes의 tier(예: 4gb).
region본문string, pattern ^[a-z]{2}-[a-z]+-[0-9]$아니요위치. 없으면 프로젝트 위치. list_server_sizes의 region.
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). 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구resize_server
본문 한도256 KiB
응답객체: job, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
tier본문string, pattern ^[0-9]+gb$예서버 크기. list_server_sizes의 tier(예: 4gb).
when본문string, now | tonight아니요now(지금, 기본) 또는 tonight(새벽 3~5시).
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를 그대로 넣으세요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구release_server
본문 한도256 KiB
응답객체: job, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
confirm본문string예프로젝트 ID(ref). 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초 응답하지 않을 때 대기 서버로 저절로 바꿔요(대기 서버가 있어야 해요). 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_standby
본문 한도256 KiB
응답객체: job, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
standby본문boolean예대기 서버를 둘지.
auto_failover본문boolean아니요자동 전환. 기본 false.
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). 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구move_server
본문 한도256 KiB
응답객체: job, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
region본문string, pattern ^[a-z]{2}-[a-z]+-[0-9]$예위치. list_server_sizes의 region(예: kr-seoul-1).
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). 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_restore_days
본문 한도256 KiB
응답객체: job, note
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
days본문integer, 7 | 28예7 또는 28.
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·마지막 사용 시각·폐기 여부예요. 비밀 접근 키는 돌려주지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_s3_keys
응답객체: keys
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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개까지예요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_s3_key
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string, min length 1, max length 60예어디에 쓰는 키인지. 예: 백업 서버
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초 안에 그 키로 서명한 요청이 거부돼요. 다른 키는 그대로예요. 되돌릴 수 없어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구revoke_s3_key
응답객체: revoked, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_s3_keys의 keys[].id
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로는 규칙을 만들 수 없어서 이 경로를 써요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예
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이면 아무것도 바꾸지 않고 수만 보여줘요. 소유자·관리자·개발자만 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구copy_storage_from_import
본문 한도256 KiB
응답객체: ref, source_project, dry_run, done, next, buckets, failures
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
buckets본문array<string>아니요복사할 Supabase 버킷 이름. 비우면 모두.
rename본문object아니요버킷 이름 바꾸기 {"Supabase 버킷": "여기 버킷"}. 없으면 소문자로, 공백은 -로 바꿔요(My Files → my-files).
dry_run본문boolean아니요true면 바꾸지 않고 만들 버킷과 옮길 파일 수만 보여줘요.
max_files본문integer, min 1, max 1000아니요이번에 옮길 파일 수의 상한(기본 200, 최대 1000).
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)도 와요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_deployment_retention
응답객체: ref, canceled, error, preview, production, always_kept, restore_days
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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로 되돌릴 수 있어요. 최근 배포와 서비스 중인 배포는 기간과 상관없이 남아요. 프로젝트 관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_deployment_retention
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
canceled_days본문string, min 1, max 3650아니요취소·건너뛴 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로.
error_days본문string, min 1, max 3650아니요실패한 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로.
preview_days본문string, min 1, max 3650아니요프리뷰 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로.
production_days본문string, min 1, max 3650아니요프로덕션 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로.
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과 클라이언트에선 만든 이름을 그대로 써요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_schemas
응답객체: ref, always_exposed, schemas, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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초 안에 적용돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_exposed_schemas
본문 한도256 KiB
응답객체: ref, exposed, schemas, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
exposed본문array<string>예노출할 스키마 이름들(list_schemas의 name). public은 늘 노출돼요.
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는 넣을 수 있는 스키마예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_data_api_settings
응답객체: ref, enabled, max_rows, exposed_schemas, search_path, search_path_choices
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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초 안에 적용돼요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_data_api_settings
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean아니요false면 /rest/v1이 모두 404로 답해요.
max_rows본문number, min 1, max 1000000아니요한 번에 돌려주는 최대 행 수. null이면 제한 없음.
search_path본문array<string>, max items 20아니요검색 경로에 넣을 스키마(get_data_api_settings의 search_path_choices의 name). 빈 목록이면 넣지 않아요.
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는 그대로 동작해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구add_sso_provider
본문 한도256 KiB
응답객체: id, entity_id, metadata_url, domains, attribute_mapping, created_at, updated_at
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
param0경로string예
param1경로string예
metadata_url본문string아니요https 주소. metadata_xml과 둘 중 하나.
metadata_xml본문string아니요The IdP's metadata XML. Give this or metadata_url.
domains본문array<string>아니요예: ["example.com"]
attribute_mapping본문object아니요GoTrue 형식: {"keys": {"email": {"name": "mail"}}}
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는 그대로 동작해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구add_sso_provider
본문 한도256 KiB
응답객체: id, entity_id, metadata_url, domains, attribute_mapping, created_at, updated_at
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
param0경로string예
param1경로string예
param2경로string예
metadata_url본문string아니요https 주소. metadata_xml과 둘 중 하나.
metadata_xml본문string아니요The IdP's metadata XML. Give this or metadata_url.
domains본문array<string>아니요예: ["example.com"]
attribute_mapping본문object아니요GoTrue 형식: {"keys": {"email": {"name": "mail"}}}
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은 제공자 콘솔에 붙여 넣을 주소예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_auth_config
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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예요. 비밀 값을 빈 문자열로 주면 지워요. 소유자·관리자·개발자만 돼요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구update_auth_config
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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>" })로 불러요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_custom_providers
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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는 기본으로 켜져요. 요금제 한도를 넘으면 거부돼요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구create_custom_provider
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
pkce본문boolean아니요On by default; turn it off only if the provider refuses PKCE.
pkce_enabled본문string아니요
identifier본문string예영문 소문자·숫자·하이픈. custom: 은 붙여도 되고 안 붙여도 돼요.
name본문string예The display name, under 100 characters.
label본문string아니요
provider_type본문string, oidc | oauth2예oidc (endpoints discovered, id_token verified) or oauth2 (endpoints given, read through claim_map).
issuer본문string아니요The provider's base URL.
discovery_url본문string아니요For oidc, when the discovery document is not at the standard path.
authorization_url본문string아니요Required for oauth2 without an issuer; for oidc, empty is discovered.
authorize_url본문string아니요
token_url본문string아니요Required for oauth2 without an issuer; for oidc, empty is discovered.
userinfo_url본문string아니요Where the user is read; for oidc, empty is discovered.
jwks_uri본문string아니요For oidc, to verify ID tokens; empty is discovered.
client_id본문string예The client ID.
client_secret본문string예The client secret.
scopes본문array<string>아니요For example ["openid", "email", "profile"].
email_optional본문boolean아니요Allow users without an email.
claim_map본문object아니요Which field of the answer is id, email, email_verified, name, avatar and phone, as dotted paths. Left out: the OpenID standard names.
claims본문string아니요
token_auth본문string, body | basic아니요Send client_secret in the body (body, the default) or as HTTP Basic (basic).
enabled본문boolean아니요On by default.
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을 빈 문자열로 두면 저장된 시크릿을 그대로 써요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구update_custom_provider
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
identifier경로string예list_custom_providers의 identifier
pkce본문boolean아니요On by default; turn it off only if the provider refuses PKCE.
pkce_enabled본문string아니요
identifier본문string예list_custom_providers의 identifier
name본문string예The display name, under 100 characters.
label본문string아니요
provider_type본문string, oidc | oauth2예oidc (endpoints discovered, id_token verified) or oauth2 (endpoints given, read through claim_map).
issuer본문string아니요The provider's base URL.
discovery_url본문string아니요For oidc, when the discovery document is not at the standard path.
authorization_url본문string아니요Required for oauth2 without an issuer; for oidc, empty is discovered.
authorize_url본문string아니요
token_url본문string아니요Required for oauth2 without an issuer; for oidc, empty is discovered.
userinfo_url본문string아니요Where the user is read; for oidc, empty is discovered.
jwks_uri본문string아니요For oidc, to verify ID tokens; empty is discovered.
client_id본문string예The client ID.
client_secret본문string아니요Empty keeps the stored secret.
scopes본문array<string>아니요For example ["openid", "email", "profile"].
email_optional본문boolean아니요Allow users without an email.
claim_map본문object아니요Which field of the answer is id, email, email_verified, name, avatar and phone, as dotted paths. Left out: the OpenID standard names.
claims본문string아니요
token_auth본문string, body | basic아니요Send client_secret in the body (body, the default) or as HTTP Basic (basic).
enabled본문boolean아니요Turn it on or off as it is saved.
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}

사용자 정의 로그인 제공자 껐다 켜기 사용자 정의 제공자 하나를 끄거나 켜요. 끄면 지금 세션은 그대로지만 새 로그인은 다시 켤 때까지 실패해요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구set_custom_provider_enabled
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
identifier경로string예The identifier from list_custom_providers.
enabled본문boolean예true to turn it on, false to turn it off.
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}

사용자 정의 로그인 제공자 삭제 사용자 정의 제공자 하나를 지워요. 되돌릴 수 없고, 이 제공자로 로그인하던 사용자는 들어올 수 없어요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구remove_custom_provider
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
identifier경로string예The identifier from list_custom_providers.
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이면 아무것도 바꾸지 않고 보여만 줘요. 소유자·관리자·개발자만 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구copy_auth_from_import
본문 한도256 KiB
응답객체: ref, source_project, dry_run, callback_url, providers, site_url, redirect_urls, console_url
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
providers본문array<string>아니요복사할 제공자(google, kakao, apple, x…). 비우면 Supabase에서 켜 둔 것 모두.
dry_run본문boolean아니요true면 바꾸지 않고 무엇을 복사할지만 보여줘요.
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)의 토큰 목록이에요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_third_party_auth
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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도 넣으세요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구add_third_party_auth
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
type본문string, firebase | clerk | workos | auth0 | cognito | oidc예firebase, clerk, workos, auth0, cognito or oidc.
value본문string예What the type takes, as above.
region본문string아니요cognito의 AWS 리전. 예: ap-northeast-2
audiences본문array<string>아니요Values a token’s aud must contain.
jwks_url본문string아니요oidc에서 디스커버리 대신 쓸 JWKS 주소
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로 거부돼요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구remove_third_party_auth
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_third_party_auth의 id
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

웹 분석 페이지뷰와 방문자를 날짜별로, 많이 본 페이지·유입 경로·국가·기기·브라우저·운영체제와 함께 돌려줘요. 개인을 알아볼 수 있는 값은 저장하지 않아서 합계만 있어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_analytics
응답객체: ref, settings
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
days쿼리integer, 1 | 7 | 30 | 90아니요기간. 기본 7.
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를 주면 그 이벤트의 속성별 값을 함께 돌려줘요. 합계만 있어요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_analytics_breakdown
응답객체: ref, days, utm_source, utm_medium, utm_campaign, routes, events, bots_filtered, crawlers
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
days쿼리integer, 1 | 7 | 30 | 90아니요기간. 기본 7.
event쿼리string, max length 100아니요속성을 볼 이벤트 이름.
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- 주소의 방문을 웹 분석에 셀지 정해요. 끄면(기본) 프리뷰에는 스크립트를 넣지 않고 보내온 것도 버려요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_analytics_previews
본문 한도256 KiB
응답객체: ref, include_previews, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
include_previews본문boolean예프리뷰도 세기.
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 문자열로 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구export_analytics
응답객체: ref, days, format, csv
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
days쿼리integer, 1 | 7 | 30 | 90아니요기간. 기본 7.
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

맞춤 리포트 목록 저장한 웹 분석 리포트와 넣을 수 있는 차트 이름을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_analytics_reports
응답객체: ref, widgets, reports
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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}

맞춤 리포트 보기 저장한 리포트 하나를 그 기간의 합계, 세부, 속도와 함께 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_analytics_report
응답객체: ref, report, totals, breakdown, speed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_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를 주면 그 리포트를 바꿔요. 개발자 이상만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구save_analytics_report
본문 한도256 KiB
응답객체: ref, report
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string, min length 1, max length 80예이름.
days본문integer, 1 | 7 | 30 | 90아니요기간. 기본 7.
widgets본문array<string>, views | visitors | path | referrer | country | device | browser | os | utm_source | utm_medium | utm_campaign | route | event | bot | vitals, min items 1, max items 16예넣을 차트와 표.
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를 주면 그 리포트를 바꿔요. 개발자 이상만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구save_analytics_report
본문 한도256 KiB
응답객체: ref, report
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string, min length 1, max length 80예이름.
days본문integer, 1 | 7 | 30 | 90아니요기간. 기본 7.
widgets본문array<string>, views | visitors | path | referrer | country | device | browser | os | utm_source | utm_medium | utm_campaign | route | event | bot | vitals, min items 1, max items 16예넣을 차트와 표.
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}

맞춤 리포트 삭제 리포트만 지워요. 분석 기록은 그대로예요. 개발자 이상만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구remove_analytics_report
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_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번째 백분위와 평가, 느린 페이지를 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_speed_insights
응답객체: ref, settings
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
days쿼리integer, 1 | 7 | 30 | 90아니요기간. 기본 7.
device쿼리string, all | desktop | mobile아니요기기. 기본 all.
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는 저장하지 않아요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_insights
본문 한도256 KiB
응답객체: ref, settings, script, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
analytics본문boolean아니요웹 분석.
speed_insights본문boolean아니요속도 인사이트.
vitals_sample_percent본문integer, min 1, max 100아니요속도를 재는 방문 비율.
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로 세요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_remote_cache
응답객체: ref, api, artifacts, bytes, last_30_days, metered
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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

원격 캐시 비우기 저장된 결과를 모두 지워요. 다음 빌드부터 다시 채워지고, 지운 만큼 저장 용량 사용량이 줄어요. 개발자 이상만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구clear_remote_cache
응답객체: ref, cleared
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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는 같은 키의 엣지 설정 값을 가리는지 알려 줘요. 키가 같으면 플래그를 따라요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_flags
응답객체: ref, flags, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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가 어느 쪽인지 알려 줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구evaluate_flag
응답객체: ref, key, environment, note
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
key쿼리string, max length 256아니요플래그 키.
environment쿼리string아니요환경. 기본 production.
context쿼리object아니요평가할 컨텍스트(JSON 객체).
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}

기능 플래그 켜기·끄기 한 환경에서 플래그를 켜거나 꺼요. 프로덕션은 소유자·관리자, 그 밖의 환경은 개발자 이상이 할 수 있어요.

이름설명
토큰 범위write
역할조직의 모든 구성원
MCP 도구set_flag_enabled
본문 한도256 KiB
응답객체: ref, key, environment, enabled, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
key경로string, max length 64예플래그 키.
environment경로string예환경.
enabled본문boolean예켜기.
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

엣지 설정 읽기 프로젝트의 엣지 설정(배포 없이 바꾸는 값과 기능 플래그) 전체와 버전, 크기, 한도를 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_edge_config
응답객체: ref, version, bytes, limits, items, read_url
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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

엣지 설정 읽기 토큰 다른 프로젝트가 이 프로젝트의 엣지 설정을 읽는 읽기 토큰과 연결된 프로젝트(변수 이름, 환경), 이 프로젝트에 연결된 다른 프로젝트의 엣지 설정을 돌려줘요. 토큰 값은 돌려주지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_edge_config_tokens
응답객체: ref, tokens, connected_here
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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=…)을 변수로 받아요. 토큰은 이때만 보여요. 프로젝트 관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_edge_config_token
본문 한도256 KiB
응답객체: ref, id, name, token, connection_string, connected, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
connect본문object아니요바로 연결할 같은 조직의 프로젝트: ref, 변수 이름 variable(기본 GLOBAL_CONFIG), 환경 targets(기본 셋 다, 프로덕션은 그 프로젝트의 소유자·관리자만).
name본문string, min length 1, max length 60예토큰 이름.
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}

읽기 토큰 폐기 읽기 토큰을 폐기해요. 바로 읽지 못하고, 연결된 프로젝트의 다음 배포부터 변수가 빠져요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구revoke_edge_config_token
응답객체: ref, id, revoked
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예읽기 토큰 id. list_edge_config_tokens로 확인해요.
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}

읽기 토큰을 프로젝트에 연결 읽기 토큰을 같은 조직의 다른 프로젝트 배포에 변수로 연결해요. 이미 연결돼 있으면 변수 이름과 환경을 바꿔요. 그 프로젝트의 개발자 이상(프로덕션은 소유자·관리자)이어야 해요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구connect_edge_config_token
본문 한도256 KiB
응답객체: ref, id, connected
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예읽기 토큰 id. list_edge_config_tokens로 확인해요.
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
variable본문string, pattern ^[A-Za-z_][A-Za-z0-9_]{0,63}$아니요배포에서 읽을 변수 이름. 기본 GLOBAL_CONFIG.
targets본문array<string>, production | preview | development, min items 1아니요변수가 들어갈 환경. 기본은 셋 다. 프로덕션은 그 프로젝트의 소유자·관리자만.
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}

읽기 토큰 연결 끊기 읽기 토큰을 한 프로젝트에서 떼요. 그 프로젝트의 다음 배포부터 변수가 빠져요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구disconnect_edge_config_token
응답객체: ref, id, disconnected
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예읽기 토큰 id. list_edge_config_tokens로 확인해요.
ref경로string, pattern ^[a-z]{20}$예연결할 같은 조직의 프로젝트.
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

엣지 설정 변경 기록 누가 언제 어떤 키를 무엇에서 무엇으로 바꿨는지, 최근 것부터 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_edge_config_history
응답객체: ref, changes
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
limit쿼리integer, min 1, max 500아니요몇 개. 기본 50.
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"]} 모양이에요. 개발자 이상만 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_edge_config
본문 한도256 KiB
응답객체: version, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
set본문object아니요저장할 키와 값 (값은 JSON).
delete본문array<string>아니요지울 키.
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

점진적 배포 상태 점진적 배포 설정과, 진행 중인 배포(새 배포가 받는 방문자 비율)와 최근 기록을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_rolling_releases
응답객체: ref, config, active, recent
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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%)를 넘으면 자동으로 되돌려요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_rolling_releases
본문 한도256 KiB
응답객체: ref, config, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean아니요켜기.
stages본문array<integer>아니요단계별 비율(%).
stage_minutes본문integer, min 1, max 1440아니요단계 길이(분).
auto_advance본문boolean아니요시간이 지나면 자동 진행.
abort_error_rate본문number, min 0.001, max 1아니요자동 중단 5xx 비율. null이면 끄기.
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}

점진적 배포 다음 단계로 진행 중인 배포를 다음 단계 비율로 올려요. 마지막 단계였다면 모두에게 배포해요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구advance_rolling_release
본문 한도256 KiB
응답객체: ref, release
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
action경로string예
reason본문string아니요
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 주소도 함께예요. 비밀을 볼 수 있는 역할만 할 수 있어요.

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구list_kv_keys
응답객체: ref, usage, keys, cursor, rest_url
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
prefix쿼리string아니요접두어.
cursor쿼리string아니요이전 응답의 cursor.
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은 만료 없음)를 돌려줘요.

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구get_kv
응답객체: ref, key, value, ttl
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예
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은 만료까지 초예요. 개발자 이상만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구set_kv
본문 한도256 KiB
응답객체: ref, key, saved
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예
value본문string예값 (JSON).
ttl본문integer, min 1아니요만료까지 초.
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 키 삭제 키를 지워요. 개발자 이상만 할 수 있어요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_kv
응답객체: ref, key, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예
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일 사용량을 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_ai_gateway
응답객체: ref, base_url, settings, providers, usage_30d, top_users_30d
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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 헤더예요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_gateway
본문 한도256 KiB
응답객체: ref, settings, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean아니요켜기.
allow_users본문boolean아니요로그인한 사용자 허용.
cache_seconds본문integer, min 0, max 86400아니요캐시 초.
rate_per_minute본문integer, min 1아니요분당 요청 한도.
platform_fallback본문boolean아니요플랫폼 공급자로 대체.
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 게이트웨이 호출 기록 최근 호출의 공급자, 모델, 상태, 토큰, 지연, 대체 여부를 돌려줘요. 대화 내용은 저장하지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_ai_gateway_logs
응답객체: ref, logs
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
limit쿼리integer, min 1, max 500아니요몇 개. 기본 50.
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만 돼요. 키는 암호화해 저장하고 다시 보여 주지 않아요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구add_ai_provider
본문 한도256 KiB
응답객체: note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string, pattern ^[a-z][a-z0-9-]{0,39}$예이름. 모델을 이름/모델로 부를 때 써요.
kind본문string, openai | anthropic | google | deepseek | openai-compatible예종류.
base_url본문string아니요주소. openai, anthropic, google, deepseek는 비워도 돼요.
key본문string아니요API 키.
models본문array<string>아니요받는 모델. 비우면 모두.
priority본문integer, min 0, max 1000아니요우선순위. 낮은 것부터.
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 공급자 끄기·켜기 설정과 키는 두고 공급자를 쓰지 않거나 다시 써요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_provider_enabled
본문 한도256 KiB
응답객체: ref, id, enabled
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예get_ai_gateway가 돌려준 id.
enabled본문boolean예쓰기.
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 공급자 삭제 공급자와 저장한 키를 지워요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구remove_ai_provider
응답객체: ref, id, removed
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예get_ai_gateway가 돌려준 id.
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). 다 쓰면 다음 기간까지 호출을 거절해요. 적지 않은 값은 그대로 둬요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_budgets
본문 한도256 KiB
응답객체: ref, budgets, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
daily_usd본문string, min 0, max 1000000아니요하루(UTC) 예산, 달러. null이면 없음.
weekly_usd본문string, min 0, max 1000000아니요한 주(월요일부터, UTC) 예산, 달러. null이면 없음.
monthly_usd본문string, min 0, max 1000000아니요한 달(UTC) 예산, 달러. null이면 없음.
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 게이트웨이 키 목록 게이트웨이 키의 이름, 앞부분, 예산, 이번 달 지출, 마지막 사용 시각을 돌려줘요. 키 자체는 돌려주지 않아요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_ai_gateway_keys
응답객체: ref, keys
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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개 제한에 들지 않아요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_ai_gateway_key
본문 한도256 KiB
응답객체: ref, id, name, key, base_url, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string, min length 1, max length 60예키 이름.
daily_usd본문string, min 0, max 1000000아니요하루(UTC) 예산, 달러. null이면 없음.
weekly_usd본문string, min 0, max 1000000아니요한 주(월요일부터, UTC) 예산, 달러. null이면 없음.
monthly_usd본문string, min 0, max 1000000아니요한 달(UTC) 예산, 달러. null이면 없음.
external_ref본문string, max length 200아니요이 키가 프로젝트 장부에서 누구인지(예: 고객의 사용자 ID). 훅에 같이 보내요.
labels본문object아니요자유 라벨 20개까지. 예: {"tier": "1"}. 훅에 같이 보내요.
rate_per_minute본문string, min 1, max 100000아니요분당 요청 수 한도. null이면 없음.
tokens_per_minute본문string, min 1, max 100000000아니요분당 토큰(입력+출력) 한도. null이면 없음.
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이면 한도를 없애요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_gateway_key_limits
본문 한도256 KiB
응답객체: ref, id, limits, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_ai_gateway_keys가 돌려준 id.
rate_per_minute본문string, min 1, max 100000아니요분당 요청 수 한도. null이면 없음.
tokens_per_minute본문string, min 1, max 100000000아니요분당 토큰(입력+출력) 한도. 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도 별칭만 보여요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_model_aliases
본문 한도256 KiB
응답객체: ref, aliases_only, aliases, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
aliases본문array<object>, max items 50예별칭 전체 목록. 빈 배열이면 모두 지워요.
aliases_only본문boolean아니요별칭만 부를 수 있게 해요. 적지 않으면 그대로 둬요.
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로 하면 꺼요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_gateway_hooks
본문 한도256 KiB
응답객체: ref, url, timeout_ms, signing_secret, events, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
url본문string, max length 500아니요훅 주소(https). null이면 꺼요.
timeout_ms본문integer, min 200, max 10000아니요ai.before가 답할 시간(밀리초). 기본 2000.
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 게이트웨이 키 예산 게이트웨이 키 하나의 예산을 바꿔요. 적지 않은 값은 그대로 둬요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_ai_gateway_key_budgets
본문 한도256 KiB
응답객체: ref, id, budgets
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_ai_gateway_keys가 돌려준 id.
daily_usd본문string, min 0, max 1000000아니요하루(UTC) 예산, 달러. null이면 없음.
weekly_usd본문string, min 0, max 1000000아니요한 주(월요일부터, UTC) 예산, 달러. null이면 없음.
monthly_usd본문string, min 0, max 1000000아니요한 달(UTC) 예산, 달러. null이면 없음.
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초 안에 모든 서버에서 거절돼요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구revoke_ai_gateway_key
응답객체: ref, id, revoked
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
id경로string예list_ai_gateway_keys가 돌려준 id.
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 게이트웨이 지출 오늘·이번 주·이번 달 지출과 예산, 하루별·모델별·키별 지출을 달러로 돌려줘요. 자기 키로 부른 공급자는 정가로 계산한 추정이에요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_ai_spend
응답객체: ref, spent_usd, budgets, days, models, keys
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
days쿼리integer, min 1, max 400아니요며칠. 기본 30.
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)를 실행하는지와 시간 한도를 돌려줘요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_middleware
응답객체: ref, enabled, timeout_ms
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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)를 정해요. 끄면 다시 배포하지 않아도 미들웨어 없이 서빙해요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_middleware
본문 한도256 KiB
응답객체: ref, enabled, timeout_ms, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
enabled본문boolean아니요실행.
timeout_ms본문integer, min 100, max 5000아니요시간 한도(ms).
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), 크기, 만료 시각. 자동 브랜치 설정도 와요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_branches
응답객체: ref, automatic, lifetime_days, has_seed, branches
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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부터 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_branch
본문 한도256 KiB
응답객체: ref, branch, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string아니요브랜치 이름(영문 소문자·숫자·-, 30자까지). 없으면 git_branch에서 만들어요.
git_branch본문string아니요연결할 git 브랜치. 그 브랜치의 미리보기 배포에 이 데이터베이스의 주소·키·연결 문자열이 들어가요.
with_seed본문boolean아니요false면 시드를 넣지 않아요.
with_data본문boolean아니요true면 프로젝트의 행까지 복사해요(마이그레이션 다시 실행과 시드 대신). 파일과 그 행은 복사하지 않아요. 데이터가 512MB를 넘으면 거절해요. 진행 상황은 list_branches의 copy에 나와요.
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일, 배포할 때마다 연장). 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_branching
본문 한도256 KiB
응답객체: ref, automatic, lifetime_days, has_seed
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
automatic본문boolean아니요true면 미리보기 브랜치마다 자동으로 만들어요.
seed_sql본문string아니요새 브랜치마다 마이그레이션 뒤에 실행할 SQL(1MB까지). 빈 문자열이면 지워요.
lifetime_days본문integer, min 1, max 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로 바꿔야 병합돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구merge_branch
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 422
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예브랜치 이름(list_branches의 name).
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에 브랜치 이름을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구reset_branch
본문 한도256 KiB
응답객체: ref, branch, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예브랜치 이름.
confirm본문string예브랜치 이름. name과 정확히 같아야 해요.
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 브랜치를 지우거나 풀 리퀘스트를 닫으면 자동으로 지워져요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_branch
본문 한도256 KiB
응답객체: ref, branch, deleted, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예브랜치 이름.
confirm본문string예브랜치 이름. name과 정확히 같아야 해요.
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)로 부를 수 있는지예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구list_queues
응답객체: ref
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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시간.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_queue_metrics
응답객체: ref, hours, queues, points
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
hours쿼리integer, min 1, max 168아니요기간(시간). 기본 24.
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(이름, 초, 개수)로 읽어요. 전용 데이터베이스에서만 돼요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구create_queue
본문 한도256 KiB
응답객체: ref
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string예대기열 이름(영문 소문자·숫자·_, 47자까지).
unlogged본문boolean아니요true면 WAL을 쓰지 않는 빠른 표로 만들어요(서버가 비정상 종료되면 메시지를 잃어요).
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", …)로 부르게 해요. 부른 사람 권한으로 실행되니 대기열 표에 권한과 접근 규칙을 주세요. 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구set_queues_api
본문 한도256 KiB
응답객체: ref
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
exposed본문boolean예true면 열고 false면 닫아요.
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에 대기열 이름을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구delete_queue
본문 한도256 KiB
응답객체: ref, queue, dropped
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예대기열 이름.
confirm본문string예대기열 이름. name과 정확히 같아야 해요.
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에 대기열 이름을 그대로 넣어야 해요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구purge_queue
본문 한도256 KiB
응답객체: ref, queue, purged
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예대기열 이름.
confirm본문string예대기열 이름. name과 정확히 같아야 해요.
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초 동안은 읽히지 않아요.

이름설명
토큰 범위write
역할data.write 소유자·관리자·개발자
MCP 도구send_queue_message
본문 한도256 KiB
응답객체: ref, queue, msg_id
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예대기열 이름.
message본문string예넣을 메시지. JSON 값이면 무엇이든 돼요.
delay본문integer, min 0아니요이 초만큼 지난 뒤에 읽을 수 있게 해요.
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

대기열 메시지 보기 대기열의 앞쪽 메시지를 가져가지 않고 봐요. 읽음 횟수도 가시성 시간도 바꾸지 않아서 작업자가 받을 메시지를 가로채지 않아요.

이름설명
토큰 범위read
역할data.write 소유자·관리자·개발자
MCP 도구peek_queue
응답객체: ref, queue, messages
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예대기열 이름.
limit쿼리integer, min 1, max 100아니요볼 메시지 수(기본 20).
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 = …로 읽어요.

이름설명
토큰 범위read
역할secrets.read 소유자·관리자·개발자
MCP 도구list_vault_secrets
응답객체: ref, enabled, secrets
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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를 켜요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구create_vault_secret
본문 한도256 KiB
응답객체: ref, secret, note
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name본문string예비밀 이름(영문자나 _로 시작, 128자까지).
value본문string예저장할 값(64KB까지). 다시 보여 주지 않아요.
description본문string아니요설명(500자까지).
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). 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구update_vault_secret
본문 한도256 KiB
응답객체: ref, secret
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예비밀 이름.
value본문string아니요새 값.
description본문string아니요새 설명.
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 비밀 삭제 비밀 하나를 지워요. 소유자·관리자만 할 수 있어요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구delete_vault_secret
응답객체: ref, name, deleted
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
name경로string예비밀 이름.
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는 이 요청을 보낸 주소가 허용되는지예요.

이름설명
토큰 범위read
역할조직의 모든 구성원
MCP 도구get_network_restrictions
응답객체: ref
상태 코드200 · 400 · 401 · 403 · 404 · 409
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
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는 영향 없어요). 소유자·관리자만 돼요.

이름설명
토큰 범위write
역할project.admin 소유자·관리자
MCP 도구update_network_restrictions
본문 한도256 KiB
응답결과 JSON (모양은 작업마다 달라요)
상태 코드200 · 400 · 401 · 403 · 404 · 409 · 413
이름위치형식필수설명
ref경로string, pattern ^[a-z]{20}$예프로젝트 ID(ref). list_projects로 확인해요.
allowed_cidrs본문array<string>아니요허용할 주소나 CIDR(예: 203.0.113.0/24). 빈 배열이면 제한을 풀어요.
allow_all본문boolean아니요true면 제한을 풀고 모든 주소를 허용해요.
enforce_ssl본문boolean아니요true면 TLS(sslmode=require) 연결만 받아요. 기본값은 true예요.
confirm본문boolean아니요이 요청을 보낸 주소가 목록에 없어도 저장해요.
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()