# Bestellung mit Guthaben

`POST /account/api/v1/orders/create`

## Autorisierung

`Authorization: Bearer YOUR_ARNPROXY_API_KEY`

`Accept: application/json`

Erforderliche Berechtigung: `purchases`

`Content-Type: application/json`

`Idempotency-Key` · 16–100 Buchstaben, Ziffern, _ oder -. Für denselben Vorgang speichern und wiederverwenden.

## Parameter

| Name | Typ | Erforderlich / Bedingt | Standardwert | Beschreibung |
|---|---|---|---|---|
| `Idempotency-Key` (header) | string | Erforderlich | — | 16–100 Buchstaben/Ziffern/_/-. Für Vorgang und Status denselben Wert behalten; nicht mit anderem Inhalt wiederverwenden. |
| `product_id` (body) | integer | Erforderlich | — | Produkt-ID aus products; 1–2147483647. |
| `lines` (body) | object[] | Erforderlich | — | 1–20 verschiedene Standortzeilen für ein Produkt. location_id nicht doppeln; insgesamt höchstens 100000 Proxys. |
| `lines[].location_id` (body) | integer | Erforderlich | — | Standort-ID aus dem gewählten Produktkatalog. |
| `lines[].time_id` (body) | integer | Erforderlich | — | Für diesen Standort angebotene Laufzeit-ID. |
| `lines[].quantity` (body) | integer | Erforderlich | — | 1–100000; zusätzlich gilt product.minimum_quantity. |
| `lines[].purpose_id` (body) | integer | Erforderlich | — | Für den aktuellen Verwendungszweck-Ablauf 201 senden. |
| `lines[].subpurpose_id` (body) | integer | Erforderlich | — | Aktiver Unterzweck von 201; -1 für Sonstiges. |
| `lines[].other_purpose` (body) | string | Bedingt | — | Bei subpurpose_id=-1 erforderlich: 1–30 UTF-8-Zeichen, sonst ignoriert. |
| `currency` (body) | string | Erforderlich | — | TRY oder USD aus demselben Angebot; muss zur Kontowährung passen. |
| `expected_total_minor` (body) | integer | Erforderlich | — | total_minor desselben Angebots als Ganzzahl, nie Dezimalbetrag oder Text. 1–999999999999. |
| `terms` (body) | boolean | Erforderlich | — | Zur ausdrücklichen Zustimmung muss der JSON-Wahrheitswert true gesendet werden, nicht die Zeichenfolge "true". |
| `promo_code` (body) | string | Optional | `""` | Optionaler Aktionscode, höchstens 100 Bytes. Zwischen Preisabfrage und Kauf/Verlängerung unverändert lassen. |
| `auth` (body) | object | Optional | — | Lieferauthentifizierung, Standard {"mode":"username_password"}. Erlaubt keine Verwaltung primärer Zugangsdaten. |
| `auth.mode` (body) | string | Bedingt | — | Wenn auth vorhanden: username_password oder ip erforderlich. Benutzername/Passwort hier nicht angeben. |
| `auth.ip` (body) | string | Bedingt | — | IPv4 nur bei auth.mode=ip erforderlich; bei username_password weglassen. |

## Anfrageinhalt

Ersetzen Sie YOUR_/FROM_ durch Werte aus Katalog, Angebot oder Umfang. Beispiele lassen die Zustimmung auf false; bestätigen Sie echte Vorgänge nur bewusst.

```json
{
  "product_id": "FROM_PRODUCTS",
  "lines": [
    {
      "location_id": "FROM_CATALOG",
      "time_id": "FROM_CATALOG",
      "quantity": 1,
      "purpose_id": 201,
      "subpurpose_id": "FROM_CATALOG_CHILDREN"
    }
  ],
  "currency": "FROM_QUOTE",
  "expected_total_minor": "FROM_QUOTE_TOTAL_MINOR",
  "promo_code": "",
  "terms": false
}
```

## Weitere Anwendungsbeispiele

IDs und Preise sind beispielhaft; verwenden Sie echte Werte aus dem Katalog und demselben Angebot. JSON-IDs und expected_total_minor müssen Zahlen sein. Beispiele verwenden bewusst terms=false. Senden Sie terms=true nur nach ausdrücklicher Zustimmung zur kostenpflichtigen Aktion.

### Ein Produkttyp, zwei Länder

Verwenden Sie bis zu 20 verschiedene location_id unter einem product_id. Jedes Land erzeugt eine eigene Bestellung; der verknüpfte Einkauf wird in einer Rechnung behandelt. Mengenrabatte werden pro Land berechnet.

```json
{
  "product_id": 5,
  "lines": [
    {
      "location_id": 10,
      "time_id": 101,
      "quantity": 1,
      "purpose_id": 201,
      "subpurpose_id": 202
    },
    {
      "location_id": 11,
      "time_id": 102,
      "quantity": 1,
      "purpose_id": 201,
      "subpurpose_id": 202
    }
  ],
  "currency": "TRY",
  "expected_total_minor": 2000,
  "promo_code": "",
  "terms": false
}
```

### Verwendungszweck „Sonstiges“

Für Sonstiges senden Sie subpurpose_id=-1 und other_purpose mit 1–30 Zeichen. Bei anderen Auswahlen ist other_purpose nicht erforderlich. purpose_id bleibt 201.

```json
{
  "product_id": 5,
  "lines": [
    {
      "location_id": 10,
      "time_id": 101,
      "quantity": 1,
      "purpose_id": 201,
      "subpurpose_id": -1,
      "other_purpose": "Custom purpose"
    }
  ],
  "currency": "TRY",
  "expected_total_minor": 1000,
  "promo_code": "",
  "terms": false
}
```

## Anfragebeispiel

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

## Antworten · HTTP 201, 200

```json
{
  "ok": true,
  "data": {
    "state": "accepted",
    "delivery_state_at_acceptance": "queued",
    "currency": "TRY",
    "total": "10.00",
    "total_minor": 1000,
    "checkout_group_id": null,
    "orders": [
      {
        "id": 10001,
        "number": "1000010001",
        "location_id": 10,
        "time_id": 101,
        "quantity": 1,
        "total": "10.00"
      }
    ],
    "accepted_at": "2030-01-01T12:00:00+00:00",
    "automatic_renewal": false,
    "replayed": false
  },
  "meta": {
    "request_id": "000000000000000000000001",
    "phase": "public_v1",
    "source": "arnproxy_records"
  }
}
```

| Name | Typ | Bedingt | Beschreibung |
|---|---|---|---|
| `ok` | boolean | — | Erfolgskennzeichen; bei false error.code prüfen. |
| `data` | object | — | Vorgangsspezifisches Ergebnis; Beispiele sind synthetisch und dienen der Veranschaulichung. |
| `data.state` | string | — | Datensatz-/Vorgangsstatus. accepted bedeutet nicht geliefert, completed keinen Verbindungstest. |
| `data.delivery_state_at_acceptance` | string | — | Vorgangsspezifischer Wert für delivery state at acceptance. Rückgabetyp beibehalten und Verhaltenshinweise beachten. |
| `data.currency` | string | — | Kontowährung der Transaktion: TRY oder USD. |
| `data.total` | string | — | Geldbetrag; Text-/Ganzzahldarstellung für Genauigkeit beibehalten. |
| `data.total_minor` | integer | — | Ganzzahl in kleinster Währungseinheit: 1000 bedeutet 10.00 TRY/USD. |
| `data.checkout_group_id` | integer|null | — | Vorgangsspezifischer Wert für checkout group id. Rückgabetyp beibehalten und Verhaltenshinweise beachten. |
| `data.orders` | array | — | Vorgangsspezifischer Wert für orders. Rückgabetyp beibehalten und Verhaltenshinweise beachten. |
| `data.orders[]` | object | — | Vorgangsspezifischer Wert für orders. Rückgabetyp beibehalten und Verhaltenshinweise beachten. |
| `data.orders[].id` | integer | — | Zugehörige ARNPROXY-Datensatz-ID statt interner Anbieter-ID verwenden. |
| `data.orders[].number` | string | — | Angezeigte Bestellnummer, nicht mit Feldern für id austauschbar. |
| `data.orders[].location_id` | integer | — | Lokale Katalog-ID für Standort oder Produkttyp. |
| `data.orders[].time_id` | integer | — | Lokale Laufzeit-/GB-Plan-ID, keine Anzahl von Tagen oder GB. |
| `data.orders[].quantity` | integer | — | Gewählte oder bestellte Proxyanzahl. |
| `data.orders[].total` | string | — | Geldbetrag; Text-/Ganzzahldarstellung für Genauigkeit beibehalten. |
| `data.accepted_at` | string | — | Zeitstempel im vom API gelieferten Format; Beispieldaten sind synthetisch. |
| `data.automatic_renewal` | boolean | — | Vorgangsspezifischer Wert für automatic renewal. Rückgabetyp beibehalten und Verhaltenshinweise beachten. |
| `data.replayed` | boolean | — | Gespeichertes Ergebnis desselben Vorgangs, kein Beweis für neue Abbuchung/Aktion. |
| `meta` | object | — | Metadaten zu Anfragezuordnung und Datenquelle. |
| `meta.request_id` | string | — | Kennung dieser HTTP-Anfrage, kein Vorgangsschlüssel oder Bestell-ID. |
| `meta.phase` | string | — | Vorgangsspezifischer Wert für phase. Rückgabetyp beibehalten und Verhaltenshinweise beachten. |
| `meta.source` | string | — | Datenquelle; lokale Datensätze und Live-Anbieterabfragen sind unterschiedliche Nachweise. |

## Verhalten & wichtige Hinweise

- IDs aus products/catalog übernehmen. quote-Zeilen enthalten nur location_id, time_id, quantity. purchase erfordert zusätzlich purpose_id=201 und gewählte subpurpose_id.
- Mehrere Länder erzeugen getrennte Bestellungen und eine mehrzeilige Rechnung. Rabatte gelten je Land. accepted ist keine Lieferung; order_delivery und order_proxies verfolgen.
- Timeout/5xx beweist keinen Schreibfehler. Ursprünglichen Idempotency-Key für den Status verwenden. Nicht mit neuem Schlüssel wiederholen; GET sendet die Änderung nicht erneut.
- Verlangen Sie bei einer Standardbestellung keine zwei Auswahlen. Suchen Sie id=201 in catalog.purposes und zeigen Sie nur dessen children an. Bei purchase ist purpose_id die feste Ganzzahl 201; subpurpose_id ist die ID des gewählten Unterzwecks. Die Hierarchie bleibt für bestehende Integrationen erhalten.
- Für Sonstiges senden Sie subpurpose_id=-1 und other_purpose mit 1–30 Zeichen. Bei anderen Auswahlen ist other_purpose nicht erforderlich. purpose_id bleibt 201.
- Verwenden Sie bis zu 20 verschiedene location_id unter einem product_id. Jedes Land erzeugt eine eigene Bestellung; der verknüpfte Einkauf wird in einer Rechnung behandelt. Mengenrabatte werden pro Land berechnet.

Authentifizierung und Validierung können eine Anfrage vor der Ausführung ablehnen. Beachten Sie die Fehlerreferenz und bewahren Sie request_id für den Support auf. Senden Sie niemals Schlüssel oder Passwörter.

[Fehler & Limits](https://docs.arnproxy.com/de/api-v1/errors)

[Denselben Vorgang verfolgen: Kaufstatus prüfen](https://docs.arnproxy.com/de/api-v1/orders/create/status)
