API v1
포다 플로우 외부 API
외부 서비스가 조직별 API 키로 계좌와 거래내역을 읽고, 계좌 일부를 고치고, 수동 갱신을 요청합니다. 계좌 등록과 은행 인증정보는 API로 다루지 않으며 웹 화면에서만 관리합니다.
- 01
Google로 가입을 신청하고 운영자 승인을 받습니다.
- 02
조직을 만들고 은행 계좌를 연결합니다.
- 03
API 키 메뉴에서 용도별 키를 발급합니다.
- 04
아래 요청으로 계좌와 거래를 동기화합니다.
인증과 공통 규칙
- 기본 주소는
https://poda-flow-api.server.ryxxn.com/v1입니다. 로컬 개발은http://127.0.0.1:3041/v1입니다. - 모든 요청에
Authorization: Bearer <API 키>를 보냅니다. 키는 발급한 조직 하나에만 묶입니다. read키는 조회만,write키는 계좌 수정과 수동 갱신까지 할 수 있습니다.- 시각은 +09:00이 붙은 ISO 8601 문자열, 금액은 원 단위 정수입니다.
- 오류는
{ "error": { "code", "message" } }형태입니다. - 키는 발급 화면에서 한 번만 보입니다. 서버 환경변수 등 안전한 곳에 보관합니다.
GET/accountsread 키
조직의 계좌 목록과 마지막 수집 상태를 조회합니다.
GET /accounts 요청 예시
curl https://poda-flow-api.server.ryxxn.com/v1/accounts \ -H "Authorization: Bearer $FLOW_API_KEY"- bank는 kb, shinhan, kfcc(새마을금고), accountKind는 personal, corporate입니다.
- balance는 마지막으로 수집한 거래의 잔액이며 수집 전이면 null입니다.
- needsAttention이 true면 웹에서 조회 정보를 다시 저장할 때까지 수집을 멈춥니다.
- lastCollect.status는 queued, running, ok, failed 중 하나입니다.
PATCH/accounts/{id}write 키
계좌 이름(alias)과 자동 수집 여부(active)를 바꿉니다.
PATCH /accounts/{id} 요청 예시
curl -X PATCH https://poda-flow-api.server.ryxxn.com/v1/accounts/acc_01J... \ -H "Authorization: Bearer $FLOW_API_KEY" \ -H "Content-Type: application/json" \ -d '{"alias":"매장 정산","active":false}'- 두 값 모두 선택이지만 하나 이상 보내야 합니다. 다른 필드는 받지 않습니다.
- 응답은 바뀐 계좌 한 건이며 GET /accounts 항목과 같은 형태입니다.
POST/accounts/{id}/refreshwrite 키
수동 갱신을 요청합니다. 수집은 비동기로 진행됩니다.
POST /accounts/{id}/refresh 요청 예시
curl -X POST https://poda-flow-api.server.ryxxn.com/v1/accounts/acc_01J.../refresh \ -H "Authorization: Bearer $FLOW_API_KEY"- 접수되면 { "jobId": "job_...", "status": "queued" }를 반환합니다. 수집 완료를 뜻하지 않습니다.
- 진행 상태는 GET /accounts의 lastCollect로 확인합니다.
- 이미 대기 또는 진행 중이면 409 refresh_running을 반환합니다.
GET/transactionsread 키
포다 플로우에 들어온 순서대로 거래 변경을 받습니다. 커서로 빠짐없이 따라잡습니다.
GET /transactions 요청 예시
curl "https://poda-flow-api.server.ryxxn.com/v1/transactions?limit=500&cursor=$CURSOR" \ -H "Authorization: Bearer $FLOW_API_KEY"- cursor는 직전 응답의 nextCursor입니다. 없으면 처음부터 받습니다.
- accountId로 한 계좌만 받을 수 있습니다. 커서는 같은 필터에서만 사용합니다.
- limit은 기본 500, 최대 1000입니다. hasMore가 true면 바로 다음 페이지를 받습니다.
- id는 다시 수집해도 같습니다. 외부 서비스는 이 값으로 중복을 판정합니다.
- 삭제된 거래는 deletedAt이 채워진 채 다시 나옵니다. 받은 순서대로 적용합니다.
동기화 예시
커서는 서명된 문자열이므로 해석하거나 편집하지 말고 그대로 보관합니다. 변경이 없는 빈 응답의 커서도 유효하므로 주기적으로 같은 방식으로 호출합니다.
거래 동기화 예시
let cursor = await store.get("flow_cursor"); // 처음이면 undefinedwhile (true) { const url = new URL("https://poda-flow-api.server.ryxxn.com/v1/transactions"); if (cursor) url.searchParams.set("cursor", cursor); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.FLOW_API_KEY}` }, }); if (res.status === 429) { await sleep(Number(res.headers.get("Retry-After") ?? 60) * 1000); continue; } const page = await res.json(); for (const item of page.items) await upsertTransaction(item); // id 기준 cursor = page.nextCursor; await store.set("flow_cursor", cursor); if (!page.hasMore) break;}오류 코드
| 상태 | code | 뜻 |
|---|---|---|
| 400 | invalid_request | 입력 형식, 커서나 범위가 잘못됨 |
| 401 | unauthorized | 키가 없거나 틀리거나 폐기됨 |
| 403 | forbidden | read 키로 쓰기를 요청함 |
| 404 | not_found | 다른 조직의 계좌이거나 없음 |
| 409 | refresh_running | 이미 대기 또는 갱신 중 |
| 409 | account_inactive | 자동 수집이 중지된 계좌 |
| 409 | authentication_required | 웹에서 조회 정보 확인 필요 |
| 413 | request_too_large | JSON 본문 32KiB 초과 |
| 429 | rate_limited | 키당 분당 120회 초과. Retry-After를 따름 |
| 503 | service_unavailable | DB 등 서비스 연결 실패 |