# Convert API

> Växla mellan kryptovalutor direkt från ditt handlarsaldo — hämta en direktkurs och utför till marknadspris.

Med Convert API kan du växla mellan valutorna som finns i ditt handlarsaldo till aktuellt marknadspris — samma motor som driver fliken **Swap** i handlarens instrumentpanel, nu åtkomlig från din backend.

> **WARNING:** Convert-slutpunkter signeras med din **vanliga API-nyckel** — samma som används för [Payment API](/docs/payments)-anrop, **inte** Payout API-nyckeln. Att utföra en konvertering debiterar och krediterar omedelbart ditt handlarsaldo, så behandla denna nyckel med samma omsorg som alla autentiseringsuppgifter som flyttar pengar.

## Hämta konverteringskurs

Returnerar en indikativ kurs för en konvertering till aktuellt marknadspris — den effektiva kursen och resulterande belopp. Inget debiteras eller reserveras; anropa så ofta du behöver innan du utför.

`POST /v1/convert/price`

### Begäranparametrar

| Fält | Typ | Obligatoriskt | Beskrivning | Värde |
|------|-----|---------------|-------------|-------|
| `from_currency` | string | ja | Källvaluta | `BTC`, `ETH`, `USDT`, `USDC`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `to_currency` | string | ja | Målvaluta. Måste skilja sig från `from_currency` | `USDT`, `USDC`, `BTC`, `ETH`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `amount` | decimal | ja | Belopp att konvertera, större än `0` |  |
| `amount_type` | string | ja | Vilken sida `amount` avser | `from`, `to` |

> **INFO:** `amount_type=from` spenderar exakt `amount` i `from_currency`. `amount_type=to` mottar exakt `amount` i `to_currency`.

**🟢 200 OK** · `application/json`

```json
{
  "state": 0,
  "result": {
    "success": true,
    "from_currency": "BTC",
    "to_currency": "USDT",
    "amount_type": "from",
    "from_amount": "0.01000000",
    "to_amount": "947.86690000",
    "effective_rate": "94786.69000000",
    "from_amount_usd": "947.87",
    "to_amount_usd": "947.87"
  }
}
```

#### Svarsfält

| Fält | Typ | Beskrivning |
|------|-----|-------------|
| `success` | boolean | Om kursen beräknades korrekt |
| `from_currency` | string | Källvaluta |
| `to_currency` | string | Målvaluta |
| `amount_type` | string | Speglar förfrågans `amount_type` |
| `from_amount` | string | Belopp som skulle debiteras i `from_currency` |
| `to_amount` | string | Belopp som skulle krediteras i `to_currency` |
| `effective_rate` | string | Kurs som tillämpas på denna kursförfrågan — 1 enhet `from_currency` i `to_currency` (inkluderar redan plattformens prissättning) |
| `from_amount_usd` | string \| null | USD-motsvarighet till `from_amount` |
| `to_amount_usd` | string \| null | USD-motsvarighet till `to_amount` |

- Kursen är **endast indikativ** — marknadspriset kan förändras mellan kursförfrågan och utförandeanropet.
- Detta anrop debiterar eller reserverar inget saldo.

> Use your project UUID and the endpoint-appropriate API key from the merchant dashboard.

#### Interactive request: `POST /v1/convert/price`
  - `from_currency` (enum, required): BTC,ETH,USDT,USDC,TRX,BNB,GRAM,SOL,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `to_currency` (enum, required): USDT,USDC,BTC,ETH,TRX,BNB,GRAM,SOL,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `amount` (decimal, required)
  - `amount_type` (enum, required): from,to

## Utföra konvertering

Utför en konvertering till aktuellt marknadspris och uppdaterar ditt handlarsaldo. Det finns inget separat steg för att "bekräfta en kurs" — anropa denna slutpunkt direkt med det belopp du vill konvertera.

`POST /v1/convert`

> **INFO:** **Idempotens.** Att upprepa exakt samma förfrågan (samma `from_currency`, `to_currency`, `amount`, `amount_type`) inom cirka en minut efter det första anropet returnerar den befintliga konverteringen istället för att skapa en andra. Efter det fönstret behandlas en identisk förfrågan som en ny konvertering — försök inte blint igen vid en timeout utan att först kontrollera föregående resultat.

> **WARNING:** Denna slutpunkt är begränsad till **10 förfrågningar per minut** per anropare — striktare än den allmänna API-gränsen — eftersom varje anrop flyttar verkligt saldo.

### Begäranparametrar

| Fält | Typ | Obligatoriskt | Beskrivning | Värde |
|------|-----|---------------|-------------|-------|
| `from_currency` | string | ja | Källvaluta | `BTC`, `ETH`, `USDT`, `USDC`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `to_currency` | string | ja | Målvaluta. Måste skilja sig från `from_currency` | `USDT`, `USDC`, `BTC`, `ETH`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `amount` | decimal | ja | Belopp att konvertera, större än `0` |  |
| `amount_type` | string | ja | Vilken sida `amount` avser | `from`, `to` |

**🟢 200 OK** · `application/json`

```json
{
  "state": 0,
  "result": {
    "id": 12345,
    "type": "manual",
    "status": "completed",
    "from_currency": "BTC",
    "to_currency": "USDT",
    "from_amount": "0.01000000",
    "requested_from_amount": "0.01000000",
    "refund_amount": null,
    "to_amount": "947.86690000",
    "exchange_rate": "94786.69000000",
    "fee_amount": "0.00000000",
    "from_amount_usd": "947.87",
    "to_amount_usd": "947.87",
    "processed_at": "2026-01-20T15:30:24Z",
    "created_at": "2026-01-20T15:30:22Z"
  }
}
```

#### Svarsfält

| Fält | Typ | Beskrivning |
|------|-----|-------------|
| `id` | int | Konverteringsorder-ID tilldelat av systemet |
| `type` | string | Alltid `manual` för detta API |
| `status` | string | Aktuell status (se «Konverteringsstatusar» nedan) |
| `from_currency` | string | Källvaluta |
| `to_currency` | string | Målvaluta |
| `from_amount` | string | Debiterat belopp i `from_currency` |
| `requested_from_amount` | string \| null | Ditt ursprungligen begärda källbelopp när `amount_type = from`. `null` när `amount_type = to` |
| `refund_amount` | string \| null | Del av det förskotterade beloppet som återbetalats till dig efter en partiell utförande. `null` om ordern utfördes fullständigt |
| `to_amount` | string | Krediterat belopp i `to_currency` |
| `exchange_rate` | string | Kurs som faktiskt tillämpades på denna konvertering — 1 enhet `from_currency` i `to_currency` (inkluderar redan plattformens prissättning) |
| `fee_amount` | string | Plattformsavgift som tagits ut för denna konvertering, angiven i `from_currency` eller `to_currency` beroende på transaktionens riktning. Redan inkluderad i `exchange_rate` — visas för transparens |
| `from_amount_usd` | string \| null | USD-motsvarighet till `from_amount` |
| `to_amount_usd` | string \| null | USD-motsvarighet till `to_amount` |
| `processed_at` | string (ISO 8601) \| null | Tidpunkt då konverteringen slutförde utförandet. `null` medan den fortfarande bearbetas |
| `created_at` | string (ISO 8601) | Tidpunkt då konverteringsordern skapades |

#### Konverteringsstatusar

| Status | Beskrivning |
|--------|-------------|
| `pending` | Skapad, ännu inte skickad till marknaden |
| `processing` | Saldo låst, order placerad på marknaden |
| `completed` | Helt utförd — `to_amount` har krediterats ditt saldo |
| `failed` | Kunde inte utföras — eventuellt förskotterat belopp återbetalades automatiskt |
| `partially_completed` | Endast för valutapar utan direkt marknad (dirigerade via en mellanliggande valuta): det första steget slutfördes men det andra misslyckades. Du krediteras den mellanliggande valutan istället för `to_currency` — konvertera igen därifrån för att nå ditt ursprungliga mål |

#### Interactive request: `POST /v1/convert`
  - `from_currency` (enum, required): BTC,ETH,USDT,USDC,TRX,BNB,GRAM,SOL,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `to_currency` (enum, required): USDT,USDC,BTC,ETH,TRX,BNB,GRAM,SOL,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `amount` (decimal, required)
  - `amount_type` (enum, required): from,to

## Fel

Vid ett fel har svaret `state: 1` och en `error_code` — delad av `/v1/convert/price` och `/v1/convert`:

**🔴 422 / 400** · `application/json`

```json
{
  "state": 1,
  "error_code": "amount_too_small",
  "errors": {
    "amount": "Amount is too small for this conversion. Please increase the amount and try again."
  }
}
```

| `error_code` | HTTP-status | Beskrivning |
|--------------|-------------|-------------|
| `validation_failed` | 422 | Ogiltiga eller saknade parametrar, eller avvisning på grund av en affärsregel (t.ex. otillräckligt saldo) — se fältet `errors` för detaljer |
| `amount_too_small` | 422 | `amount` understiger den minsta handelsbara storleken för detta valutapar |
| `convert_unavailable` | 400 | Konverteringen kunde inte utföras just nu (marknadsdata otillgänglig eller ingen rutt mellan de två valutorna) — försök igen inom kort |
| `internal_error` | 400 | Oväntat internt serverfel vid bearbetning av förfrågan |

## Automatisk konvertering av inkommande betalningar

Auto-konvertering är en projektinställning för inkommande fakturor och statiska plånbokskrediter. Den konfigureras i handlarens instrumentpanel, inte genom att lägga till fält i `/v1/payment`. Varje regel väljer en eller flera källvalutor och en målvaluta.

När konverteringen är klar kan betalningsinformation och handlar-webhooks inkludera:

```json
{
  "payment_amount": "0.14800000",
  "merchant_amount": "0.146520000000000000",
  "payer_currency": "XMR",
  "convert": {
    "to_currency": "USDT",
    "commission": "0.09000000",
    "rate": "323.21000000",
    "amount": "47.262015740000000000"
  }
}
```

Beloppsområdena är avsiktligt separata:

- `payment_amount` — vad som upptäcktes på kedjan i källbetalningsvalutan;
- `merchant_amount` — nettokällbeloppet som tillfaller handlaren före konvertering;
- `convert.amount` — beloppet som krediterats i `convert.to_currency`;
- `convert.rate` och `convert.commission` — det utförda konverteringsresultatet, inte ett pris du bör räkna om lokalt.

> **WARNING:** Avsaknaden av `convert` är meningsfull: konvertering kan inte ha slutförts, kan vara ej konfigurerad för den källan, eller kan ha fallit tillbaka till kredit i källvaluta. Uppfinn aldrig ett målvärde från `/exchange-rates` eller ett offentligt marknadspris.

### Automatisk konverteringsfel och fallback

Konvertering sker efter mottagande av blockchain-betalningen. Marknadstillgänglighet, minsta orderstorlekar, precisionbegränsningar, utbytes-timeouter och otillräcklig verkställbar likviditet kan fördröja eller förhindra konvertering.

- Insättningar under global/projektminimum kringgår konverteringsflödet och krediteras i källvaluta.
- Tillfälliga fel kan försökas igen asynkront.
- Stora eller icke-handelsbara insättningar kan återgå till ett källvalutakredit efter att återförsökspolicyn är uttömd.
- En betalning kan därför vara giltig även när den önskade målvalutakonverteringen inte genomfördes.

Din integration bör först spara den verifierade betalningen, och sedan stämma av den faktiska krediterade valutan från betalningsinformationen, den valfria `convert`-blocket och handlarens saldon. Blockera inte bekräftelsen av betalningswebhooken medan du väntar på dina egna analys- eller notificationssystem.

### Automatiserade konverteringstest av godkännande

Testa åtminstone: lyckad direktkonvertering, bro-/flerstegs-konvertering, damm under minimum, tillfällig omförsök, återfall till källvaluta, underbetalning, överbetalning, duplicerat webhook, saknad `convert` och avstämning efter en tvetydig timeout.

## Manuella konverteringskantfall

- `/v1/convert/price` är en indikativ förhandsvisning; marknadsrörelser kan ändra utfallet av exekveringen.
- `amount_type: from` fixar källsidans begäran, medan `amount_type: to` begär ett målbelopp. Byt inte betydelse vid presentation av bekräftelsegränssnitt.
- Ett par utan direkt marknad kan routas genom en mellanliggande valuta. Om endast ett ben slutförs, rapporterar `partially_completed` den mellanliggande krediten.
- Om ett execute-anrop överstiger tiden, förlikna innan du försöker igen. En marknadsorder kan genomföras även när dess HTTP-svar förloras.
- Behandla `failed` som ett tillstånd att förlikna, inte som tillåtelse att göra en lokal kompensationsbalanspost; plattformen äger debet-/återbetalningsredovisningen.