FinLog 로고 FinLog
Webhook & REST API Reference v0.0.7

FinLog 커스텀 동기화 API 가이드

FinLog은 중앙 서버가 없는 100% 온디바이스 가계부입니다. 내가 소유한 구글 시트, NAS, 홈서버로 금융 알림 내역을 실시간 수신하여 자유롭게 분석하고 영구 보관하세요.

Step 0
JSON 데이터 규격
포맷 및 필드 스키마
Track 1
구글 스프레드시트
서버 없이 엑셀 자동 누적
Track 2
개인 백엔드 서버
Express / FastAPI / Flask
Quick Test
cURL 검증 명령
1초 즉시 테스트
0

FinLog 송신 데이터 규격 (JSON Payload)

앱에서 지정한 웹훅/서버 URL로 발송되는 HTTP POST 요청 사양입니다.

Method: POST
Content-Type: application/json
Auth Header: Bearer <Token>
전송 JSON 바디 (Payload Example) v0.0.7 schema
{
  "app": "FinLog",
  "version": "0.0.7",
  "syncedAt": "2026-09-14T15:00:00.000Z",
  "sheetName": "FinLog_Sheet",
  "transactions": [
    {
      "id": "tx_1726300000_abc",
      "sourceType": "NOTIFICATION",   // "NOTIFICATION" | "SMS" | "MANUAL"
      "sourceApp": "com.kakaobank.channel",
      "bankName": "카카오뱅크",
      "amount": 15000,
      "type": "EXPENSE",              // "EXPENSE"(지출) | "INCOME"(수입) | "TRANSFER"(이체)
      "merchant": "스타벅스 강남점",
      "category": "카페/간식",
      "memo": "아메리카노 결제",
      "balance": 245000,             // 통장 잔액 (알림에 잔액이 포함된 경우)
      "rawText": "[카카오뱅크] 체크카드 승인 15,000원 스타벅스 강남점",
      "timestamp": "2026-09-14T15:00:00.000Z"
    }
  ],
  "detectionLogs": [
    {
      "id": "audit_1726300010_xyz",
      "transactionId": "tx_1726300000_abc",
      "timestamp": "2026-09-14T15:05:00.000Z",
      "fieldName": "category",
      "oldValue": "기타",
      "newValue": "카페/간식",
      "reason": "사용자 카테고리 수동 수정"
    }
  ]
}

📋 필드 세부 명세서

필드명 타입 필수 설명
app string 필수 앱 식별자 (고정값 "FinLog")
version string 필수 데이터를 보낸 FinLog 앱 버전 (예: "0.0.7")
syncedAt string (ISO 8601) 필수 동기화 전송 시각 UTC (예: "2026-09-14T15:00:00.000Z")
sheetName string 선택 구글 시트 연동 시 타겟 시트명 (기본: "FinLog_Sheet")
transactions Array<object> 필수 발생한 금융 거래 데이터 목록 배열
detectionLogs Array<object> 선택 사용자가 가계부 내역을 수정하거나 변경한 내역 감사(Audit) 로그

transactions 배열 내부 객체 필드

필드명 타입 값 범위 / 예시 설명
id string tx_1726300000_abc 거래 고유 식별자
sourceType string NOTIFICATION | SMS | MANUAL 수집 경로 (푸시 알림 / 문자 / 직접 입력)
bankName string 카카오뱅크, 국민카드, 토스 등 금융기관 및 카드사 이름
amount number 15000 거래 금액 (원화 기준 양수)
type string EXPENSE | INCOME | TRANSFER 거래 구분 (지출 / 수입 / 이체)
merchant string 스타벅스 강남점 가맹점 상호명 또는 결제처
category string 식비, 카페/간식, 교통, 쇼핑 등 자동 분류된 소비 카테고리
balance number? 245000 (없으면 null) 거래 후 통장 잔액 (알림에 잔액 표기 시)
rawText string [카카오뱅크] 체크카드 승인... 기기에서 파싱한 원본 메시지 텍스트
timestamp string (ISO) 2026-09-14T15:00:00.000Z 결제 및 거래가 일어난 시각
1
트랙 1 · 가장 간편한 방법

구글 스프레드시트 (Apps Script Webhook)

별도의 백엔드 서버나 데이터베이스 구축 없이 구글 드라이브 엑셀 시트에 금융 내역을 실시간 행(Row)으로 자동 누적할 때 사용합니다.

💡 장점

100% 무료, 24시간 서버 유지보수 불필요, PC 구글 시트에서 엑셀 수식(SUM, 피벗테이블, 차트) 즉시 연동

🔗 연결 방식

구글 스프레드시트 > 확장 프로그램 > Apps Script > 웹 앱(Web App) 배포 URL을 FinLog에 입력

구글 Apps Script 배포 코드 (Code.gs)
// [구글 Apps Script 코드]
function doPost(e) {
  try {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getActiveSheet();
    
    // 1. 첫 행이 비어있으면 엑셀 헤더 자동 생성
    if (sheet.getLastRow() === 0) {
      sheet.appendRow(['기록일시', '금융기관', '구분', '금액', '가맹점/상호', '카테고리', '잔액', '메모', '원본메시지']);
      sheet.getRange(1, 1, 1, 9)
        .setBackground('#1e293b')
        .setFontColor('#ffffff')
        .setFontWeight('bold');
      sheet.setFrozenRows(1);
    }
    
    // 2. FinLog 앱에서 보낸 데이터 파싱
    var postData = JSON.parse(e.postData.contents);
    var transactions = postData.transactions || [];
    
    // 단일 전송 및 다건 전송 모두 수용
    if (postData.transaction) transactions = [postData.transaction];
    
    // 3. 시트에 한 줄씩 추가
    transactions.forEach(function(tx) {
      var typeText = tx.type === 'EXPENSE' ? '지출' : (tx.type === 'INCOME' ? '수입' : '이체');
      sheet.appendRow([
        tx.timestamp || new Date().toLocaleString(),
        tx.bankName || '기타금융',
        typeText,
        tx.amount || 0,
        tx.merchant || '',
        tx.category || '기타',
        tx.balance || '',
        tx.memo || '',
        tx.rawText || ''
      ]);
    });
    
    return ContentService.createTextOutput(JSON.stringify({ status: "success", count: transactions.length }))
      .setMimeType(ContentService.MimeType.JSON);
  } catch (err) {
    return ContentService.createTextOutput(JSON.stringify({ status: "error", message: err.toString() }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

// 연결 테스트용 (Ping)
function doGet(e) {
  return ContentService.createTextOutput(JSON.stringify({ status: "ok", service: "FinLog Google Sheets Webhook" }))
    .setMimeType(ContentService.MimeType.JSON);
}

🛠️ 배포 및 연동 3단계 가이드

  1. 새 구글 스프레드시트 생성 후 상단 메뉴에서 확장 프로그램 > Apps Script 클릭
  2. 기존 코드를 지우고 위 코드를 붙여넣은 뒤 저장 (Ctrl + S)
  3. 우측 상단 배포 > 새 배포 선택:
    • 유형: 웹 앱(Web App)
    • 다음 사용자로 실행: 나(내 계정)
    • 액세스 권한: 모든 사용자(Anyone) *필수
  4. 생성된 https://script.google.com/macros/s/.../exec URL을 FinLog 앱 웹훅 주소에 붙여넣기
2
트랙 2 · 개인 홈서버 / NAS / 클라우드

백엔드 서버 구현 예제

Synology NAS(Docker), 오라클/AWS 클라우드 VPS, 개인 홈서버 등 선호하는 백엔드 환경에 맞추어 선택하여 구축할 수 있습니다.

포트: 8080 · Bearer Token 인증 및 JSONL 파일 누적 저장 server.js
// server.js
const express = require('express');
const cors = require('cors');
const fs = require('fs');
const app = express();
const PORT = 8080;
const AUTH_TOKEN = "my-secret-token"; // 앱의 [인증 토큰] 칸과 일치시킴

app.use(cors());
app.use(express.json());

// 1. Health Check (앱의 "연결 테스트 (Ping)" 버튼이 호출)
app.get('/api/v1/finlog/health', (req, res) => {
  const auth = req.headers['authorization'];
  if (AUTH_TOKEN && auth !== `Bearer ${AUTH_TOKEN}`) {
    return res.status(401).json({ error: '인증 실패' });
  }
  res.json({ status: 'ok', serverTime: new Date().toISOString() });
});

// 2. 로그 수신 엔드포인트 (앱의 "지금 전체 로그 전송" 및 자동 동기화가 호출)
app.post('/api/v1/finlog/logs', (req, res) => {
  const auth = req.headers['authorization'];
  if (AUTH_TOKEN && auth !== `Bearer ${AUTH_TOKEN}`) {
    return res.status(401).json({ error: '인증 실패' });
  }
  const { app: appName, version, transactions, detectionLogs, syncedAt } = req.body;
  console.log(`[${syncedAt}] 거래 ${transactions?.length || 0}건, 수정로그 ${detectionLogs?.length || 0}건 수신`);
  
  // 로컬 파일 (JSONL) 또는 MariaDB/PostgreSQL 등에 저장
  const logLine = JSON.stringify(req.body) + '\n';
  fs.appendFileSync('finlog_records.jsonl', logLine, 'utf8');
  
  res.json({
    success: true,
    receivedTransactions: transactions?.length || 0,
    receivedAuditLogs: detectionLogs?.length || 0
  });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`FinLog Express 서버가 포트 ${PORT}에서 실행 중입니다.`);
});
npm init -y && npm install express cors && node server.js
3
개발자 로컬 테스트용

cURL 테스트 명령

서버를 실행한 뒤, FinLog 앱 없이 터미널(CMD / PowerShell / Bash)에서 서버가 올바르게 응답하는지 1초 만에 검증할 수 있습니다.

1) Health Check (Ping) 테스트 GET
curl -X GET http://localhost:8080/api/v1/finlog/health \
     -H "Authorization: Bearer my-secret-token"
2) 가상 거래 데이터 전송 테스트 POST
curl -X POST http://localhost:8080/api/v1/finlog/logs \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer my-secret-token" \
     -d '{
       "app": "FinLog",
       "version": "0.0.7",
       "syncedAt": "2026-09-14T15:00:00Z",
       "sheetName": "FinLog_Sheet",
       "transactions": [
         {
           "id": "test_01",
           "bankName": "테스트은행",
           "type": "EXPENSE",
           "amount": 10000,
           "merchant": "테스트가맹점",
           "category": "식비",
           "timestamp": "2026-09-14T15:00:00Z",
           "rawText": "테스트 결제 10,000원"
         }
       ]
     }'
💡

요약 및 권장 사항

FinLog 앱 내 [온라인 백업] 설정창에서 입력할 항목 매핑 가이드

권장 연동 방식 선택

  • • 가장 간편한 방법: 별도 서버나 고정 IP가 없다면 트랙 1 (구글 스프레드시트)로 시작하는 것을 추천합니다.
  • • 개인 NAS / 홈서버: Node.js 환경이면 Express, 파이썬 기반 데이터 분석(Pandas, AI 모델)을 원하시면 FastAPI를 추천합니다.

앱 설정 매핑 가이드

  • 통신 프로토콜: http 또는 https
  • 서버 주소: IP 또는 도메인 (예: 192.168.0.50 / mynas.me)
  • 포트: 8080 (또는 설정한 포트)
  • 엔드포인트: /api/v1/finlog/logs
  • 인증 토큰: my-secret-token (서버 설정값과 일치)