# Perpanjang dengan saldo

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

## Otorisasi

`Authorization: Bearer YOUR_ARNPROXY_API_KEY`

`Accept: application/json`

Izin yang diperlukan: `renewals`

`Content-Type: application/json`

`Idempotency-Key` · 16–100 huruf, angka, _ atau -. Simpan dan gunakan nilai yang sama untuk operasi yang sama.

## Parameter

| Nama | Tipe | Wajib / Bersyarat | Nilai bawaan | Keterangan |
|---|---|---|---|---|
| `Idempotency-Key` (header) | string | Wajib | — | 16–100 huruf/angka/_/-. Pertahankan nilai untuk operasi/status; jangan pakai lagi dengan isi berbeda. |
| `proxy_ids` (body) | integer[] | Wajib | — | 1–1000 ID proxy unik milik sendiri; jangan campur tipe produk saat perlu cakupan/harga bersama. Beberapa operasi lebih ketat. |
| `time_id` (body) | integer | Wajib | — | ID periode/paket GB dari katalog/options terkait, bukan jumlah hari/GB. |
| `promo_code` (body) | string | Opsional | `""` | Promo opsional, maksimal 100 byte. Pertahankan sama antara harga dan pembelian/perpanjangan. |
| `currency` (body) | string | Wajib | — | TRY atau USD dari kutipan harga yang sama; harus cocok dengan mata uang akun. |
| `expected_total_minor` (body) | integer | Wajib | — | total_minor dari harga yang sama sebagai integer, bukan nominal desimal atau string. 1–999999999999. |
| `expected_days` (body) | integer | Wajib | — | days dari harga yang sama; 1–36500. |
| `expected_selection_hash` (body) | string | Wajib | — | selection_hash dari harga yang sama: 64 karakter heksadesimal kecil. |
| `terms` (body) | boolean | Wajib | — | Persetujuan harus berupa boolean JSON true, bukan string "true". |

## Isi permintaan

Ganti YOUR_/FROM_ dengan nilai katalog, kutipan harga, atau cakupan terkait. Persetujuan pada contoh tetap false; setujui operasi nyata secara sengaja.

```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
}
```

## Contoh permintaan

### 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());
```

## Respons · 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"
  }
}
```

| Nama | Tipe | Bersyarat | Keterangan |
|---|---|---|---|
| `ok` | boolean | — | Penanda berhasil; jika false, periksa error.code. |
| `data` | object | — | Hasil khusus operasi; contoh bersifat ilustratif dan sintetis. |
| `data.state` | string | — | Status catatan/operasi. accepted bukan terkirim; completed bukan tes koneksi. |
| `data.currency` | string | — | Mata uang transaksi akun: TRY atau USD. |
| `data.total` | string | — | Nominal uang; pertahankan representasi string/integer untuk presisi. |
| `data.total_minor` | integer | — | Integer satuan uang terkecil: 1000 berarti 10.00 TRY/USD. |
| `data.renewal_batch_id` | integer | — | Nilai khusus operasi untuk renewal batch id. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `data.renewal_request_ids` | array | — | Nilai khusus operasi untuk renewal request ids. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `data.renewal_request_ids[]` | integer | — | Nilai khusus operasi untuk renewal request ids. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `data.days` | integer | — | Durasi paket dalam hari, terpisah dari jumlah trafik paket GB. |
| `data.proxies` | array | — | Nilai khusus operasi untuk proxies. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `data.proxies[]` | object | — | Nilai khusus operasi untuk proxies. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `data.proxies[].id` | integer | — | ID catatan ARNPROXY terkait; gunakan alih-alih ID internal penyedia. |
| `data.proxies[].previous_last_service_date` | string | — | Hari layanan terakhir: saat ini, sebelumnya, atau proyeksi harga. Proyeksi tidak memperpanjang. |
| `data.proxies[].last_service_date` | string | — | Hari layanan terakhir: saat ini, sebelumnya, atau proyeksi harga. Proyeksi tidak memperpanjang. |
| `data.proxies[].total` | string | — | Nominal uang; pertahankan representasi string/integer untuk presisi. |
| `data.completed_at` | string | — | Stempel waktu sesuai representasi API; tanggal contoh sintetis. |
| `data.automatic_renewal` | boolean | — | Nilai khusus operasi untuk automatic renewal. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `data.source` | string | — | Sumber data; catatan lokal dan kueri penyedia langsung merupakan bukti berbeda. |
| `data.replayed` | boolean | — | Hasil tersimpan dari operasi sama, bukan bukti debit/tindakan baru. |
| `meta` | object | — | Metadata korelasi permintaan dan sumber data. |
| `meta.request_id` | string | — | ID korelasi permintaan HTTP ini, bukan kunci operasi atau ID pesanan. |
| `meta.phase` | string | — | Nilai khusus operasi untuk phase. Pertahankan tipe yang dikembalikan dan baca catatan perilaku. |
| `meta.source` | string | — | Sumber data; catatan lokal dan kueri penyedia langsung merupakan bukti berbeda. |

## Perilaku & catatan penting

- Perpanjangan memakai harga dan saldo situs yang ada. Salin nominal, hari, dan hash pilihan dari renewal_quote yang sama. Tidak mengaktifkan perpanjangan otomatis.
- Timeout/5xx bukan bukti perubahan gagal. Gunakan Idempotency-Key awal untuk status. Jangan ulang dengan kunci baru; GET tidak mengirim ulang perubahan.
- Proxy dalam satu permintaan perpanjangan harus memiliki jenis produk yang sama. Diskon dihitung per negara berdasarkan jumlah yang dipilih, bukan gabungan semua negara.

Autentikasi dan validasi dapat menolak permintaan sebelum dijalankan. Lihat referensi kesalahan dan simpan request_id untuk dukungan. Jangan kirim kunci atau kata sandi.

[Kesalahan & batas](https://docs.arnproxy.com/id/api-v1/errors)

[Lacak operasi yang sama: Status perpanjangan](https://docs.arnproxy.com/id/api-v1/renewals/status)
