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 |
현금영수증 발급 취소 |