본문으로 건너뛰기

계좌조회 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자리
startDate string 필수 조회 시작일 (YYYYMMDD)
endDate string 필수 조회 종료일 (YYYYMMDD)

은행 코드

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

코드 예제

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",
    "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)이 포함될 수 있습니다.

에러 응답

429 Too Many Requests - 동일 계좌 쿨다운
{
  "success": false,
  "error": "ACCOUNT_COOLDOWN",
  "message": "동일 계좌는 5분에 1회만 조회할 수 있습니다. 잠시 후 다시 시도해 주세요.",
  "retryAfterSec": 540
}
429 Too Many Requests - 조회 한도 초과
{
  "success": false,
  "error": "QUERY_QUOTA_EXCEEDED",
  "message": "조회 한도(30분당 30회)를 초과했습니다.",
  "retryAfterSec": 1200
}
429 Too Many Requests - 요청 한도 초과
{
  "success": false,
  "error": "TOO_MANY_REQUESTS",
  "message": "요청 한도(30분당 60회)를 초과했습니다.",
  "retryAfterSec": 800
}
401 Unauthorized - 인증 실패
{
  "success": false,
  "error": "Invalid API Key"
}
참고: 별도의 계좌 등록 절차 없이 바로 조회할 수 있습니다. 단 같은 계좌는 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 실패 시 에러 코드 (선택)
참고: 신한은 인터넷뱅킹 로그인이 필요하며, 로그인 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 접근 권한 없음
404 Not Found 존재하지 않는 엔드포인트
429 Too Many Requests Rate Limit 초과
500 Internal Server Error 서버 내부 오류

에러 응답 형식

error는 에러 코드 문자열이고, 제한(429)일 때는 retryAfterSec(재시도까지 남은 초)이 함께 옵니다.

{
  "success": false,
  "error": "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 테스트 페이지로 이동 →