# Convert API

> แปลงสกุลเงินคริปโตโดยตรงจากยอดคงเหลือของร้านค้าคุณ — รับราคาแบบเรียลไทม์และดำเนินการที่ราคาตลาด

Convert API ช่วยให้คุณแลกเปลี่ยนระหว่างสกุลเงินที่อยู่ในยอดคงเหลือของร้านค้าได้ที่ราคาตลาดปัจจุบัน — เอนจินเดียวกับที่ขับเคลื่อนแท็บ **Swap** ในแดชบอร์ดร้านค้า ตอนนี้สามารถเรียกใช้ได้จากแบ็กเอนด์ของคุณ

> **WARNING:** เอนด์พอยต์ Convert จะเซ็นด้วย **API key ปกติ** ของคุณ — ตัวเดียวกับที่ใช้สำหรับคำขอ [Payment API](/docs/payments) **ไม่ใช่** Payout API key การดำเนินการแปลงสกุลเงินจะหักและเพิ่มยอดคงเหลือร้านค้าของคุณทันที ดังนั้นควรดูแล key นี้ด้วยความระมัดระวังเช่นเดียวกับข้อมูลรับรองใด ๆ ที่เคลื่อนย้ายเงิน

## รับราคาการแปลงสกุลเงิน

ส่งคืนราคาโดยประมาณสำหรับการแปลงสกุลเงินที่ราคาตลาดปัจจุบัน — อัตราที่มีผลจริงและจำนวนเงินที่ได้ ไม่มีการหักเงินหรือสำรองใด ๆ เรียกใช้ได้บ่อยเท่าที่ต้องการก่อนดำเนินการจริง

`POST /v1/convert/price`

### พารามิเตอร์คำขอ

| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย | ค่า |
|-------|--------|--------|----------|-----|
| `from_currency` | string | ใช่ | สกุลเงินต้นทาง | `BTC`, `ETH`, `USDT`, `USDC`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `to_currency` | string | ใช่ | สกุลเงินปลายทาง ต้องแตกต่างจาก `from_currency` | `USDT`, `USDC`, `BTC`, `ETH`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `amount` | decimal | ใช่ | จำนวนเงินที่จะแปลง ต้องมากกว่า `0` |  |
| `amount_type` | string | ใช่ | `amount` หมายถึงฝั่งใด | `from`, `to` |

> **INFO:** `amount_type=from` ใช้จ่าย `amount` ใน `from_currency` พอดี ส่วน `amount_type=to` ได้รับ `amount` ใน `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"
  }
}
```

#### ฟิลด์การตอบกลับ

| ฟิลด์ | ประเภท | คำอธิบาย |
|-------|--------|----------|
| `success` | boolean | ราคานี้คำนวณสำเร็จหรือไม่ |
| `from_currency` | string | สกุลเงินต้นทาง |
| `to_currency` | string | สกุลเงินปลายทาง |
| `amount_type` | string | สะท้อน `amount_type` จากคำขอ |
| `from_amount` | string | จำนวนที่จะถูกหักในสกุล `from_currency` |
| `to_amount` | string | จำนวนที่จะถูกเพิ่มในสกุล `to_currency` |
| `effective_rate` | string | อัตราที่ใช้กับราคานี้ — 1 หน่วยของ `from_currency` เทียบเป็น `to_currency` (รวมราคาของแพลตฟอร์มไว้แล้ว) |
| `from_amount_usd` | string \| null | มูลค่าเทียบเท่าดอลลาร์สหรัฐของ `from_amount` |
| `to_amount_usd` | string \| null | มูลค่าเทียบเท่าดอลลาร์สหรัฐของ `to_amount` |

- ราคานี้เป็น**เพียงการประมาณการเท่านั้น** — ราคาตลาดอาจเปลี่ยนแปลงระหว่างการขอราคาและการเรียกดำเนินการจริง
- การเรียกนี้ไม่หักหรือสำรองยอดคงเหลือใด ๆ

> 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

## ดำเนินการแปลงสกุลเงิน

ดำเนินการแปลงสกุลเงินที่ราคาตลาดปัจจุบันและอัปเดตยอดคงเหลือร้านค้าของคุณ ไม่มีขั้นตอนแยกต่างหากในการ "ยืนยันราคา" — เรียกเอนด์พอยต์นี้โดยตรงพร้อมจำนวนเงินที่ต้องการแปลง

`POST /v1/convert`

> **INFO:** **Idempotency** การส่งคำขอเดียวกันทุกประการซ้ำ (`from_currency`, `to_currency`, `amount`, `amount_type` เดียวกัน) ภายในประมาณหนึ่งนาทีหลังการเรียกครั้งแรก จะส่งคืนการแปลงสกุลเงินเดิมแทนที่จะสร้างครั้งที่สอง หลังจากช่วงเวลานี้ผ่านไป คำขอที่เหมือนกันจะถูกถือว่าเป็นการแปลงสกุลเงินใหม่ — อย่าลองใหม่โดยไม่ตรวจสอบผลลัพธ์ก่อนหน้าเมื่อเกิด timeout

> **WARNING:** เอนด์พอยต์นี้จำกัดไว้ที่ **10 คำขอต่อนาที** ต่อผู้เรียก — เข้มงวดกว่าขีดจำกัด API ทั่วไป — เพราะทุกการเรียกจะเคลื่อนย้ายยอดเงินจริง

### พารามิเตอร์คำขอ

| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย | ค่า |
|-------|--------|--------|----------|-----|
| `from_currency` | string | ใช่ | สกุลเงินต้นทาง | `BTC`, `ETH`, `USDT`, `USDC`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `to_currency` | string | ใช่ | สกุลเงินปลายทาง ต้องแตกต่างจาก `from_currency` | `USDT`, `USDC`, `BTC`, `ETH`, `TRX`, `BNB`, `GRAM`, `SOL`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `amount` | decimal | ใช่ | จำนวนเงินที่จะแปลง ต้องมากกว่า `0` |  |
| `amount_type` | string | ใช่ | `amount` หมายถึงฝั่งใด | `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"
  }
}
```

#### ฟิลด์การตอบกลับ

| ฟิลด์ | ประเภท | คำอธิบาย |
|-------|--------|----------|
| `id` | int | ID คำสั่งแปลงสกุลเงินที่ระบบกำหนดให้ |
| `type` | string | เป็น `manual` เสมอสำหรับ API นี้ |
| `status` | string | สถานะปัจจุบัน (ดู «สถานะการแปลงสกุลเงิน» ด้านล่าง) |
| `from_currency` | string | สกุลเงินต้นทาง |
| `to_currency` | string | สกุลเงินปลายทาง |
| `from_amount` | string | จำนวนที่หักในสกุล `from_currency` |
| `requested_from_amount` | string \| null | จำนวนต้นทางที่คุณร้องขอไว้เดิมเมื่อ `amount_type = from` เป็น `null` เมื่อ `amount_type = to` |
| `refund_amount` | string \| null | ส่วนหนึ่งของจำนวนที่หักไว้ล่วงหน้าซึ่งคืนให้คุณหลังการดำเนินการบางส่วน เป็น `null` หากคำสั่งดำเนินการสำเร็จเต็มจำนวน |
| `to_amount` | string | จำนวนที่เพิ่มในสกุล `to_currency` |
| `exchange_rate` | string | อัตราที่ใช้จริงกับการแปลงสกุลเงินนี้ — 1 หน่วยของ `from_currency` เทียบเป็น `to_currency` (รวมราคาของแพลตฟอร์มไว้แล้ว) |
| `fee_amount` | string | ค่าธรรมเนียมแพลตฟอร์มที่เรียกเก็บสำหรับการแปลงสกุลเงินนี้ แสดงในสกุล `from_currency` หรือ `to_currency` ขึ้นอยู่กับทิศทางของธุรกรรม สะท้อนอยู่ใน `exchange_rate` แล้ว — แสดงเพื่อความโปร่งใส |
| `from_amount_usd` | string \| null | มูลค่าเทียบเท่าดอลลาร์สหรัฐของ `from_amount` |
| `to_amount_usd` | string \| null | มูลค่าเทียบเท่าดอลลาร์สหรัฐของ `to_amount` |
| `processed_at` | string (ISO 8601) \| null | เวลาที่การแปลงสกุลเงินดำเนินการเสร็จสิ้น เป็น `null` ขณะยังดำเนินการอยู่ |
| `created_at` | string (ISO 8601) | เวลาที่สร้างคำสั่งแปลงสกุลเงิน |

#### สถานะการแปลงสกุลเงิน

| สถานะ | คำอธิบาย |
|-------|----------|
| `pending` | สร้างแล้ว ยังไม่ได้ส่งไปยังตลาด |
| `processing` | ยอดคงเหลือถูกล็อกและวางคำสั่งในตลาดแล้ว |
| `completed` | ดำเนินการสำเร็จเต็มจำนวน — `to_amount` ถูกเพิ่มเข้ายอดคงเหลือของคุณแล้ว |
| `failed` | ไม่สามารถดำเนินการได้ — จำนวนที่หักไว้ล่วงหน้าถูกคืนโดยอัตโนมัติ |
| `partially_completed` | ใช้เฉพาะคู่สกุลเงินที่ไม่มีตลาดโดยตรง (ผ่านสกุลเงินตัวกลาง): ขั้นตอนแรกสำเร็จแต่ขั้นตอนที่สองล้มเหลว คุณจะได้รับสกุลเงินตัวกลางแทน `to_currency` — แปลงอีกครั้งจากตรงนั้นเพื่อให้ถึงเป้าหมายเดิม |

#### 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

## ข้อผิดพลาด

เมื่อล้มเหลว การตอบกลับจะมี `state: 1` และ `error_code` — ใช้ร่วมกันระหว่าง `/v1/convert/price` และ `/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 | คำอธิบาย |
|--------------|------------|----------|
| `validation_failed` | 422 | พารามิเตอร์ไม่ถูกต้องหรือขาดหาย หรือถูกปฏิเสธตามกฎธุรกิจ (เช่น ยอดคงเหลือไม่เพียงพอ) — ดูรายละเอียดในฟิลด์ `errors` |
| `amount_too_small` | 422 | `amount` ต่ำกว่าขนาดขั้นต่ำที่ซื้อขายได้สำหรับคู่สกุลเงินนี้ |
| `convert_unavailable` | 400 | ไม่สามารถดำเนินการแปลงสกุลเงินได้ในขณะนี้ (ข้อมูลตลาดไม่พร้อมใช้งานหรือไม่มีเส้นทางระหว่างสองสกุลเงิน) — โปรดลองใหม่อีกครั้งในไม่ช้า |
| `internal_error` | 400 | เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์ที่ไม่คาดคิดขณะประมวลผลคำขอ |

## การแปลงอัตโนมัติของการชำระเงินที่เข้ามา

การแปลงอัตโนมัติเป็นการตั้งค่าโปรเจกต์สำหรับใบแจ้งหนี้ที่เข้ามาและเครดิตวอลเล็ตคงที่ ซึ่งสามารถกำหนดค่าได้ในแดชบอร์ดผู้ขาย ไม่ใช่โดยการเพิ่มฟิลด์ไปที่ `/v1/payment` กฎแต่ละข้อจะเลือกสกุลเงินต้นทางหนึ่งหรือมากกว่าและสกุลเงินเป้าหมาย

เมื่อการแปลงเสร็จสิ้น ข้อมูลการชำระเงินและเว็บฮุกของผู้ขายสามารถรวมถึง:

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

โดเมนจำนวนเงินถูกแยกอย่างตั้งใจ:

- `payment_amount` — สิ่งที่ตรวจพบบนเชนในสกุลเงินการชำระเงินต้นทาง;
- `merchant_amount` — จำนวนสุทธิของต้นทางที่สามารถระบุให้กับผู้ขายก่อนการแปลง;
- `convert.amount` — จำนวนที่ถูกเครดิตใน `convert.to_currency`;
- `convert.rate` และ `convert.commission` — ผลลัพธ์การแปลงที่ดำเนินการแล้ว ไม่ใช่ราคาที่คุณควรคำนวณซ้ำในเครื่องของคุณ

> **WARNING:** การไม่มี `convert` มีความหมาย: การแปลงอาจยังไม่เสร็จสมบูรณ์ อาจไม่ได้ตั้งค่าสำหรับแหล่งข้อมูลนั้น หรืออาจกลับไปใช้เครดิตในสกุลเงินต้นทาง อย่าสร้างจำนวนเป้าหมายจาก `/exchange-rates` หรือราคาตลาดสาธารณะโดยเด็ดขาด

### การแปลงอัตโนมัติล้มเหลวและย้อนกลับ

การแปลงเกิดขึ้นหลังจากรับการชำระเงินผ่านบล็อกเชน ความพร้อมของตลาด ขนาดคำสั่งขั้นต่ำ ข้อจำกัดความแม่นยำ การหมดเวลาในการแลกเปลี่ยน และสภาพคล่องที่ไม่เพียงพอ สามารถทำให้การแปลงล่าช้าหรือไม่สามารถทำได้

- เงินฝากที่ต่ำกว่าค่าเงินขั้นต่ำของโครงการ/ทั่วโลก จะข้ามกระบวนการแปลงและให้เครดิตในสกุลเงินต้นทาง
- ความล้มเหลวชั่วคราวสามารถลองใหม่แบบอะซิงโครนัสได้
- เงินฝากขนาดใหญ่หรือที่ไม่สามารถซื้อขายได้สามารถกลับไปสู่เครดิตสกุลเงินต้นทางได้หลังจากที่นโยบายการลองใหม่หมดลง
- ดังนั้นการชำระเงินจึงสามารถถูกต้องได้แม้ว่าการแปลงเป็นสกุลเงินเป้าหมายที่ต้องการจะไม่เกิดขึ้น

การรวมของคุณควรบันทึกการชำระเงินที่ได้รับการตรวจสอบก่อน จากนั้นปรับยอดสกุลเงินจริงจากข้อมูลการชำระเงิน บล็อก `convert` ที่เป็นทางเลือก และยอดคงเหลือของผู้ขาย อย่าขัดขวางการรับทราบ webhoook การชำระเงินในขณะรอระบบวิเคราะห์หรือการแจ้งเตือนของคุณเอง

### การทดสอบการยอมรับการแปลงอัตโนมัติ

ทดสอบอย่างน้อย: การแปลงตรงที่สำเร็จ, การแปลงผ่านสะพาน/หลายขั้น, ฝุ่นต่ำกว่าขั้นต่ำ, การลองใหม่ชั่วคราว, การย้อนกลับไปยังสกุลเงินต้นทาง, การชำระเงินไม่เต็ม, การชำระเงินเกิน, เว็บฮุคซ้ำ, `convert` หายไป, และการปรับยอดหลังจากหมดเวลาไม่แน่นอน

## กรณีขอบเขตการแปลงด้วยตนเอง

- `/v1/convert/price` เป็นตัวอย่างพรีวิว; การเคลื่อนไหวของตลาดสามารถเปลี่ยนผลลัพธ์การดำเนินการได้
- `amount_type: from` แก้ไขคำขอทางฝั่งต้นทาง ขณะที่ `amount_type: to` ขอจำนวนทางฝั่งเป้าหมาย อย่าสลับความหมายเมื่อแสดง UI ยืนยัน
- คู่สกุลเงินที่ไม่มีตลาดตรงสามารถเดินทางผ่านสกุลเงินกลาง หากมีเพียงขาคู่เดียวที่เสร็จ `partially_completed` รายงานเครดิตกลาง
- หากการเรียกใช้งาน execute หมดเวลา ให้ทำการปรับสมดุลก่อนลองใหม่ คำสั่งซื้อขายแบบตลาดสามารถดำเนินการได้แม้ว่าการตอบสนอง HTTP ของมันจะหายไป
- พิจารณา `failed` เป็นสถานะที่ต้องปรับสมดุล ไม่ใช่สิทธิ์ในการบันทึกยอดคงเหลือชดเชยภายในเครื่อง; แพลตฟอร์มเป็นเจ้าของบัญชีเดบิต/คืนเงิน