---
title: API 개요
description: 페이싱크 REST API의 기본 주소, 인증 방식, 응답 형식, 페이지네이션, ID 형식을 정리했어요.
sidebar:
  label: 개요
  order: 1
  icon: info
---

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

## 기본 정보

| 항목 | 값 |
| --- | --- |
| 기본 주소 | `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`](https://docs.paysync.kr/openapi.json) |

## 인증

대시보드 [API 관리](https://paysync.kr/dashboard/api-keys)에서 발급한 키를 `Authorization` 헤더에 넣어요. API 키는 `sk_live_`로 시작해요.

```http
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
```

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

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

```bash cURL
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" }
  }'
```

```js Node.js
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();
```

```python Python
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())
```

```kotlin Kotlin
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())
```

```java Java
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());
    }
}
```

```rust Rust
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(())
}
```

:::warning
API 키 값은 발급할 때 한 번만 보여요. 키를 잃어버렸다면 새로 발급하고 이전 키를 삭제하세요. 키를 브라우저 코드나 공개 저장소에 넣지 마세요.
:::

## API 키 계좌 제한

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

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

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

## 응답 형식

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

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `code` | string | 처리 결과 코드예요. 예: `OK`, `CREATED`, `INVALID_AMOUNT` |
| `data` | object \| array \| null | 응답 데이터예요. 오류 응답에서는 `null`이에요. |

```json 주문 생성 성공
{
  "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
  }
}
```

```json 오류
{
  "code": "INVALID_AMOUNT",
  "data": null
}
```

코드 목록은 [에러 코드](/api-reference/error-codes)에 있어요.

## 페이지네이션

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

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

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

```json 입금 내역 목록
{
  "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` | [주문 생성](/api-reference/invoices/issue) |
| `GET` | `/v1/invoices` | [주문 목록 조회](/api-reference/invoices/list) |
| `GET` | `/v1/invoices/{id}` | [주문 단건 조회](/api-reference/invoices/get) |
| `POST` | `/v1/invoices/{id}/mark-as-paid` | [주문 결제 완료 처리](/api-reference/invoices/mark-as-paid) |
| `DELETE` | `/v1/invoices/{id}` | [주문 삭제](/api-reference/invoices/delete) |
| `GET` | `/v1/transactions` | [입금 내역 목록 조회](/api-reference/transactions/list) |
| `GET` | `/v1/transactions/{id}` | [입금 단건 조회](/api-reference/transactions/get) |
| `POST` | `/v1/cash-receipts` | [현금영수증 발급](/api-reference/cash-receipts/issue) |
| `GET` | `/v1/cash-receipts` | [현금영수증 목록 조회](/api-reference/cash-receipts/list) |
| `GET` | `/v1/cash-receipts/{id}` | [현금영수증 단건 조회](/api-reference/cash-receipts/get) |
| `POST` | `/v1/cash-receipts/{id}/revoke` | [현금영수증 발급 취소](/api-reference/cash-receipts/revoke) |
