주문 생성
POST /v1/invoices 로 결제받을 주문을 만들어요.
POST /v1/invoices
결제받을 주문을 만들어요. 등록한 계좌에 입금자명과 금액이 모두 같은 입금이 들어오면 페이싱크가 주문을 결제 완료로 바꾸고 invoice.paid 웹훅을 보내요. 주문을 만들면 invoice.created 웹훅도 가요.
요청 본문
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
bankAccountIds |
string[] | 예 | 입금받을 계좌 ID 목록이에요. 빈 배열이면 등록한 모든 계좌로 받아요. 1원 인증을 마친 내 계좌만 넣을 수 있어요. 다중 계좌 라우팅 참고 |
customer.name |
string | 예 | 입금자명이에요. 1~16자, 공백 없이 입력해요. 은행이 긴 입금자명을 자르는 경우는 이름 앞자리 매칭을 참고하세요. |
customer.email |
string | 구매자 이메일이에요. 5~255자예요. 결제 완료 이메일을 켜면 이 주소로 메일을 보내요. | |
customer.phoneNumber |
string | 구매자 전화번호예요. 하이픈 없이 숫자 10~11자리로 입력해요. 예: 01012345678 |
|
amount |
integer | 예 | 금액(원)이에요. 0보다 커야 해요. 입금 금액과 같아야 매칭돼요. |
cashReceipt.type |
string | 현금영수증 종류예요. PERSONAL(소득공제용) 또는 CORPORATE(지출증빙용) |
|
cashReceipt.identifier |
string | PERSONAL이면 휴대폰 번호, CORPORATE이면 사업자등록번호 10자리예요. |
|
expireAfter |
string | 만료까지 남은 기간이에요. 최대 365일이고, 빼면 만료되지 않아요. | |
metadata |
object | 주문에 함께 저장할 문자열 키와 값이에요. 최대 5쌍, 키 64자, 값 1024자까지 넣을 수 있어요. |
expireAfter 형식
ISO 8601 기간 형식과 짧은 형식을 모두 받아요.
| 형식 | 예 |
|---|---|
| ISO 8601 | PT30M, PT1H, P1D, P1DT6H20M |
| 짧은 형식 | 30m, 1h, 1d, 1d 6h 20m, 7d |
현금영수증 자동 발급
cashReceipt를 넣으면 주문이 결제 완료될 때 페이싱크가 현금영수증을 발급해요. 대시보드 현금영수증 메뉴에 사업자 정보가 등록돼 있어야 해요. 주문을 만들 때는 identifier 형식을 검사하지 않고 발급할 때 검사하니, 형식이 틀리면 현금영수증이 발급되지 않아요. 발급 결과는 현금영수증 목록 조회나 대시보드에서 확인하세요.
metadata 활용
쇼핑몰 주문 ID 같은 내 시스템의 값을 넣어 두면 웹훅을 받았을 때 바로 주문을 찾을 수 있어요. CAFE24_나 IMWEB_로 시작하는 키는 쇼핑몰 연동에서 쓰니 피하세요.
요청 예시
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,
"cashReceipt": { "type": "PERSONAL", "identifier": "01012345678" },
"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,
cashReceipt: { type: "PERSONAL", identifier: "01012345678" },
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,
"cashReceipt": {"type": "PERSONAL", "identifier": "01012345678"},
"expireAfter": "1d",
"metadata": {"orderId": "ORDER-2026-0001"},
},
)
print(res.json())응답
201 CREATED와 함께 만든 주문 객체가 와요.
{
"code": "CREATED",
"data": {
"id": "ivc_a1b2c3d4e5f6g7h8i9j0k1l2",
"issuerId": "acc_x9y8z7w6v5u4t3s2r1q0p9o8",
"bankAccountIds": [],
"customer": {
"name": "홍길동",
"email": "hong@example.com",
"phoneNumber": "01012345678"
},
"cashReceipt": {
"type": "PERSONAL",
"identifier": "01012345678"
},
"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
}
}
오류
| HTTP | code |
발생 조건 |
|---|---|---|
| 401 | NOT_AUTHORIZED |
API 키가 없거나 올바르지 않아요. |
| 403 | INSUFFICIENT_PERMISSIONS |
bankAccountIds에 다른 계정의 계좌가 있거나, API 키의 접근 가능한 계좌 밖의 계좌가 있어요. 계좌를 제한한 키로 빈 배열을 보내도 이 코드가 와요. |
| 403 | BANK_ACCOUNT_NOT_VERIFIED |
bankAccountIds에 1원 인증을 마치지 않은 계좌가 있어요. |
| 404 | BANK_ACCOUNT_NOT_FOUND |
bankAccountIds에 없는 계좌 ID가 있어요. |
| 409 | INVOICE_ALREADY_EXISTS |
입금자명과 금액이 같고 받을 계좌가 겹치는 결제 대기 주문이 이미 있어요. 주문 충돌 규칙 참고 |
| 422 | INVALID_CUSTOMER_NAME |
customer.name이 1~16자가 아니거나 공백이 있어요. |
| 422 | INVALID_EMAIL |
customer.email 형식이나 길이가 맞지 않아요. |
| 422 | INVALID_PHONE_NUMBER |
customer.phoneNumber가 숫자 10~11자리가 아니에요. |
| 422 | INVALID_AMOUNT |
amount가 0 이하예요. |
| 422 | INVALID_DURATION |
expireAfter를 기간으로 읽을 수 없어요. |
| 422 | EXPIRE_AFTER_EXCEEDS_MAXIMUM |
expireAfter가 365일을 넘어요. |
| 422 | METADATA_KEY_VALUE_PAIR_LIMIT_EXCEEDED |
metadata가 5쌍을 넘어요. |
| 422 | METADATA_KEY_LENGTH_LIMIT_EXCEEDED |
metadata 키가 64자를 넘어요. |
| 422 | METADATA_VALUE_LENGTH_LIMIT_EXCEEDED |
metadata 값이 1024자를 넘어요. |