# Payment refunds This method initiates a **refund** of a successful SBP payment. Pass the `order_id` of the original payment and a separate `user_data` for the refund operation. After the request is accepted, the API returns `refund_order_id` and status `REFUND_PENDING`; the final result arrives at the project `notify_url`. Request format and signatures — [API request format](../init-request.md). ## How it works 1. **Original payment** — a refund is available for `order_id` of a payment in success status (`SUCCESS`, code `3`). The ID comes from the [form](./init-form.md) or [GATE](./host2host.md) creation response. 2. **Initiation** — signed request to `init_refund` with a unique **refund** `user_data` (different from the payment `user_data`). 3. **Response** — `refund_order_id`, `status` `9` (`REFUND_PENDING`), and `status_description`. 4. **Final status** — POST JSON callback to `notify_url`; if needed, poll status by `refund_order_id` via [Payment status](./status.md). See [Transaction statuses](../transaction-statuses.md) for `status` and `status_description` for refunds (`REFUND`, `REFUND_PENDING`). ## Technical details | | | | --- | --- | | **Endpoint** | `https://api.1payment.com/init_refund` | | **Methods** | `GET`, `POST` | | **Response format** | JSON | | **Callback type** | `payment_type` — see [Payment types](../payment-types.md) (`refund` in refund notifications) | ## Request parameters ### Required | Parameter | Type | Description | | --- | --- | --- | | `partner_id` | Integer | Your unique ID in the 1Payment system. | | `project_id` | Integer | Your project identifier. | | `order_id` | String | `order_id` of the **original successful** SBP payment. | | `user_data` | String | Unique **refund** ID on your side (different from payment `user_data`). Up to 255 characters; UUID recommended. | | `sign` | String | Request signature (see the "Signature" section). | ### Optional | Parameter | Type | Description | | --- | --- | --- | | `amount` | Number | **Partial** refund amount. Confirm partial refund availability with your 1Payment manager. | ## Signature generation (`sign`) Signature: MD5, lowercase (hex). General rules — [API request format](../init-request.md#request-signature-sign). **Formula:** ```text MD5(init_refund + <параметры_без_sign_в_алфавитном_порядке_через_&> + ) ``` **Example string before hashing:** ```text init_refundorder_id=8p3brmb19gfg0sg8gcwhws8kgc748s87&partner_id=1234&project_id=5678&user_data=abcd1234secret_key ``` For a partial refund, the passed `amount` is included in the signature. ### Signature verification in the documentation {% signatureVerifier method="init_refund" preset="sbp_init_refund" /%} ## Request examples {% codeTabs %} {% tab label="Node.js" %} ```javascript const crypto = require('crypto'); const axios = require('axios'); async function initSbpRefund(apiKey, params) { const sortedKeys = Object.keys(params).sort(); const queryString = sortedKeys.map((key) => `${key}=${params[key]}`).join('&'); const baseString = `init_refund${queryString}${apiKey}`; params.sign = crypto.createHash('md5').update(baseString).digest('hex'); const response = await axios.get('https://api.1payment.com/init_refund', { params }); return response.data; } const apiKey = process.env.ONEPAYMENT_API_KEY; const data = { partner_id: 1234, project_id: 5678, order_id: '8p3brmb19gfg0sg8gcwhws8kgc748s87', user_data: 'abcd1234', }; initSbpRefund(apiKey, data).then(console.log); ``` {% /tab %} {% tab label="Python" %} ```python import hashlib import os import requests def init_sbp_refund(api_key: str, params: dict) -> dict: sorted_keys = sorted(params.keys()) query_string = "&".join(f"{k}={params[k]}" for k in sorted_keys) base_string = f"init_refund{query_string}{api_key}" params["sign"] = hashlib.md5(base_string.encode("utf-8")).hexdigest() response = requests.get("https://api.1payment.com/init_refund", params=params) response.raise_for_status() return response.json() api_key = os.environ["ONEPAYMENT_API_KEY"] data = { "partner_id": 1234, "project_id": 5678, "order_id": "8p3brmb19gfg0sg8gcwhws8kgc748s87", "user_data": "abcd1234", } print(init_sbp_refund(api_key, data)) ``` {% /tab %} {% tab label="cURL" %} ```bash # sign = md5("init_refund" + order_id=...&partner_id=1234&project_id=5678&user_data=abcd1234 + API_KEY) curl -sS "https://api.1payment.com/init_refund?partner_id=1234&project_id=5678&order_id=8p3brmb19gfg0sg8gcwhws8kgc748s87&user_data=abcd1234&sign=PASTE_MD5_HEX" ``` {% /tab %} {% /codeTabs %} ## API response Successful response (`200`): ```json { "refund_order_id": "crf_1p3brmb19gfg0sg8gcwhws8kgc748s87", "status": 9, "status_description": "REFUND_PENDING", "status_code": 0 } ``` | Field | Description | | --- | --- | | `refund_order_id` | Refund ID in 1Payment; use for status polling and accounting. | | `status` | Numeric code (`9` — refund in progress). | | `status_description` | `REFUND_PENDING`, etc. | | `status_code` | Decline code on refund error (see [decline codes](../decline-error-codes.md)). | Request error (`400`): ```json { "error_code": 2 } ``` ## Status notifications (callbacks) After the refund status changes, the server sends **POST** JSON to the project `notify_url`. | Parameter | Type | Req. | Description | | --- | --- | --- | --- | | `payment_type` | String | Yes | Operation type (see [Payment types](../payment-types.md)). | | `order_id` | String | Yes | **Refund** identifier in 1Payment. | | `project_id` | Integer | Yes | Your project ID. | | `status` | Integer | Yes | Refund state (`5` — `REFUND`, `9` — `REFUND_PENDING`, etc.). | | `status_description` | String | Yes | `REFUND`, `REFUND_PENDING`, `FAILURE`, etc. | | `init_time` | String | Yes | Refund creation time. | | `status_time` | String | Yes | Status received time. | | `merchant_price` | Number | Yes | Original payment amount for the payer. | | `init_price` | Number | No | Amount at initiation. | | `user_price` | Number | Yes | Refund debit amount. | | `user_data` | String | Yes | Refund ID passed in `init_refund`. | | `original_order_id` | String | No | Original payment `order_id`. | | `status_code` | String | No | Error code on decline. | | `sign` | String | Yes | Callback signature. | **Important:** your server must return **HTTP 200 OK**. Otherwise the system retries the callback **once per minute for 10 minutes**. **Callback signature verification:** MD5 of all parameters in alphabetical order joined by `&` + `API_KEY` (**without** the `init_refund` prefix). See [API request format](../init-request.md#callbacks-notifications). ## Related sections - [Form payment creation](./init-form.md) - [Host-to-host payment creation (GATE)](./host2host.md) - [Payment status](./status.md) - [Transaction statuses](../transaction-statuses.md) - [Payment types](../payment-types.md) - [Error codes (API)](../error-codes-api.md) - [Decline error codes](../decline-error-codes.md)