개발자 센터
BankFlow은 은행 입출금 알림을 통합 관리하고, 실시간 입금 자동매칭을 제공하는 SaaS 플랫폼입니다.
API를 통해 다음 기능을 이용할 수 있습니다:
- 입출금 데이터 실시간 수신 — 계좌의 입출금 발생 시 Webhook으로 즉시 전달
- 주문-입금 자동매칭 — 쇼핑몰 주문을 등록하면, 입금 시 입금자명+금액으로 1초 자동매칭
- 거래 데이터 조회 — 저장된 거래 내역을 API로 조회
인증
모든 API 요청에는 다음 헤더가 필요합니다:
Content-Type: application/json X-API-Key: your-api-key X-Store-Id: your-store-key (선택, 주문 API 사용 시 필요)
API Key는 대시보드 > 설정 > API 키에서 생성할 수 있습니다.
X-Store-Id는 여러 사이트를 운영할 때 어떤 사이트의 요청인지 구분하기 위한 헤더입니다. 대시보드 > 상점 관리에서 상점을 등록하면 Store Key가 발급됩니다.
오류 처리
모든 응답은 JSON 형식이며, success 필드로 성공 여부를 판단합니다:
성공 응답
{
"success": true,
"message": "주문이 등록되었습니다.",
"data": { ... }
}
실패 응답
{
"success": false,
"message": "필수 항목이 누락되었습니다: amount"
}
| HTTP 코드 | 의미 |
|---|---|
| 200 | 성공 |
| 400 | 잘못된 요청 (파라미터 오류) |
| 401 | 인증 실패 (API Key 오류) |
| 403 | 권한 없음 |
| 404 | 리소스 없음 |
| 405 | 허용되지 않는 메서드 |
| 409 | 충돌 (중복 등) |
| 500 | 서버 오류 |
입출금 데이터 실시간 수신
계좌에 입출금이 발생하면 알림전달앱 → BankFlow → 등록된 Webhook URL로 데이터를 전송합니다.
설정 방법
- 대시보드 > 설정에서 Webhook URL과 Webhook Secret을 확인합니다.
- 알림전달앱에 Webhook URL을 등록합니다.
- 은행 앱에서 SMS 통지 서비스를 신청합니다.
수신 데이터 형식
알림전달앱에서 BankFlow로 전송하는 형식:
POST https://bankflow.co.kr/api/v1/webhook
인증 방식 (택 1)
| 방식 | 설명 |
|---|---|
| API 키 | 헤더에 X-API-Key: your-api-key |
| 시크릿 | Body에 "secret": "your-webhook-secret" 포함 |
요청 Body
{
"message": "[입금] 홍길동 313,500원 1005-204-572***계좌 잔액 7,566,003원 04/17 16:29:16",
"source": "macrodroid",
"secret": "your-webhook-secret"
}
또는 상세 형식:
{
"app": "알림전달앱이름",
"title": "우리은행",
"message": "[입금] 홍길동 313,500원 1005-204-572***계좌 잔액 7,566,003원 04/17 16:29:16",
"timestamp": "2024-04-17 16:29:16",
"secret": "your-webhook-secret"
}
주문 등록
무통장입금 주문을 등록합니다. 해당 금액+입금자명으로 입금이 발생하면 자동으로 매칭됩니다.
POST https://bankflow.co.kr/api/v1/order
Request Body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| order_ref | string | O | 쇼핑몰 주문번호 (고유) |
| amount | integer | O | 주문 금액 (원) |
| depositor_name | string | O | 예상 입금자명 |
| buyer_name | string | 주문자명 (입금자와 다를 경우) | |
| bank_account_id | integer | 특정 계좌만 매칭 (미지정 시 전체) | |
| callback_url | string | 매칭 완료 시 결과 전송할 URL | |
| expires_hours | integer | 매칭 대기 시간 (기본 336=14일) | |
| meta | object | 추가 데이터 (콜백 시 함께 전달) |
요청 예시
{
"order_ref": "ORD-20240417-001",
"amount": 50000,
"depositor_name": "홍길동",
"callback_url": "https://myshop.com/api/payment-confirm",
"meta": {
"product": "프리미엄 플랜",
"user_id": 1234
}
}
응답 예시
{
"success": true,
"message": "주문이 등록되었습니다.",
"data": {
"order_id": 1,
"order_ref": "ORD-20240417-001",
"status": "pending"
}
}
주문 매칭제외
특정 주문을 매칭 대상에서 제외합니다.
POST https://bankflow.co.kr/api/v1/order-exclude
Request Body
{
"order_ref": "ORD-20240417-001"
}
// 또는
{
"order_id": 1
}
주문 조회
등록된 주문 목록을 조회합니다.
GET https://bankflow.co.kr/api/v1/orders?status=pending&page=1&per_page=30
Query Parameters
| 파라미터 | 설명 |
|---|---|
| status | pending, matched, excluded, expired, cancelled (선택) |
| page | 페이지 번호 (기본 1) |
| per_page | 페이지당 건수 (기본 30, 최대 100) |
매칭 완료 Webhook
주문이 입금과 매칭되면 등록된 callback_url로 다음 데이터가 전송됩니다:
WEBHOOK callback_url (고객사 서버)
{
"event": "order.matched",
"order_id": 1,
"order_ref": "ORD-20240417-001",
"amount": 50000,
"depositor_name": "홍길동",
"transaction_id": 123,
"matched_at": "2024-04-17 16:29:16",
"balance_after": 7566003,
"meta": {
"product": "프리미엄 플랜",
"user_id": 1234
}
}
응답 규격
콜백을 정상적으로 수신했으면 아래와 같이 응답해야 합니다. 미응답 또는 오류 시 최대 3회 재전송됩니다.
| 항목 | 값 |
|---|---|
| HTTP 상태코드 | 200 |
| Content-Type | application/json |
| Response Body | {"status": "success"} |
// PHP 예시
http_response_code(200);
header('Content-Type: application/json');
echo json_encode(['status' => 'success']);
{"status": "success"}가 아닌 응답은 모두 실패로 간주됩니다.
상점 (Store)
여러 사이트를 운영하는 경우, 각 사이트를 상점(Store)으로 등록하여 독립적으로 관리할 수 있습니다.
상점별 분리 항목
| 항목 | 설명 |
|---|---|
| Store Key | API 요청 시 X-Store-Id 헤더에 사용 |
| 콜백 URL | 주문별 미지정 시 상점의 기본 URL 사용 |
| 연결 계좌 | 이 상점의 입금을 특정 계좌에서만 매칭 |
| 주문 네임스페이스 | 상점별로 order_ref 독립 관리 (다른 상점과 겹쳐도 OK) |
사용 예시
// BlogMate에서 주문 등록 POST /api/v1/order Headers: X-API-Key: bf_xxxxx X-Store-Id: blogmate // Work ERP에서 주문 등록 (같은 API Key, 다른 Store) POST /api/v1/order Headers: X-API-Key: bf_xxxxx X-Store-Id: work-erp
거래 내역 조회
저장된 거래 내역을 조회합니다.
GET https://bankflow.co.kr/api/v1/transactions?from=2024-01-01&to=2024-12-31&type=deposit
Query Parameters
| 파라미터 | 설명 |
|---|---|
| from | 시작일 (YYYY-MM-DD) |
| to | 종료일 (YYYY-MM-DD) |
| type | deposit, withdrawal (선택) |
| account_id | 특정 계좌 ID (선택) |
| page | 페이지 번호 |
| per_page | 페이지당 건수 (최대 100) |
계좌 목록 조회
등록된 계좌 목록을 조회합니다.
GET https://bankflow.co.kr/api/v1/accounts
현금영수증 발행 API
외부 서비스에서 API로 현금영수증을 발행할 수 있습니다. 팝빌 연동이 완료되어 있어야 합니다.
POST https://bankflow.co.kr/api/v1/cashbill
요청 헤더
| 헤더 | 설명 |
|---|---|
X-API-Key | API 키 |
Content-Type | application/json |
요청 Body
{
"amount": 11000,
"trade_type": "income",
"identity_num": "01012345678",
"buyer_name": "홍길동",
"item_name": "포인트 충전",
"transaction_id": 123
}
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| amount | integer | Y | 거래금액 (부가세 포함) |
| trade_type | string | Y | income (소득공제) / expense (지출증빙) |
| identity_num | string | Y | 식별번호 (휴대폰번호 또는 사업자번호) |
| buyer_name | string | 구매자명 | |
| item_name | string | 품목명 | |
| transaction_id | integer | BankFlow 거래 ID (연결 시 증빙 상태 자동 업데이트) |
응답
{
"success": true,
"message": "현금영수증이 발행되었습니다.",
"data": {
"approval_num": "TB0000043",
"mgt_key": "BF260320143025abc1"
}
}
세금계산서 발행 API
외부 서비스에서 API로 전자세금계산서를 발행할 수 있습니다. 팝빌 연동 + 공인인증서 등록이 필요합니다.
POST https://bankflow.co.kr/api/v1/taxinvoice
요청 Body
{
"amount": 110000,
"invoicee_corp_num": "1234567890",
"invoicee_corp_name": "거래처상호",
"invoicee_ceo_name": "대표자명",
"invoicee_email": "tax@example.com",
"item_name": "서비스 이용료",
"write_date": "20260320",
"transaction_id": 123
}
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| amount | integer | Y | 합계금액 (부가세 포함) |
| invoicee_corp_num | string | Y | 공급받는자 사업자번호 (하이픈 없이) |
| invoicee_corp_name | string | Y | 공급받는자 상호 |
| invoicee_ceo_name | string | Y | 공급받는자 대표자명 |
| invoicee_email | string | 공급받는자 이메일 (계산서 발송) | |
| item_name | string | 품목명 (기본: 서비스 이용료) | |
| write_date | string | 작성일자 yyyyMMdd (기본: 오늘) | |
| transaction_id | integer | BankFlow 거래 ID |
응답
{
"success": true,
"message": "세금계산서가 발행되었습니다.",
"data": {
"mgt_key": "BF260320143025abc1"
}
}
tax_type, tax_status, tax_note 필드로 증빙 상태를 확인할 수 있습니다.
알림 웹훅 수신
알림 규칙에서 "외부 웹훅"을 선택하면, 조건에 매칭되는 거래 발생 시 지정한 URL로 POST 요청을 보냅니다.
설정 방법
- 대시보드 > 알림 규칙 > 규칙 추가
- 조건 설정 (예: 입금/출금 전체, 금액 초과 등)
- 알림 방식: "외부 웹훅" 또는 "웹 알림 + 외부 웹훅" 선택
- 웹훅 URL 입력 + 데이터 형식 선택 (JSON / 메시지)
요청 형식
POST 지정한 웹훅 URL
JSON 형식 (API 연동용)
헤더: Content-Type: application/json, X-BankFlow-Event: transaction.alert
{
"event": "transaction.alert",
"type": "deposit",
"amount": 880000,
"counterpart": "홍길동",
"balance_after": 8761172,
"transacted_at": "2026-03-19 08:49:25",
"rule_name": "모든 입금 알림",
"transaction_id": 2345,
"account_id": 1
}
| 필드 | 타입 | 설명 |
|---|---|---|
| event | string | transaction.alert (정상 알림) 또는 transaction.flagged (이상거래) |
| type | string | deposit (입금), withdrawal (출금), note (비거래) |
| amount | integer | 거래 금액 (원) |
| counterpart | string|null | 상대방 (입금자명 또는 수취인) |
| balance_after | integer|null | 거래 후 잔액 |
| transacted_at | string | 거래 일시 (Y-m-d H:i:s) |
| rule_name | string | 매칭된 알림 규칙명 |
| transaction_id | integer | BankFlow 거래 ID |
| account_id | integer | BankFlow 계좌 ID |
메시지 형식 (사람 읽기용)
헤더: Content-Type: text/plain; charset=utf-8
[입금] 880,000원 홍길동 · 880,000원 · 잔액 8,761,172원
수신 측 구현 예시 (PHP)
// 웹훅 수신 엔드포인트
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if ($data['event'] === 'transaction.alert' && $data['type'] === 'deposit') {
// 입금 알림 처리
$amount = $data['amount'];
$counterpart = $data['counterpart'];
$balance = $data['balance_after'];
// 예: DB 기록, 슬랙 알림, 포인트 충전 등
logDeposit($amount, $counterpart, $balance);
}
// 200 OK 응답 (필수)
http_response_code(200);
echo 'OK';
응답 규격
웹훅을 정상 수신했으면 아래와 같이 응답합니다. 미응답 시 최대 3회 재전송됩니다.
| 항목 | 값 |
|---|---|
| HTTP 상태코드 | 200 |
| Response Body | {"status": "success"} 또는 OK |
거래 데이터 동기화 가이드
BankFlow의 거래 데이터를 자체 서비스 DB에 동기화하여 사용할 수 있습니다.
권장 테이블 구조
CREATE TABLE bankflow_transactions (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
bf_id BIGINT UNSIGNED NOT NULL COMMENT 'BankFlow 거래 ID',
bank_account_id INT UNSIGNED DEFAULT NULL,
type VARCHAR(20) NOT NULL DEFAULT 'deposit',
amount BIGINT UNSIGNED NOT NULL DEFAULT 0,
balance_after BIGINT DEFAULT NULL,
counterpart VARCHAR(100) DEFAULT NULL,
memo VARCHAR(500) DEFAULT NULL,
transacted_at DATETIME NOT NULL,
source VARCHAR(20) DEFAULT 'notification',
is_flagged TINYINT(1) NOT NULL DEFAULT 0,
synced_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_bf_id (bf_id),
INDEX idx_type (type),
INDEX idx_date (transacted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
| bf_id | BIGINT | BankFlow 거래 고유 ID (중복 방지 키) |
| type | VARCHAR(20) | deposit (입금), withdrawal (출금), note (비거래 메모) |
| amount | BIGINT | 거래 금액 (원) |
| balance_after | BIGINT | 거래 후 잔액 (없으면 NULL) |
| counterpart | VARCHAR | 상대방 (입금자명 또는 수취인) |
| memo | VARCHAR | 은행 적요 |
| transacted_at | DATETIME | 거래 일시 |
| source | VARCHAR | notification (알림앱), api, manual (수동입력), csv (CSV업로드) |
| is_flagged | TINYINT | 이상거래 여부 (0/1) |
note (비거래 메모) 등 추가 타입이 존재할 수 있습니다.
동기화 방식
거래 내역 조회 API를 주기적으로 호출하여 bf_id 기준으로 없는 데이터만 INSERT합니다.
최초 전체 동기화
// 100건씩 페이지네이션으로 전체 데이터 수집
GET /api/v1/transactions?from=2020-01-01&to=2026-12-31&page=1&per_page=100
// 응답
{
"success": true,
"data": {
"transactions": [...],
"total": 2246, // 전체 건수
"page": 1, // 현재 페이지
"per_page": 100 // 페이지당 건수
}
}
// total_pages = ceil(total / per_page) = 23
// page 1~23까지 반복 호출
증분 동기화 (크론탭)
// 최근 3일만 조회하여 새로운 것만 INSERT GET /api/v1/transactions?from=2026-03-15&to=2026-03-18&per_page=100 // bf_id UNIQUE KEY로 중복 자동 방지 // 5분 간격 크론탭 권장
자주 묻는 질문
자동매칭되는 기준은 무엇인가요?
입금 내역의 입금자명과 금액이 대기 중인 주문의 입금자명, 금액과 정확히 일치하는 주문이 1건일 때 자동매칭됩니다. 일치하는 주문이 없거나 2건 이상이면 매칭되지 않습니다.
매칭이 안 되는 경우는?
- 주문이 입금보다 나중에 등록된 경우 (주문을 먼저 등록해야 합니다)
- 입금자명에 공백이 포함되어 정확히 일치하지 않는 경우
- 주문 만료 시간(기본 14일)이 지난 경우
- 동일 입금자명+금액의 주문이 2건 이상인 경우
Webhook이 오지 않아요
- 등록한 Webhook URL이 외부에서 접근 가능한 HTTPS 주소인지 확인하세요.
- 서버 방화벽에서 외부 요청을 차단하고 있지 않은지 확인하세요.
- 유효한 SSL 인증서가 설치되어 있는지 확인하세요.
- 대시보드 > Webhook 로그에서 전송 내역을 확인할 수 있습니다.
API 호출 제한이 있나요?
구독 플랜에 따라 시간당 요청 수가 제한됩니다. 기본 1,000건/시간입니다.