본문으로 건너뛰기
페이싱크 개발자센터
Esc
↑↓이동↵열기⌘J미리보기
이 페이지에서

API 개요

페이싱크 REST API의 기본 주소, 인증 방식, 응답 형식, 페이지네이션, ID 형식을 정리했어요.

페이싱크 API로 주문을 만들고, 입금 내역과 현금영수증을 조회할 수 있어요. 요청과 응답 본문은 JSON이에요. 주문 상태가 바뀔 때 알림을 받으려면 웹훅을 함께 쓰세요.

기본 정보

항목 값
기본 주소 https://api.paysync.kr
버전 v1 (모든 경로가 /v1으로 시작해요)
인증 Authorization: Bearer <API 키>
본문 형식 application/json, UTF-8
시각 형식 ISO 8601, UTC. 예: 2026-04-28T03:14:15.926Z
날짜 필터 형식 YYYY-MM-DD, 한국 시간(KST) 기준
OpenAPI 명세 /openapi.json

인증

대시보드 API 관리에서 발급한 키를 Authorization 헤더에 넣어요. API 키는 sk_live_로 시작해요.

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx

만료된 키, 삭제된 키, 대시보드에서 비활성화한 키로 요청하면 401 NOT_AUTHORIZED가 와요.

주문 하나를 만드는 요청이에요.

curl -X POST https://api.paysync.kr/v1/invoices \
  -H "Authorization: Bearer $PAYSYNC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bankAccountIds": [],
    "customer": {
      "name": "홍길동",
      "email": "hong@example.com",
      "phoneNumber": "01012345678"
    },
    "amount": 50000,
    "expireAfter": "1d",
    "metadata": { "orderId": "ORDER-2026-0001" }
  }'
const res = await fetch("https://api.paysync.kr/v1/invoices", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAYSYNC_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    bankAccountIds: [],
    customer: {
      name: "홍길동",
      email: "hong@example.com",
      phoneNumber: "01012345678",
    },
    amount: 50000,
    expireAfter: "1d",
    metadata: { orderId: "ORDER-2026-0001" },
  }),
});
const { code, data } = await res.json();
import os
import requests

res = requests.post(
    "https://api.paysync.kr/v1/invoices",
    headers={"Authorization": f"Bearer {os.environ['PAYSYNC_API_KEY']}"},
    json={
        "bankAccountIds": [],
        "customer": {
            "name": "홍길동",
            "email": "hong@example.com",
            "phoneNumber": "01012345678",
        },
        "amount": 50000,
        "expireAfter": "1d",
        "metadata": {"orderId": "ORDER-2026-0001"},
    },
)
print(res.json())
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.*

val client = HttpClient(CIO) {
    install(ContentNegotiation) { json() }
}

val response = client.post("https://api.paysync.kr/v1/invoices") {
    bearerAuth(System.getenv("PAYSYNC_API_KEY"))
    contentType(ContentType.Application.Json)
    setBody(buildJsonObject {
        putJsonArray("bankAccountIds") {}
        putJsonObject("customer") {
            put("name", "홍길동")
            put("email", "hong@example.com")
            put("phoneNumber", "01012345678")
        }
        put("amount", 50000)
        put("expireAfter", "1d")
        putJsonObject("metadata") { put("orderId", "ORDER-2026-0001") }
    })
}

println(response.bodyAsText())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class IssueInvoice {

    public static void main(String[] args) throws Exception {
        String body = """
            {
              "bankAccountIds": [],
              "customer": {
                "name": "홍길동",
                "email": "hong@example.com",
                "phoneNumber": "01012345678"
              },
              "amount": 50000,
              "expireAfter": "1d",
              "metadata": { "orderId": "ORDER-2026-0001" }
            }
            """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.paysync.kr/v1/invoices"))
            .header("Authorization", "Bearer " + System.getenv("PAYSYNC_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.body());
    }
}
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let api_key = std::env::var("PAYSYNC_API_KEY").expect("PAYSYNC_API_KEY");

    let body = json!({
        "bankAccountIds": [],
        "customer": {
            "name": "홍길동",
            "email": "hong@example.com",
            "phoneNumber": "01012345678"
        },
        "amount": 50000,
        "expireAfter": "1d",
        "metadata": { "orderId": "ORDER-2026-0001" }
    });

    let response = reqwest::Client::new()
        .post("https://api.paysync.kr/v1/invoices")
        .bearer_auth(api_key)
        .json(&body)
        .send()
        .await?
        .text()
        .await?;

    println!("{response}");
    Ok(())
}

API 키 계좌 제한

API 키를 만들 때 접근 가능한 계좌를 고르면 그 키로 다룰 수 있는 주문과 입금이 좁혀져요. 전체 계좌 접근 허용을 켠 키에는 제한이 없어요.

API 계좌를 제한한 키의 동작
주문 생성 bankAccountIds에 허용된 계좌만 넣을 수 있어요. 빈 배열(전체 계좌 수신)로는 만들 수 없어요.
주문 조회, 결제 완료 처리, 삭제 bankAccountIds가 모두 허용된 계좌인 주문만 다뤄요. 전체 계좌 수신 주문은 다룰 수 없어요.
주문 목록 위 조건에 맞는 주문만 나와요.
입금 조회와 목록 허용된 계좌로 들어온 입금만 나와요.
현금영수증 계좌와 관계가 없어서 제한하지 않아요.

허용되지 않은 주문이나 입금에 접근하면 403 INSUFFICIENT_PERMISSIONS가 와요.

응답 형식

모든 응답은 code와 data를 담아요. code는 처리 결과를 나타내는 문자열이고, HTTP 상태 코드와 함께 와요.

필드 타입 설명
code string 처리 결과 코드예요. 예: OK, CREATED, INVALID_AMOUNT
data object | array | null 응답 데이터예요. 오류 응답에서는 null이에요.
{
  "code": "CREATED",
  "data": {
    "id": "ivc_a1b2c3d4e5f6g7h8i9j0k1l2",
    "issuerId": "acc_x9y8z7w6v5u4t3s2r1q0p9o8",
    "bankAccountIds": [],
    "customer": {
      "name": "홍길동",
      "email": "hong@example.com",
      "phoneNumber": "01012345678"
    },
    "cashReceipt": null,
    "amount": 50000,
    "paid": false,
    "metadata": { "orderId": "ORDER-2026-0001" },
    "issuedAt": "2026-04-28T03:14:15.926Z",
    "expiresAt": "2026-04-29T03:14:15.926Z",
    "deletedAt": null
  }
}
{
  "code": "INVALID_AMOUNT",
  "data": null
}

코드 목록은 에러 코드에 있어요.

페이지네이션

목록 조회는 offset과 limit 쿼리 파라미터로 페이지를 나눠요. 두 값 모두 필수예요. 빠뜨리면 HTTP 400 응답이 와요.

파라미터 타입 설명
offset integer 건너뛸 항목 수예요. 0 이상이에요.
limit integer 가져올 항목 수예요. 1~100이에요.

목록 응답에는 조건에 맞는 전체 항목 수 totalItems가 함께 와요. 항목은 최신순으로 정렬돼요.

{
  "code": "OK",
  "totalItems": 142,
  "data": [
    {
      "id": "trx_a1b2c3d4e5f6g7h8i9j0k1l2",
      "matchedInvoiceId": "ivc_n0o1p2q3r4s5t6u7v8w9x0y1",
      "matchMethod": "EXACT",
      "amount": 50000,
      "description": "홍길동"
    }
  ]
}

날짜 필터

dateAfter와 dateBefore는 YYYY-MM-DD 형식의 한국 시간 날짜예요. 두 날짜 모두 결과에 포함돼요. dateAfter=2026-04-01&dateBefore=2026-04-30은 4월 1일 0시부터 4월 30일 24시(KST)까지예요.

ID 형식

모든 ID는 리소스 접두사 뒤에 영문 소문자와 숫자 24자가 붙어요.

접두사 리소스
ivc_ 주문
trx_ 입금
crt_ 현금영수증
bac_ 은행 계좌
acc_ 페이싱크 계정
whd_ 웹훅
whm_ 웹훅 전송

엔드포인트

메서드 경로 설명
POST /v1/invoices 주문 생성
GET /v1/invoices 주문 목록 조회
GET /v1/invoices/{id} 주문 단건 조회
POST /v1/invoices/{id}/mark-as-paid 주문 결제 완료 처리
DELETE /v1/invoices/{id} 주문 삭제
GET /v1/transactions 입금 내역 목록 조회
GET /v1/transactions/{id} 입금 단건 조회
POST /v1/cash-receipts 현금영수증 발급
GET /v1/cash-receipts 현금영수증 목록 조회
GET /v1/cash-receipts/{id} 현금영수증 단건 조회
POST /v1/cash-receipts/{id}/revoke 현금영수증 발급 취소

이 페이지가 도움이 되었나요?