# Balance renewal; real debit

`POST /account/api/v1/renewals/create`

## Authorization

`Authorization: Bearer YOUR_ARNPROXY_API_KEY`

`Accept: application/json`

Required permission: `renewals`

`Content-Type: application/json`

`Idempotency-Key` · 16–100 letters, digits, _ or -. Persist and reuse the same value for the same operation.

## Parameters

| Name | Type | Required / Conditional | Default | Description |
|---|---|---|---|---|
| `Idempotency-Key` (header) | string | Required | — | 16–100 letters/digits/_/-. Keep the same value for the operation/status; do not reuse with a different body. |
| `proxy_ids` (body) | integer[] | Required | — | 1–1000 unique owned proxy IDs; do not mix product types where a common scope/price is required. Some operations have tighter bounds. |
| `time_id` (body) | integer | Required | — | Period/GB-plan ID from the matching catalog/options, not a day/GB count. |
| `promo_code` (body) | string | Optional | `""` | Optional promo, up to 100 bytes. Keep it identical between quote and purchase/renewal. |
| `currency` (body) | string | Required | — | TRY or USD from the same quote; must match the account currency. |
| `expected_total_minor` (body) | integer | Required | — | total_minor from the same quote, as an integer; never decimal money or a string. 1–999999999999. |
| `expected_days` (body) | integer | Required | — | days from the same price quote. 1–36500. |
| `expected_selection_hash` (body) | string | Required | — | selection_hash from the same quote: 64 lowercase hexadecimal characters. |
| `terms` (body) | boolean | Required | — | Must be the JSON boolean true for explicit approval, not the string "true". |

## Request body

Replace YOUR_/FROM_ placeholders with values from the relevant catalog, quote or scope. Examples leave consent false; only approve a real operation intentionally.

```json
{
  "proxy_ids": [
    "YOUR_PROXY_ID"
  ],
  "time_id": "FROM_RENEWAL_OPTIONS",
  "promo_code": "",
  "currency": "FROM_QUOTE",
  "expected_total_minor": "FROM_QUOTE_TOTAL_MINOR",
  "expected_days": "FROM_QUOTE_DAYS",
  "expected_selection_hash": "FROM_QUOTE_SELECTION_HASH",
  "terms": false
}
```

## Request example

### curl

```curl
printf 'Authorization: Bearer %s\n' "$ARNPROXY_API_KEY" |
  curl --silent --show-error --header @- \
    --header 'Accept: application/json' \
    --connect-timeout 10 --max-time 30 \
    --header 'Idempotency-Key: YOUR_SAVED_OPERATION_KEY' \
    --request POST --header 'Content-Type: application/json' \
    --data-binary @request.json \
    'https://www.arnproxy.com/account/api/v1/renewals/create'
```

### python

```python
import os, requests

headers = {"Authorization": "Bearer " + os.environ["ARNPROXY_API_KEY"]}
headers["Idempotency-Key"] = "YOUR_SAVED_OPERATION_KEY"
import json
with open("request.json", encoding="utf-8") as f:
    payload = json.load(f)
response = requests.post(
    "https://www.arnproxy.com/account/api/v1/renewals/create",
    headers=headers, json=payload,
    timeout=(10, 30), allow_redirects=False
)
print(response.status_code, response.text)
# No automatic write retry.
```

### javascript

```javascript
const headers = { Authorization: `Bearer ${process.env.ARNPROXY_API_KEY}` };
headers['Idempotency-Key'] = 'YOUR_SAVED_OPERATION_KEY';
const { readFile } = await import('node:fs/promises');
headers['Content-Type'] = 'application/json';
const body = await readFile('request.json', 'utf8');
const response = await fetch("https://www.arnproxy.com/account/api/v1/renewals/create", {
  method: 'POST', headers, redirect: 'error',
  signal: AbortSignal.timeout(30000), body
});
console.log(response.status, await response.text());
// A write timeout is ambiguous; query its saved operation.
```

### php

```php
<?php
$headers = ['Accept: application/json',
    'Authorization: Bearer '.getenv('ARNPROXY_API_KEY')];
$headers[] = 'Idempotency-Key: YOUR_SAVED_OPERATION_KEY';
$headers[] = 'Content-Type: application/json';
$ch = curl_init('https://www.arnproxy.com/account/api/v1/renewals/create');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 30,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => file_get_contents('request.json'),
]);
$result = curl_exec($ch);
if ($result === false) {
    // Do not repeat a write; use the original operation key.
    throw new RuntimeException('Transport result unknown');
}
echo curl_getinfo($ch, CURLINFO_HTTP_CODE).PHP_EOL.$result;
curl_close($ch);
```

### go

```go
package main

import (
  "fmt"
  "io"
  "net/http"
  "os"
  "time"
)

func main() {
  client := &http.Client{Timeout: 30*time.Second,
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
      return http.ErrUseLastResponse
    }}
  var body io.Reader
  file, err := os.Open("request.json"); if err != nil { panic(err) }
  defer file.Close(); body = file
  req, err := http.NewRequest("POST", "https://www.arnproxy.com/account/api/v1/renewals/create", body)
  if err != nil { panic(err) }
  req.Header.Set("Authorization", "Bearer "+os.Getenv("ARNPROXY_API_KEY"))
  req.Header.Set("Idempotency-Key", "YOUR_SAVED_OPERATION_KEY")
  req.Header.Set("Content-Type", "application/json")
  res, err := client.Do(req); if err != nil { panic(err) }
  defer res.Body.Close()
  data, err := io.ReadAll(res.Body); if err != nil { panic(err) }
  fmt.Println(res.StatusCode, string(data))
}
```

### csharp

```csharp
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

using var handler = new HttpClientHandler { AllowAutoRedirect = false };
using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) };
using var request = new HttpRequestMessage(HttpMethod.Post,
    "https://www.arnproxy.com/account/api/v1/renewals/create");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("ARNPROXY_API_KEY"));
request.Headers.Add("Idempotency-Key", "YOUR_SAVED_OPERATION_KEY");
request.Content = new StringContent(
    await File.ReadAllTextAsync("request.json"), Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine((int)response.StatusCode);
Console.WriteLine(await response.Content.ReadAsStringAsync());
// Never automatically retry an ambiguous write.
```

### java

```java
import java.net.URI;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

// Inside your application method:
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://www.arnproxy.com/account/api/v1/renewals/create"))
    .header("Authorization", "Bearer " + System.getenv("ARNPROXY_API_KEY"))
    .header("Accept", "application/json")
    .header("Idempotency-Key", System.getenv("ARNPROXY_OPERATION_KEY"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(
        Files.readString(Path.of("request.json"), StandardCharsets.UTF_8)))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
```

## Responses · HTTP 201, 200

```json
{
  "ok": true,
  "data": {
    "state": "completed",
    "currency": "TRY",
    "total": "10.00",
    "total_minor": 1000,
    "renewal_batch_id": 100,
    "renewal_request_ids": [
      101
    ],
    "days": 7,
    "proxies": [
      {
        "id": 12345,
        "previous_last_service_date": "2030-02-01",
        "last_service_date": "2030-02-08",
        "total": "10.00"
      }
    ],
    "completed_at": "2030-01-01T12:00:00+00:00",
    "automatic_renewal": false,
    "source": "existing_website_renewal",
    "replayed": false
  },
  "meta": {
    "request_id": "000000000000000000000001",
    "phase": "public_v1",
    "source": "arnproxy_records"
  }
}
```

| Name | Type | Conditional | Description |
|---|---|---|---|
| `ok` | boolean | — | Success envelope flag; on false inspect error.code. |
| `data` | object | — | Operation-specific result; examples are illustrative and synthetic. |
| `data.state` | string | — | Record/operation state. accepted is not delivery; completed is not a connection test. |
| `data.currency` | string | — | Account transaction currency: TRY or USD. |
| `data.total` | string | — | Money amount; preserve the returned string/integer representation for precision. |
| `data.total_minor` | integer | — | Integer minor units: 1000 means 10.00 TRY/USD. |
| `data.renewal_batch_id` | integer | — | Operation-specific renewal batch id value; preserve its demonstrated type and consult the behavior notes. |
| `data.renewal_request_ids` | array | — | Operation-specific renewal request ids value; preserve its demonstrated type and consult the behavior notes. |
| `data.renewal_request_ids[]` | integer | — | Operation-specific renewal request ids value; preserve its demonstrated type and consult the behavior notes. |
| `data.days` | integer | — | Plan duration in days, separate from a GB plan’s traffic amount. |
| `data.proxies` | array | — | Operation-specific proxies value; preserve its demonstrated type and consult the behavior notes. |
| `data.proxies[]` | object | — | Operation-specific proxies value; preserve its demonstrated type and consult the behavior notes. |
| `data.proxies[].id` | integer | — | Relevant ARNPROXY record ID; use it instead of the upstream internal ID. |
| `data.proxies[].previous_last_service_date` | string | — | Last service day: current, previous or projected by the quote. A projection does not renew. |
| `data.proxies[].last_service_date` | string | — | Last service day: current, previous or projected by the quote. A projection does not renew. |
| `data.proxies[].total` | string | — | Money amount; preserve the returned string/integer representation for precision. |
| `data.completed_at` | string | — | Timestamp in the API’s returned representation; example dates are synthetic. |
| `data.automatic_renewal` | boolean | — | Operation-specific automatic renewal value; preserve its demonstrated type and consult the behavior notes. |
| `data.source` | string | — | Data source; local records and a live provider lookup are different evidence. |
| `data.replayed` | boolean | — | Saved result for the same operation was returned, not proof of a new debit/action. |
| `meta` | object | — | Request correlation and data-source metadata. |
| `meta.request_id` | string | — | This HTTP request’s correlation ID, not an operation key or order ID. |
| `meta.phase` | string | — | Operation-specific phase value; preserve its demonstrated type and consult the behavior notes. |
| `meta.source` | string | — | Data source; local records and a live provider lookup are different evidence. |

## Behavior & important notes

- Renewal uses existing website pricing and balance processing. Copy amount, days and selection hash from the same renewal_quote. It does not enable automatic renewal.
- A timeout/5xx is not proof that a write failed. Use the original Idempotency-Key with its status resource. Do not retry under a new key; GET does not resend the change.
- Proxies in one renewal request must share the same product type. Quantity discounts are calculated separately using each country’s selected quantity, not the combined country total.

Authentication and validation may reject a request before execution. Consult the error reference and retain request_id when contacting support. Never send keys or passwords.

[Errors & limits](https://docs.arnproxy.com/api-v1/errors)

[Follow the same operation: Saved renewal result](https://docs.arnproxy.com/api-v1/renewals/status)
