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

API 개요

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

페이싱크 API로 주문을 만들고 바꾸고, 입금 내역과 현금영수증을 다룰 수 있어요. 요청과 응답 본문은 JSON이에요. 주문과 입금에 일이 생길 때 바로 알고 싶다면 웹훅을 함께 쓰세요.

기본 정보

항목 값
기본 주소 https://api.paysync.kr
버전 v2 (모든 경로가 /v2로 시작해요)
인증 Authorization: Bearer <API 키>
본문 형식 application/json, UTF-8
시각 형식 Unix 초(정수). 예: 1777346055
날짜 필터 형식 YYYY-MM-DD, 한국 시간(KST) 기준
금액 원 단위 정수, 부가세 포함
OpenAPI 명세 /openapi.json

인증

대시보드 API 키에서 만든 키를 Authorization 헤더에 넣어요. API 키는 sk_live_로 시작해요.

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

API 키는 워크스페이스 하나에 속해요. 키로 보낸 요청은 그 워크스페이스의 주문, 입금, 현금영수증만 다뤄요. 대시보드처럼 X-Workspace-Id 헤더를 보낼 필요는 없어요.

상황 응답
Authorization 헤더가 없어요. 401, 80003
Bearer가 아닌 인증 방식이에요. 401, 80001
키가 틀렸거나, 만료됐거나, 삭제됐거나, 꺼져 있어요. 401, 290006
읽기 전용 키로 쓰기 요청을 보냈어요. 403, 290007
API 키로 쓸 수 없는 대시보드 전용 요청이에요. 403, 80002 또는 80008

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

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

res = requests.post(
    "https://api.paysync.kr/v2/invoices",
    headers={"Authorization": f"Bearer {os.environ['PAYSYNC_API_KEY']}"},
    json={
        "customer": {
            "name": "홍길동",
            "email": "hong@example.com",
            "phoneNumber": "01012345678",
        },
        "amount": 50000,
        "expireAfterDays": 1,
        "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/v2/invoices") {
    bearerAuth(System.getenv("PAYSYNC_API_KEY"))
    contentType(ContentType.Application.Json)
    setBody(buildJsonObject {
        putJsonObject("customer") {
            put("name", "홍길동")
            put("email", "hong@example.com")
            put("phoneNumber", "01012345678")
        }
        put("amount", 50000)
        put("expireAfterDays", 1)
        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 CreateInvoice {

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

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.paysync.kr/v2/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!({
        "customer": {
            "name": "홍길동",
            "email": "hong@example.com",
            "phoneNumber": "01012345678"
        },
        "amount": 50000,
        "expireAfterDays": 1,
        "metadata": { "orderId": "ORDER-2026-0001" }
    });

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

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

API 키 권한

API 키를 만들 때 권한을 골라요.

권한 할 수 있는 일
읽기·쓰기 주문, 입금, 현금영수증 조회와 주문 생성, 수정, 결제 완료 처리, 취소, 현금영수증 발급, 재발급, 취소, 전송
읽기 전용 조회만 해요. 쓰기 요청에는 403, 290007이 와요.

계좌, 웹훅, 멤버, 구독 같은 워크스페이스 설정은 API 키로 바꿀 수 없어요. 대시보드에서 바꿔요.

API 키 계좌 범위

API 키를 만들 때 계좌 범위를 고른 계좌만으로 정하면 그 키로 다룰 수 있는 주문과 입금이 좁혀져요. 모든 계좌로 만든 키에는 제한이 없어요.

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

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

응답 형식

모든 응답은 code를 담아요. code는 처리 결과를 나타내는 숫자 문자열이고, HTTP 상태 코드와 함께 와요. 성공하면 "10001"이에요.

응답 종류 형식
단건 { "code", "data" }
목록 { "code", "items", "totalItems" }
데이터 없음 { "code" }
{
  "code": "10001",
  "data": {
    "id": "ivc_a1b2c3d4e5f6g7h8i9j0k1l2",
    "number": 1043,
    "status": "PENDING",
    "customer": {
      "name": "홍길동",
      "email": "hong@example.com",
      "phoneNumber": "01012345678"
    },
    "amount": 50000,
    "...": "..."
  }
}
{
  "code": "220003"
}

일부 오류는 처리에 필요한 정보를 data에 담아요. 예를 들어 같은 주문이 이미 있으면 기존 주문 ID를 함께 알려 줘요.

{
  "code": "220010",
  "data": { "invoiceId": "ivc_n0o1p2q3r4s5t6u7v8w9x0y1", "number": 1042 }
}

코드 목록은 에러 코드에 있어요. 응답 객체에는 새 필드가 추가될 수 있으니, 모르는 필드는 무시하도록 만들어 주세요.

페이지네이션

목록 조회는 offset과 limit 쿼리 파라미터로 페이지를 나눠요.

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

주문과 입금 목록에서는 두 값이 필수예요. 현금영수증 목록에서 빼면 offset=0, limit=100으로 조회해요. 목록 응답의 totalItems는 조건에 맞는 전체 항목 수예요.

{
  "code": "10001",
  "items": [
    { "id": "trx_a1b2c3d4e5f6g7h8i9j0k1l2", "depositorName": "홍길동", "amount": 50000, "...": "..." }
  ],
  "totalItems": 142
}

필터

  • 날짜 필터 dateFrom, dateTo는 YYYY-MM-DD 형식의 한국 시간 날짜예요. 두 날짜 모두 결과에 포함돼요. dateFrom=2026-04-01&dateTo=2026-04-30은 4월 1일 0시부터 4월 30일 24시(KST)까지예요.
  • status처럼 여러 값을 받는 필터는 쉼표로 이어 보내거나(status=PENDING,EXPIRED) 파라미터를 반복해서 보내요(status=PENDING&status=EXPIRED).

시각 형식

API 응답의 시각은 Unix 초 단위 정수예요. 요청 본문의 expiresAt도 Unix 초로 보내요. 웹훅 페이로드의 시각만 ISO 8601 문자열이에요.

ID 형식

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

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

주문에는 ID와 별개로 워크스페이스마다 1001부터 매기는 주문번호(number)가 있어요. 대시보드와 구매자 메일에는 #1043처럼 주문번호가 보여요.

요청 기록

API 키로 보낸 요청은 대시보드 API 키의 요청 기록에 30일 동안 남아요. 메서드, 경로, HTTP 상태, 오류 코드, 처리 시간, IP 주소를 볼 수 있어요. 요청 본문과 응답 본문은 남기지 않아요.

엔드포인트

메서드 경로 설명
POST /v2/invoices 주문 생성
GET /v2/invoices 주문 목록 조회
GET /v2/invoices/{id} 주문 단건 조회
PATCH /v2/invoices/{id} 주문 수정
POST /v2/invoices/{id}/mark-paid 주문 결제 완료 처리
POST /v2/invoices/{id}/cancel 주문 취소
GET /v2/transactions 입금 내역 목록 조회
GET /v2/transactions/{id} 입금 단건 조회
POST /v2/cash-receipts 현금영수증 발급
GET /v2/cash-receipts 현금영수증 목록 조회
GET /v2/cash-receipts/{id} 현금영수증 단건 조회
POST /v2/cash-receipts/{id}/cancel 현금영수증 취소
POST /v2/cash-receipts/{id}/reissue 현금영수증 재발급
GET /v2/cash-receipts/{id}/urls 현금영수증 문서 주소 조회
POST /v2/cash-receipts/{id}/send-email 현금영수증 이메일 전송

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