xdata-kr Billing Refunds API

The Billing Refunds API from xdata-kr — 2 operation(s) for billing refunds.

Operations 3

POST /v1/refunds Create Refund #
GET /v1/refunds List Refunds #
GET /v1/refunds/{refund_id} Get Refund #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/xdata-kr:xdata-kr-billing-refunds-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

xdata-kr-billing-refunds-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: XBOSS Billing Refunds API
  description: '통합 REST API 서버 (홈택스 등). Human API guide: https://developer.xdata.kr · OpenAPI Reference: /docs'
  version: 2.0.0
security:
- basicClientCredential: []
- mcpOAuth2: []
tags:
- name: Billing Refunds
paths:
  /v1/refunds:
    post:
      tags:
      - Billing Refunds
      summary: Create Refund
      description: 환불 요청.
      operationId: create_refund_v1_refunds_post
      parameters:
      - name: env_scope
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
          enum:
          - production
          - real_test
          - sandbox
          title: Env Scope
        description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
      - name: Idempotency-Key
        in: header
        required: true
        schema:
          type: string
          minLength: 1
          maxLength: 128
          title: Idempotency-Key
      - name: Authorization
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Authorization
      - name: X-Env-Scope
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
          enum:
          - production
          - real_test
          - sandbox
          title: X-Env-Scope
        description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RefundCreateRequest'
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RefundCreateResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    get:
      tags:
      - Billing Refunds
      summary: List Refunds
      description: 환불 목록 조회.
      operationId: list_refunds_v1_refunds_get
      parameters:
      - name: query
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/RefundListQuery'
      - name: env_scope
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
          enum:
          - production
          - real_test
          - sandbox
          title: Env Scope
        description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
      - name: Authorization
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Authorization
      - name: X-Env-Scope
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
          enum:
          - production
          - real_test
          - sandbox
          title: X-Env-Scope
        description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageEnvelope_RefundResponse_'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/refunds/{refund_id}:
    get:
      tags:
      - Billing Refunds
      summary: Get Refund
      description: 환불 단건 조회.
      operationId: get_refund_v1_refunds__refund_id__get
      parameters:
      - name: refund_id
        in: path
        required: true
        schema:
          type: integer
          title: Refund Id
      - name: env_scope
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
          enum:
          - production
          - real_test
          - sandbox
          title: Env Scope
        description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
      - name: Authorization
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Authorization
      - name: X-Env-Scope
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
          enum:
          - production
          - real_test
          - sandbox
          title: X-Env-Scope
        description: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RefundResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
    PageEnvelope_RefundResponse_:
      properties:
        items:
          items:
            $ref: '#/components/schemas/RefundResponse'
          type: array
          title: Items
          description: Page result items. Empty list allowed.
        next_cursor:
          anyOf:
          - type: string
          - type: 'null'
          title: Next Cursor
          description: Opaque cursor for next page, or null on last page.
        has_more:
          type: boolean
          title: Has More
          description: Whether another page exists. False when next_cursor is null.
          default: false
      additionalProperties: false
      type: object
      title: PageEnvelope[RefundResponse]
    RefundListQuery:
      properties:
        organization_id:
          anyOf:
          - type: integer
            minimum: 1.0
          - type: 'null'
          title: Organization Id
          description: 조직 PK. 본인 조직 미지정 가능(라우트 주입).
        payment_id:
          anyOf:
          - type: integer
            minimum: 1.0
          - type: 'null'
          title: Payment Id
          description: 결제 ID 필터 (단일 결제의 환불 이력 조회).
        status:
          anyOf:
          - items:
              type: string
              enum:
              - PENDING
              - SUCCEEDED
              - FAILED
              - CANCELED
            type: array
          - type: 'null'
          title: Status
          description: 상태 필터(다중). 미지정 시 전체.
        limit:
          type: integer
          maximum: 100.0
          minimum: 1.0
          title: Limit
          description: 페이지 크기.
          default: 20
        cursor:
          anyOf:
          - type: string
          - type: 'null'
          title: Cursor
          description: 이전 응답의 next_cursor.
      type: object
      title: RefundListQuery
      description: '환불 목록 조회 쿼리.


        자동 필터(라우트 강제):

        - `organization_id`: 본인 조직(ADMIN은 명시 가능)

        - `env_scope = X-Env-Scope`


        명세에 GET 목록 표가 없어 이 DTO 가 그 자리를 대신하며

        함께 잠금한다(`InvoiceListQuery`/`PaymentListQuery` 패턴 동형).'
    RefundCreateRequest:
      properties:
        payment_id:
          type: integer
          minimum: 1.0
          title: Payment Id
          description: 환불 대상 결제 ID (payments.id). status='SUCCEEDED'만 허용하고 무통장 입금 결제는 받지 않는다(422).
        amount_minor:
          type: integer
          exclusiveMinimum: 0.0
          title: Amount Minor
          description: 환불 금액 (minor unit 정수). 0 과 음수는 받지 않는다. 전액/부분 모두 허용. 환불 합산 ≤ 원 결제 amount_minor는 서비스 계층 검증.
        reason:
          anyOf:
          - type: string
            enum:
            - USER_REQUEST
            - OPS_DISPUTE_RESOLUTION
            - DUPLICATE_PAYMENT
            - PAYMENT_FAILED_REVERSAL
            - FRAUDULENT_PAYMENT
            - OTHER
          - type: 'null'
          title: Reason
          description: 환불 사유 enum. 미지정이면 기본값 없이 저장하고 응답 reason 은 null (note 만 있으면 그 글만 저장).
        note:
          anyOf:
          - type: string
            maxLength: 200
          - type: 'null'
          title: Note
          description: 운영 메모(자유 텍스트). SCHEMA `refunds.reason VARCHAR(255)` 컬럼에 `reason` enum과 함께 합성 저장(서비스 계층 책임). PII/secret 금지.
        cancel_subscription:
          type: boolean
          title: Cancel Subscription
          description: 동일 트랜잭션에서 구독 CANCELED 전이 여부. True 시 `subscriptions.status='CANCELED'`로 전이 + `audit_logs.billing.subscription.transition` 적재.
          default: false
        metadata:
          anyOf:
          - additionalProperties:
              type: string
            type: object
          - type: 'null'
          title: Metadata
          description: '운영 메타데이터 (예: source, dispute_id, support_ticket_id). PII/secret 적재 금지. 키 화이트리스트는 별도 결정.'
      additionalProperties: false
      type: object
      required:
      - payment_id
      - amount_minor
      title: RefundCreateRequest
      description: "환불 생성 요청.\n\n처리 흐름:\n1) AuthPolicyService 평가(`request_kind='billing'`, BILLING_ADMIN·SYS_ADMIN 또는 본인 조직 OWNER)\n2) `payment_id` 소유권·`status='SUCCEEDED'`·env_scope 검증 - 무통장 입금 결제는 이 요청으로 환불하지 않는다\n   (`422 BILLING_INVALID_INPUT`, 아무것도 쓰기 전에 거절)\n3) 환불 합산 ≤ 원 결제 amount_minor 검증 (서비스 계층 책임)\n   - 위반 시 `422 BILLING_REFUND_EXCEEDS_PAYMENT`\n4) `refunds` 행 PENDING 생성\n5) 환불 요청 (어댑터 호출)\n6) `cancel_subscription=true`인 경우 동일 트랜잭션에서 구독 `CANCELED` 전이\n7) 동기 응답: 202 Accepted + 환불 객체 스냅샷(PENDING)\n\nPG 환불 결과는 웹훅으로 수신 → `refunds.SUCCEEDED` + `invoices.REFUNDED/PARTIALLY_REFUNDED`.\n\n`organization_id`는 본 DTO에 두지 않는다 — `payment_id`로 조직이 자동 추론되며,\n라우트가 `PrincipalContext.organization_id`와의 일치를 검증하여 403 차단(IDOR 방지).\n\n`metadata`는 입력만 허용(응답 미노출). PII/secret/credential 적재 금지.\n키 화이트리스트는 후속 ADR."
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    RefundCreateResponse:
      properties:
        refund_id:
          type: integer
          minimum: 1.0
          title: Refund Id
          description: refunds.id (BIGSERIAL PK).
        payment_id:
          type: integer
          minimum: 1.0
          title: Payment Id
          description: 원 결제 ID (payments.id).
        amount_minor:
          type: integer
          exclusiveMinimum: 0.0
          title: Amount Minor
          description: 환불 금액 (minor unit). 0 과 음수는 받지 않는다.
        status:
          type: string
          enum:
          - PENDING
          - SUCCEEDED
          - FAILED
          - CANCELED
          title: Status
          description: 환불 상태. 본 응답은 보통 PENDING(202 Accepted).
        env_scope:
          type: string
          enum:
          - sandbox
          - real_test
          - production
          title: Env Scope
          description: 환경 스코프. 모든 응답에 일관되게 노출한다(환경 식별 + 감사 일관성).
        requested_at:
          type: string
          format: date-time
          title: Requested At
          description: 환불 요청 시각 (aware datetime, naive 입력 시 422).
      additionalProperties: false
      type: object
      required:
      - refund_id
      - payment_id
      - amount_minor
      - status
      - env_scope
      - requested_at
      title: RefundCreateResponse
      description: '환불 생성 응답 - `202 Accepted` 의 몸통.


        즉시 응답 다섯 칸(`refund_id` · `payment_id` · `amount_minor` · `status` ·

        `requested_at`)에 **`env_scope` 를 더해** 모든 응답에 일관되게 노출한다.


        GET 단건 조회(`RefundResponse`)와 다른 객체:

        - 본 응답은 **즉시 응답 최소 필드**만 포함(BFF 폴링 시작용).

        - 상세 조회는 `GET /v1/refunds/{id}` (`RefundResponse`) 사용.


        `status`는 통상 PENDING(PG 비동기 결과 대기). 동기 SUCCEEDED는 PG가 즉시 응답한 경우만.'
    RefundResponse:
      properties:
        refund_id:
          type: integer
          minimum: 1.0
          title: Refund Id
          description: refunds.id.
        organization_id:
          type: integer
          minimum: 1.0
          title: Organization Id
          description: 소유 조직 PK.
        payment_id:
          type: integer
          minimum: 1.0
          title: Payment Id
          description: 원 결제 ID.
        invoice_id:
          anyOf:
          - type: integer
            minimum: 1.0
          - type: 'null'
          title: Invoice Id
          description: 연결된 인보이스 ID. NULL 허용.
        env_scope:
          type: string
          enum:
          - sandbox
          - real_test
          - production
          title: Env Scope
          description: 환경 스코프.
        pg_provider:
          type: string
          enum:
          - portone
          - toss
          - payup
          - offline
          title: Pg Provider
          description: PG 사업자.
        provider_refund_id:
          anyOf:
          - type: string
            maxLength: 120
          - type: 'null'
          title: Provider Refund Id
          description: PG 발급 환불 식별자. PG 비동기 처리 중에는 NULL일 수 있다. BFF/관리자/대사 입력용. 외부 사용자 UI 표시 권장 X.
        amount_minor:
          type: integer
          exclusiveMinimum: 0.0
          title: Amount Minor
          description: 환불 금액 (minor unit). 0 과 음수는 받지 않는다.
        currency:
          type: string
          const: KRW
          title: Currency
          description: 통화 코드. v1=KRW.
        status:
          type: string
          enum:
          - PENDING
          - SUCCEEDED
          - FAILED
          - CANCELED
          title: Status
          description: 환불 상태 (4값 enum).
        reason:
          anyOf:
          - type: string
            enum:
            - USER_REQUEST
            - OPS_DISPUTE_RESOLUTION
            - DUPLICATE_PAYMENT
            - PAYMENT_FAILED_REVERSAL
            - FRAUDULENT_PAYMENT
            - OTHER
          - type: 'null'
          title: Reason
          description: 환불 사유 enum. SCHEMA 자유 텍스트를 enum으로 정규화 노출 (자유 텍스트 원문은 `audit_logs.billing.refund.transition.payload.reason_raw`로 보존).
        requested_at:
          type: string
          format: date-time
          title: Requested At
          description: 환불 요청 시각 (aware datetime, naive 입력 시 422).
        confirmed_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Confirmed At
          description: 환불 확정 시각 (SUCCEEDED 진입 시 채워짐).
        created_at:
          type: string
          format: date-time
          title: Created At
          description: 환불 행 생성 시각 (aware datetime, naive 입력 시 422).
      additionalProperties: false
      type: object
      required:
      - refund_id
      - organization_id
      - payment_id
      - env_scope
      - pg_provider
      - amount_minor
      - currency
      - status
      - requested_at
      - created_at
      title: RefundResponse
      description: "환불 단일 객체 응답 - `GET /v1/refunds/{id}`.\n\nSCHEMA → DTO 매핑:\n- `refunds.id` → `refund_id`.\n- `organization_id/payment_id/invoice_id/env_scope/provider/provider_refund_id/\n  amount_minor/currency/status/requested_at/confirmed_at/created_at` → 직접 매핑.\n- `reason`은 enum 정규화하여 노출(SCHEMA는 자유 텍스트지만 DTO는 enum 형식 권장).\n- `requested_by/metadata/updated_at` 미노출 (운영 추적은 audit_logs + 운영 API).\n\n`provider_refund_id`는 PG 트랜잭션 식별자. PG 비동기 처리 중에는 NULL일 수 있다."
  securitySchemes:
    basicClientCredential:
      type: http
      scheme: basic
      description: 'Console-issued client credential. Send `Authorization: Basic base64(client_id:client_secret)`.'
    mcpOAuth2:
      type: oauth2
      description: For MCP clients. OAuth 2.0 authorization code flow with PKCE (S256) for public clients. The client_id is the HTTPS URL of an OAuth Client ID Metadata Document that XBOSS has allow-listed; dynamic client registration is not supported.
      flows:
        authorizationCode:
          authorizationUrl: https://api.xdata.kr/oauth/authorize
          tokenUrl: https://api.xdata.kr/oauth/token
          scopes: {}