<!-- Source: https://docs.infraio.xyz/ko/api-reference -->
<!-- Last updated: 2026-10-04 -->

# API 레퍼런스

아래의 모든 엔드포인트는 JSON으로 통신하며, `https://api.infraio.xyz`(프로덕션)
또는 `https://api-dev.infraio.xyz`(테스트) 아래에 존재하고, HMAC-SHA256으로
인증합니다 — 요청 서명은 [인증](https://docs.infraio.xyz/ko/api-reference/authentication)을, 오류 envelope
형식은 [오류](https://docs.infraio.xyz/ko/api-reference/errors)를 참조하세요.

이 페이지는 가맹점 연동용 엔드포인트를 나열합니다. 자체 페이지가 없는
엔드포인트는 관련 개념 페이지에 설명되어 있습니다.

> **Note:**
>
> **`/b2b/v1/*`** 아래의 엔드포인트는 **시크릿** 키(`sk_…`)로 HMAC 서명합니다.
> 가맹점 백엔드가 호출하는 표면입니다. 가맹점 대시보드와 호스팅 결제 페이지는
> 자체 엔드포인트를 사용하며, 이는 연동 API에 포함되지 않습니다.

## 체크아웃

| 메서드 | 경로 | 용도 | 비고 |
| --- | --- | --- | --- |
| `POST` | `/b2b/v1/checkout-sessions/quick` | 한 번의 호출로 세션 생성 — 주문 + 체크아웃 세션을 함께 발급. | 요청 본문과 샘플은 [빠른 시작](https://docs.infraio.xyz/ko/get-started/quickstart#2-create-a-checkout-session-server)을 참조하세요. |
| `POST` | `/b2b/v1/checkout-sessions` | *기존* 주문에 대해 세션 생성. 플랫폼에 자체 주문 모델이 있고 시도당 하나의 세션을 원할 때 사용. | 2단계 흐름. |
| `GET` | `/b2b/v1/checkout-sessions/by-order/{order_id}` | 한 주문에 대해 발급된 모든 세션 목록. | 구매자가 세션을 포기했고 대시보드에 이전 시도를 표시하고 싶을 때 유용합니다. |

## 주문

주문은 시간을 초월하는 청구 가능한 엔티티입니다. 하나의 주문이 여러 체크아웃
세션을 지원할 수 있습니다(예: 구매자 포기, 재시도).

| 메서드 | 경로 | 용도 | 비고 |
| --- | --- | --- | --- |
| `POST` | `/b2b/v1/orders` | 세션 없이 주문 생성. | 즉시 리디렉션하는 대신 나중에 구매자에게 결제 링크를 보내려는 경우 사용합니다. |
| `GET` | `/b2b/v1/orders/{id}` | 라인 아이템 + 상태가 포함된 단일 주문 읽기. | 상태: `PENDING` → `PAID` \| `PARTIAL_PAID` \| `CANCELED`. 환불 후: `PARTIALLY_REFUNDED` \| `REFUNDED`. |
| `GET` | `/b2b/v1/orders/by-merchant/{merchant_id}` | 가맹점의 주문 목록. 커서 페이지네이션. | 커서 프로토콜은 [커서 페이지네이션](#cursor-pagination)을 참조하세요. |
| `PATCH` | `/b2b/v1/orders/{id}/cancel` | 미결제 주문을 취소로 표시. `order.canceled`를 발생시킵니다. | 주문이 이미 결제된 경우 실패합니다. |
| `PATCH` | `/b2b/v1/orders/{id}/reopen` | 자동 취소(`canceled_reason=payment_timeout`)를 되돌립니다. | TTL 만료 후 구매자가 돌아오는 경우 유용합니다. |

## 환불

saga 흐름과 토큰 라이프사이클은 [환불 개념 페이지](https://docs.infraio.xyz/ko/concepts/refunds)를
참조하세요.

### 가맹점 시작

| 메서드 | 경로 | 용도 | 비고 |
| --- | --- | --- | --- |
| `POST` | `/b2b/v1/merchants/{merchant_id}/refunds` | 가맹점 시작 환불. 자동 승인(`PENDING` 건너뜀). | `payment.refund.approved`를 즉시 발생시킵니다. |

### 고객 시작 — 환불 요청 토큰

구매자는 저희 호스팅 페이지에서 환불 양식을 작성합니다. 가맹점은 토큰을
발급하고 URL을 전달하기만 하면 됩니다. 백엔드(아래)에서 또는 가맹점 대시보드에서
토큰을 발급할 수 있습니다. 갱신과 취소는 대시보드에서 처리합니다.

| 메서드 | 경로 | 인증 | 용도 |
| --- | --- | --- | --- |
| `POST` | `/b2b/v1/merchants/{merchant_id}/refund-requests` | HMAC (`sk_…`) | 백엔드에서 토큰 발급. 본문: `{ref_type, ref_value, amount, ttl_seconds?, metadata?, hide_summary?, hide_header?}`. `ref_type`은 `order_id` / `order_number` / `session_id` / `session_key` 중 하나. `ref_value`는 매칭되는 식별자. `amount`는 **필수**이며 구매자가 제출할 수 있는 최대값을 잠급니다. 기본 TTL **30분**. `refund_request.created`(`source: b2b`)를 발생시킵니다. |

### 환불 라이프사이클 (생성 후)

두 흐름 모두에 적용됩니다. 아래 엔드포인트는 요청 토큰이 아닌 환불 자체
(id가 `rfn_…`로 시작)에 작동합니다.

| 메서드 | 경로 | 용도 | 비고 |
| --- | --- | --- | --- |
| `GET` | `/b2b/v1/refunds/{id}` | 단일 환불 읽기. | 상태: `PENDING` → `APPROVED` → `EXECUTED` \| `REJECTED`. |
| `GET` | `/b2b/v1/refunds/by-merchant/{merchant_id}` | 환불 목록. 커서 페이지네이션. | — |
| `POST` | `/b2b/v1/refunds/{id}/approve` | `PENDING` 환불 승인(고객 시작만 — 가맹점 시작은 이미 `APPROVED` 상태). | 암호화폐: `APPROVED`로 도착하면 다음 `/submit-tx`를 호출합니다. |
| `POST` | `/b2b/v1/refunds/{id}/reject` | `PENDING` 환불 거부. | `payment.refund.rejected`를 발생시킵니다. |
| `POST` | `/b2b/v1/refunds/{id}/submit-tx` | 암호화폐 전용 — 브로드캐스트한 온체인 tx 해시를 스탬프. | 본문: `{tx_hash, network, token_address}` — 세 개 모두 필수. |

## 카탈로그 (읽기 전용)

| 메서드 | 경로 | 용도 |
| --- | --- | --- |
| `GET` | `/v1/supported/networks` | InfraIO Pay가 정산할 수 있는 모든 체인(메인넷 + 테스트넷, env로 필터링됨). |
| `GET` | `/v1/supported/tokens` | 해당 체인의 모든 스테이블코인. |
| `GET` | `/v1/supported/currencies` | `order.currency`에 허용되는 통화. |

## 헬스

| 메서드 | 경로 | 인증 | 용도 |
| --- | --- | --- | --- |
| `GET` | `/health` | 없음 (공개) | 라이브니스 확인. `{"status":"ok"}`를 반환합니다. 업타임 모니터를 여기에 지정하세요. |

## 커서 페이지네이션

모든 목록 엔드포인트는 동일한 쿼리 매개변수를 받고 동일한 envelope를
반환합니다. 커서는 불투명하며 오프셋 대신 사용되므로, 페이지를 넘기는 동안 새
행이 도착해도 페이지가 이동하지 않습니다.

| 쿼리 매개변수 | 타입 | 기본값 | 비고 |
| --- | --- | --- | --- |
| `cursor` | `string` | — | 불투명 — 이전 응답의 `next_cursor`를 그대로 복사합니다. |
| `limit` | `int` | `20` | `1..100`. |
| `sort_dir` | `'asc' \| 'desc'` | `desc` | `(created_at, id)` 기준 정렬. |
| `from` / `to` | `RFC3339` | — | 선택적 시간 윈도우 필터. |
| `search` | `string` | — | 지원되는 경우 자유 텍스트 필터. |

응답 envelope:

```json
{
  "orders": [ /* page rows */ ],
  "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0...",
  "has_next": true
}
```

`has_next`는 항상 존재합니다. `next_cursor`는 `has_next`가 `false`일 때
생략됩니다. 커서는 불투명한 문자열로 다루세요.

## 이 페이지에서 누락된 항목

이 페이지는 가맹점 연동용 엔드포인트를 다룹니다. 나열되지 않은 엔드포인트나
OpenAPI 스펙이 필요하면 지원팀에 문의하세요.
