본문으로 건너뛰기

계좌조회 API 문서

계좌조회 API 개요

Bank API는 국내 은행 계좌의 거래내역을 조회할 수 있는 REST API입니다. 간단한 HTTP 요청으로 은행 데이터를 연동할 수 있습니다.

Base URL

https://api.bankapi.co.kr

테스트용 API Key

아래 키를 사용하여 바로 테스트해볼 수 있습니다:

Test Credentials
API Key:    {{API_KEY}}
Secret Key: {{SECRET_KEY}}
주의: 위 키는 테스트 전용입니다. 실제 서비스에서는 반드시 본인의 API Key를 발급받아 사용하세요. 테스트 키는 Rate Limit이 제한되어 있으며, 예고 없이 변경될 수 있습니다.

계좌조회 API 인증 방식

API 요청 시 Authorization 헤더에 API Key와 Secret Key를 포함해야 합니다.

Private Mode (권장)

API Key와 Secret Key를 콜론(:)으로 연결하여 Bearer 토큰으로 전송합니다.

Authorization: Bearer {apiKey}:{secretKey}

인증 예시

Authorization: Bearer {{API_KEY}}:{{SECRET_KEY}}

계좌거래내역 조회

지정한 기간의 계좌 거래내역을 조회합니다.

POST /v1/transactions

요청 파라미터

파라미터 타입 필수 설명
bankCode string 필수 은행 코드 (NH, KB, WR, IBK). 신한 SH는 로그인 기반 조회 사용
accountNumber string 필수 계좌번호 (하이픈 없이)
accountPassword string 필수 계좌 비밀번호
residentNumber string 필수 신원 확인 번호 — 숫자만(하이픈·공백 없이). 개인은 생년월일 6자리(YYMMDD), 사업자는 사업자등록번호 10자리(은행별 자릿수는 아래 표)
accountType string 선택 personal(개인) 또는 business(사업자). 보내지 않으면 지금은 residentNumber가 6자리면 개인, 그 밖이면 사업자로 봅니다. 앞으로는 보내지 않으면 개인으로 볼 예정이니 사업자 계좌는 business를 함께 보내 주세요.
startDate string 필수 조회 시작일 (YYYYMMDD)
endDate string 필수 조회 종료일 (YYYYMMDD)

은행 코드

코드 은행명 코드 은행명
NH 농협은행 KB KB국민은행
WR 우리은행 IBK 기업은행
SH 신한은행 (로그인 기반 → 아래 섹션 사용)

개인·사업자 신원 확인 번호

residentNumber에 넣는 번호입니다. 사업자등록번호 10자리를 보내면 은행이 받는 자릿수로 맞춰 조회합니다(우리은행 뒤 5자리, 기업은행 뒤 7자리).

은행 개인 (personal) 사업자 (business)
농협 NH · 국민 KB 생년월일 6자리 사업자등록번호 10자리
우리 WR 생년월일 6자리 사업자등록번호 10자리 또는 뒤 5자리
기업 IBK 생년월일 6자리 사업자등록번호 10자리 또는 뒤 7자리

숫자 말고 다른 글자가 있거나 자릿수가 맞지 않으면 은행에 조회하지 않고 400과 함께 아래 코드로 알려 드립니다. 같은 계좌 5분 제한은 걸리지 않으니 고쳐서 바로 다시 보내면 됩니다.

error 언제
INVALID_RESIDENT_NUMBER 숫자 말고 다른 글자가 있거나 문자열이 아님 · accountType 없이 보낸 번호의 자릿수가 개인·사업자 어느 쪽에도 맞지 않음
INVALID_ACCOUNT_TYPE accountType이 personal·business가 아님
INVALID_BIRTH_DATE 개인(personal)인데 생년월일 6자리가 아님
INVALID_BUSINESS_NUMBER 사업자(business)인데 그 은행이 받는 자릿수가 아님

코드 예제

bank-api ~ terminal
curl -X POST https://api.bankapi.co.kr/v1/transactions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {{API_KEY}}:{{SECRET_KEY}}" \
  -d '{
    "bankCode": "NH",
    "accountNumber": "{{ACCOUNT_NUMBER}}",
    "accountPassword": "1234",
    "residentNumber": "800101",
    "accountType": "personal",
    "startDate": "20260101",
    "endDate": "20260110"
  }'

응답 예시

200 OK
{
  "success": true,
  "transactions": [
    {
      "date": "2026-01-10",
      "time": "14:30:25",
      "description": "스마트출금",
      "displayName": "스타벅스",
      "counterparty": "스타벅스코리아",
      "amount": 50000,
      "balance": 1234567,
      "type": "withdrawal",
      "branch": "강남"
    },
    {
      "date": "2026-01-09",
      "time": "09:15:00",
      "description": "FBS입금",
      "displayName": "",
      "counterparty": "홍길동",
      "amount": 3000000,
      "balance": 1284567,
      "type": "deposit",
      "branch": "국민 0068738"
    }
  ],
  "accountInfo": {
    "accountNumber": "{{ACCOUNT_NUMBER}}",
    "balance": 1284567
  }
}

응답 필드

필드 타입 설명
date string 거래일자 — 은행에 따라 YYYY-MM-DD 또는 YYYY/MM/DD 형식
time string 거래시간 (HH:MM:SS)
type string 입출금 구분 ("deposit" 또는 "withdrawal")
amount number 거래금액
balance number 거래 후 잔액
description string 거래 유형 (예: 카드결제, 스마트출금, FBS입금)
displayName string 내통장표시내용/거래내용 — 은행에 따라 통장 표시 이름 또는 거래내용이 들어갑니다 (빈 문자열일 수 있음)
counterparty string 의뢰인/수취인 — 상대방 이름 또는 거래내용 (KB·IBK 지원, 그 외 은행은 빈 문자열일 수 있음)
branch string 거래점 — 은행에 따라 상대은행이 들어갈 수 있음 (빈 문자열일 수 있음)
memo string 메모 (빈 문자열일 수 있음)
accountInfo: 응답에는 계좌 요약 정보 accountInfo가 함께 옵니다. accountNumber·balance는 공통이며, 은행에 따라 예금 종류(accountName)·예금주명(accountHolder)이 포함될 수 있습니다.

실패 응답 — code와 message

은행이 조회를 거절하면 HTTP 200에 success: false로 옵니다. HTTP 상태만 보지 말고 success를 확인하세요. 모든 실패(200·400·401·429·500)에 code(프로그램용 종류)와 message(사람이 읽는 안내)가 함께 오니, 분기는 code로 하고 화면에는 message를 띄우면 됩니다. error는 예전부터 있던 칸으로 값이 바뀌지 않습니다(은행 거절은 은행 문장 그대로, 나머지는 코드 문자열).

200 OK - 은행이 거절 (success: false)
{
  "success": false,
  "transactions": [],
  "error": "계좌번호 오류입니다. 계좌번호를 다시 확인해 주세요. (안내코드 01506)",
  "code": "BANK_REJECTED",
  "message": "계좌번호 오류입니다. 계좌번호를 다시 확인해 주세요. (안내코드 01506)"
}
code 뜻 message
BANK_REJECTED 은행이 거절 — 계좌번호·비밀번호·생년월일(사업자번호) 불일치, 빠른조회 미등록, 오류 횟수 초과 등 은행이 보낸 문장 그대로
BANK_TIMEOUT 은행 응답이 제한 시간(60초) 안에 오지 않음 정해 둔 안내
BANK_UNAVAILABLE 은행에 연결하지 못했거나 은행 서버가 오류로 답함 정해 둔 안내
KEYPAD_FAILED 은행 보안키패드에 값을 넣지 못함 — 비밀번호·생년월일에 숫자 아닌 글자가 있거나 키패드 인식 실패 정해 둔 안내
UNEXPECTED_PAGE 은행이 예상과 다른 화면을 보냄(점검 등) 정해 둔 안내
CRAWLER_ERROR 그 밖의 조회 서버 오류 정해 둔 안내

은행에 가기 전에 끝나는 오류의 code는 error와 같은 코드입니다: MISSING_FIELDS·INVALID_BANK_CODE·USE_LOGIN_ENDPOINT·신원 확인 번호 오류 4개(400), UNAUTHORIZED(401), ACCOUNT_COOLDOWN·QUERY_QUOTA_EXCEEDED·TOO_MANY_REQUESTS(429), CRAWLER_UNAVAILABLE(조회 서버가 답하지 않음, 500).

에러 응답

400 Bad Request - 신원 확인 번호 자릿수
{
  "success": false,
  "error": "INVALID_BUSINESS_NUMBER",
  "code": "INVALID_BUSINESS_NUMBER",
  "message": "사업자번호의 뒷7자리가 필요해요."
}
429 Too Many Requests - 동일 계좌 쿨다운
{
  "success": false,
  "error": "ACCOUNT_COOLDOWN",
  "code": "ACCOUNT_COOLDOWN",
  "message": "동일 계좌는 5분에 1회만 조회할 수 있습니다. 잠시 후 다시 시도해 주세요.",
  "retryAfterSec": 540
}
429 Too Many Requests - 조회 한도 초과
{
  "success": false,
  "error": "QUERY_QUOTA_EXCEEDED",
  "code": "QUERY_QUOTA_EXCEEDED",
  "message": "조회 한도(30분당 30회)를 초과했습니다.",
  "retryAfterSec": 1200
}
429 Too Many Requests - 요청 한도 초과
{
  "success": false,
  "error": "TOO_MANY_REQUESTS",
  "code": "TOO_MANY_REQUESTS",
  "message": "요청 한도(30분당 60회)를 초과했습니다.",
  "retryAfterSec": 800
}
401 Unauthorized - 인증 실패
{
  "success": false,
  "error": "Invalid API Key",
  "code": "UNAUTHORIZED",
  "message": "인증에 실패했습니다. Authorization: Bearer {apiKey}:{secretKey} 형식과 키 값을 확인해 주세요."
}
참고: Bank API에 계좌를 따로 등록할 필요는 없지만, 해당 은행의 빠른조회(간편조회) 서비스가 계좌에 등록되어 있어야 합니다. 같은 계좌는 5분에 1회, 30분당 최대 30회(성공 기준)·60회(요청 기준)까지 조회할 수 있습니다.

로그인 기반 거래내역 조회 (신한)

신한은행처럼 홈페이지 ID/PW 로그인이 필요한 은행의 거래내역을 조회합니다. 로그인 1회로 등록된 여러 계좌를 한 번에 조회합니다(배치). 무로그인 4개 은행(농협·국민·우리·기업)은 위 거래내역 조회를 사용하세요.

POST /v1/transactions/login

요청 파라미터

파라미터 타입 필수 설명
bankCode string 필수 은행 코드 (현재 SH 신한)
loginId string 필수 인터넷뱅킹 이용자 ID
loginPassword string 필수 인터넷뱅킹 로그인 비밀번호
accounts array 필수 조회할 계좌 목록(1개 이상). 각 항목: { accountNumber, accountPassword } — 계좌번호(하이픈 없이)와 계좌 비밀번호(4자리)
startDate string 필수 조회 시작일 (YYYYMMDD)
endDate string 필수 조회 종료일 (YYYYMMDD)
sortOrder string 선택 정렬: recent(최근거래순, 기본) 또는 old(과거거래순)
지원 은행: 신한은행(SH) — 인터넷뱅킹 회원이 간편계좌관리에 등록한 간편계좌를 조회합니다. 로그인 자격증명·계좌 비밀번호는 저장·기록하지 않고 조회에만 사용합니다.

코드 예제

cURL
curl -X POST https://api.bankapi.co.kr/v1/transactions/login \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {{API_KEY}}:{{SECRET_KEY}}" \
  -d '{
    "bankCode": "SH",
    "loginId": "{{LOGIN_ID}}",
    "loginPassword": "{{LOGIN_PASSWORD}}",
    "accounts": [
      { "accountNumber": "{{ACCOUNT_NUMBER}}", "accountPassword": "{{ACCOUNT_PASSWORD}}" }
    ],
    "startDate": "20260101",
    "endDate": "20260131",
    "sortOrder": "recent"
  }'

응답 예시

200 OK
{
  "success": true,
  "results": [
    {
      "accountNumber": "{{ACCOUNT_NUMBER}}",
      "success": true,
      "accountInfo": {
        "accountNumber": "{{ACCOUNT_NUMBER}}",
        "accountName": "쏠편한 입출금통장(저축예금)",
        "accountHolder": "홍길동",
        "balance": 1284567
      },
      "transactions": [
        {
          "date": "2026/01/10",
          "time": "14:30:25",
          "description": "타행이체",
          "displayName": "",
          "counterparty": "홍길동",
          "amount": 50000,
          "balance": 1234567,
          "type": "withdrawal",
          "branch": "종로중"
        }
      ]
    }
  ]
}

응답 필드

필드 타입 설명
success boolean 로그인 성공 여부. 계좌별 성공/실패는 results[].success로 구분
results array 계좌별 결과 배열. 각 원소는 무로그인 단건 응답과 동일한 형태(구분용 accountNumber 포함)
results[].accountNumber string 해당 계좌번호 (결과 구분용)
results[].success boolean 해당 계좌 조회 성공 여부
results[].transactions array 거래내역 배열 (거래내역 조회와 동일 필드)
results[].accountInfo object 계좌 요약: accountNumber, accountName, accountHolder, balance
results[].error string 실패 시 에러 코드 (선택) — 은행이 준 코드 또는 조회 서버 코드
results[].code string 계좌별 실패 종류 (선택) — BANK_REJECTED·KEYPAD_FAILED·BANK_TIMEOUT·BANK_UNAVAILABLE·UNEXPECTED_PAGE·CRAWLER_ERROR·PIN_INVALID_LENGTH·ACCOUNT_COOLDOWN 등 (무로그인 조회의 실패 응답과 같은 종류)
results[].message string 계좌별 실패 안내 (선택) — 은행이 보낸 문장 그대로, 없으면 정해 둔 안내
code / message string 로그인 자체가 실패했을 때(success: false) 실패 종류와 안내. error에는 은행 코드(예: PFM40133) 또는 조회 서버 코드가 그대로 옵니다
참고: 신한은 인터넷뱅킹 로그인이 필요하며, 로그인 1회로 accounts의 여러 계좌를 순차 조회합니다. 같은 계좌 5분 1회 등 조회 제한은 아래와 동일하게 적용됩니다.

계좌조회 API Rate Limiting

거래내역 조회는 남용 방지를 위해 아래 제한이 적용됩니다. 제한 초과 시 429 에러가 반환됩니다.

제한 기준 한도 에러 코드
동일 계좌 재조회 계좌별 (전역 · 키/IP 무관) 5분당 1회 ACCOUNT_COOLDOWN
조회 횟수(성공 기준) API Key별 · IP별 30분당 30회 QUERY_QUOTA_EXCEEDED
요청 횟수(성공+실패) API Key별 30분당 60회 TOO_MANY_REQUESTS

Retry-After 헤더

제한에 걸리면 응답 헤더와 본문(retryAfterSec)에서 재시도까지 남은 시간(초)을 확인할 수 있습니다:

HTTP/1.1 429 Too Many Requests
Retry-After: 540

실전: 429 자동 재시도 (복붙 가능)

제한에 걸리면 retryAfterSec만큼 기다렸다 재시도하는 패턴입니다. 응답 파싱까지 포함해 바로 쓸 수 있습니다.

JavaScript
const API_KEY = '{{API_KEY}}';
const SECRET_KEY = '{{SECRET_KEY}}';

async function getTransactions(body, maxRetries = 2) {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch('https://api.bankapi.co.kr/v1/transactions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}:${SECRET_KEY}`
      },
      body: JSON.stringify(body)
    });
    const data = await res.json();

    // 429(제한) 이면 retryAfterSec 만큼 대기 후 재시도
    if (res.status === 429 && attempt < maxRetries) {
      const waitSec = data.retryAfterSec || Number(res.headers.get('Retry-After')) || 60;
      console.log(`Rate limit(${data.error}) — ${waitSec}s 후 재시도`);
      await new Promise(r => setTimeout(r, waitSec * 1000));
      continue;
    }
    if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
    return data.transactions;
  }
}

// 사용 예
const txs = await getTransactions({
  bankCode: 'NH', accountNumber: '{{ACCOUNT_NUMBER}}', accountPassword: '1234',
  residentNumber: '800101', startDate: '20260101', endDate: '20260110'
});
txs.forEach(t => console.log(`${t.date} ${t.type} ${t.amount}원 (잔액 ${t.balance})`));
Python
import requests, time

API_KEY = '{{API_KEY}}'
SECRET_KEY = '{{SECRET_KEY}}'

def get_transactions(body, max_retries=2):
    for attempt in range(max_retries + 1):
        res = requests.post(
            'https://api.bankapi.co.kr/v1/transactions',
            headers={
                'Content-Type': 'application/json',
                'Authorization': f'Bearer {API_KEY}:{SECRET_KEY}'
            },
            json=body
        )
        data = res.json()

        # 429(제한) 이면 retryAfterSec 만큼 대기 후 재시도
        if res.status_code == 429 and attempt < max_retries:
            wait = data.get('retryAfterSec') or int(res.headers.get('Retry-After', 60))
            print(f"Rate limit({data['error']}) — {wait}s 후 재시도")
            time.sleep(wait)
            continue
        res.raise_for_status()
        return data['transactions']

# 사용 예
txs = get_transactions({
    'bankCode': 'NH', 'accountNumber': '{{ACCOUNT_NUMBER}}', 'accountPassword': '1234',
    'residentNumber': '800101', 'startDate': '20260101', 'endDate': '20260110'
})
for t in txs:
    print(f"{t['date']} {t['type']} {t['amount']}원 (잔액 {t['balance']})")
팁: ACCOUNT_COOLDOWN(같은 계좌 5분)은 대기가 길어 자동 재시도보다 폴링 주기를 5분 이상으로 두는 편이 낫습니다. 자동 재시도는 QUERY_QUOTA_EXCEEDED·TOO_MANY_REQUESTS처럼 짧은 일시적 초과에 유용합니다.

계좌조회 API 에러 코드

API 요청 실패 시 반환되는 에러 코드입니다.

코드 상태 설명
400 Bad Request 잘못된 요청 파라미터
401 Unauthorized 인증 실패 (API Key/Secret Key 오류)
403 Forbidden 접근 차단 — 국내(대한민국) IP가 아닌 곳에서 호출한 경우가 대부분입니다
404 Not Found 존재하지 않는 엔드포인트
429 Too Many Requests Rate Limit 초과
500 Internal Server Error 서버 내부 오류
403이 반복된다면 — 호출 위치를 확인하세요. BankAPI는 보안 정책상 대한민국 국내 IP에서의 호출만 허용합니다. 해외 리전 서버(AWS 도쿄·미국, Linode, Vultr, Render, Heroku 등)에서의 호출은 차단되며, 개별 IP 화이트리스트·예외 등록은 제공하지 않습니다. 국내 서버라고 알고 계신데도 차단된다면, API를 호출하는 바로 그 서버에서 curl https://api.ipify.org를 실행해 실제 외부 IP부터 확인해 주세요. 쇼핑몰 호스팅과 API를 호출하는 프로그램이 서로 다른 서버에 있는 경우가 많습니다. 해외 서버라면 국내 리전(카페24, 네이버클라우드, AWS 서울 등)으로 옮기면 정상 호출됩니다. 단, Google Apps Script(구글 스프레드시트 자동화)는 구글 인프라 경유로 예외 허용됩니다.

에러 응답 형식

모든 실패에 code(프로그램용 종류)와 message(사람이 읽는 안내)가 옵니다. error는 예전부터 있던 칸이고(은행 거절은 은행 문장, 나머지는 코드 문자열), 제한(429)일 때는 retryAfterSec(재시도까지 남은 초)이 함께 옵니다. 은행이 거절한 경우는 HTTP 200에 success: false입니다 — 위 실패 응답 참고.

{
  "success": false,
  "error": "ACCOUNT_COOLDOWN",
  "code": "ACCOUNT_COOLDOWN",
  "message": "동일 계좌는 5분에 1회만 조회할 수 있습니다. 잠시 후 다시 시도해 주세요.",
  "retryAfterSec": 540
}

계좌조회 API 보안

Bank API는 사용자의 금융 정보 보호를 최우선으로 합니다.

계좌 정보 보호

Bank API는 어떠한 경우에도 계좌 정보를 데이터베이스에 저장하지 않습니다.

  • 계좌번호, 비밀번호, 주민등록번호 등 민감 정보는 API 요청 처리 후 즉시 폐기됩니다
  • 거래내역 데이터는 서버에 저장되지 않으며, 실시간으로 은행에서 조회하여 전달합니다
  • 서버 로그에도 민감 정보는 기록되지 않습니다
  • 계좌번호를 식별용 해시(SHA-256)로도 저장하지 않습니다 — 조회 제한은 서버 메모리에서만 임시 처리됩니다

API Key 보안

  • API Key와 Secret Key는 SHA-256으로 해시하여 저장합니다
  • 평문 키는 최초 발급 시 한 번만 표시되며, 이후 복구가 불가능합니다
  • 키가 유출된 경우 즉시 새로운 키를 발급받으세요

통신 보안

  • 모든 API 통신은 TLS 1.2 이상의 HTTPS로 암호화됩니다
  • HTTP 요청은 자동으로 HTTPS로 리다이렉트됩니다

API 테스트

API를 직접 테스트해보고 싶으신가요? 회원가입 없이 바로 실제 API를 호출해볼 수 있습니다.

API 테스트 페이지로 이동 →