# Payment refunds This method initiates a **refund** of a successful **bank card** 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 — see [API request format](../init-request.md). ## How it works 1. **Original payment** — a refund is possible for an `order_id` of a payment in success status (`SUCCESS`, code `3`). The ID comes from the [form](./init-form.md) or [host2host (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** — callback POST JSON to `notify_url`; if needed, poll status by `refund_order_id` via [Payment statuses](./status.md). Interpretation of `status` and `status_description` for refunds — in [Transaction statuses](../transaction-statuses.md) (`REFUND`, `REFUND_PENDING`). ## Technical information | | | | --- | --- | | **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** card payment. | | `user_data` | String | Unique **refund** ID on your side (different from the payment `user_data`). Up to 255 characters; UUID is recommended. | | `sign` | String | Request signature (see the "Signature" section). | ### Optional | Parameter | Type | Description | | --- | --- | --- | | `amount` | Number | **Partial** refund amount. Contact your 1Payment account manager to confirm partial refund availability. | ## Signature generation (`sign`) Signature: MD5, lowercase (hex). General rules — [API request format](../init-request.md#подпись-запроса-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 partial refunds, the passed `amount` is included in the signature. ### Signature verification in the documentation {% signatureVerifier method="init_refund" preset="card_init_refund" /%} ## Request examples {% codeTabs %} {% tab label="Node.js" %} ```javascript const crypto = require('crypto'); const axios = require('axios'); async function initCardRefund(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', }; initCardRefund(apiKey, data).then(console.log); ``` {% /tab %} {% tab label="Python" %} ```python import hashlib import os import requests def init_card_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_card_refund(api_key, data)) ``` {% /tab %} {% tab label="PHP" %} ```php $v) { if ($k === 'sign') { continue; } $tail .= "{$k}={$v}&"; } $tail = substr($tail, 0, -1); // 2. Формирование подписи (префикс init_refund) $params['sign'] = md5('init_refund' . $tail . $apiKey); // 3. Запрос к API $url = 'https://api.1payment.com/init_refund?' . http_build_query($params); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); return $response; } // Пример данных запроса $apiKey = getenv('ONEPAYMENT_API_KEY'); $data = [ 'partner_id' => 1234, 'project_id' => 5678, 'order_id' => '8p3brmb19gfg0sg8gcwhws8kgc748s87', 'user_data' => 'abcd1234', ]; echo initCardRefund($apiKey, $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 | Time the status was received. | | `merchant_price` | Number | Yes | Original payment amount for the payer. | | `init_price` | Number | No | Amount at initialization. | | `user_price` | Number | Yes | Refund debit amount. | | `user_data` | String | Yes | Refund ID passed in `init_refund`. | | `original_order_id` | String | No | `order_id` of the original payment. | | `status_code` | String | No | Decline error code. | | `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 with `&` + `API_KEY` (**without** the `init_refund` prefix). For details, see [API request format](../init-request.md#колбеки-уведомления). ## Related sections - [Create payment via form](./init-form.md) - [Create host2host (GATE) payment](./host2host.md) - [Create subscription payment](./recurring.md) - [Payment statuses](./status.md) - [Transaction statuses](../transaction-statuses.md) - [Payment types](../payment-types.md) - [Error codes (API)](../error-codes-api.md) - [Error codes (declines)](../decline-error-codes.md)