# مفاتيح API الخاصة بك

مفاتيح الاختبار ومفاتيح الوضع المباشر، السرية والقابلة للنشر، وأول طلب مصادَق عليه ترسله.

يحمل كل طلب إلى واجهة API لدى AdProMaxPay مفتاحًا. يخبر المفتاح الواجهة بمؤسستك وبالوضع الذي تعمل
فيه: وضع الاختبار أو الوضع المباشر.

## أنواع المفاتيح الأربعة

| البادئة         | النوع      | الوضع    |
| --------------- | ---------- | -------- |
| `apx_sk_test_…` | سري        | الاختبار |
| `apx_pk_test_…` | قابل للنشر | الاختبار |
| `apx_sk_live_…` | سري        | المباشر  |
| `apx_pk_live_…` | قابل للنشر | المباشر  |

* **المفتاح السري** يتصرف باسم مؤسستك كلها. مكانه خادمك، لا صفحة ويب ولا تطبيق
  أبدًا.
* **المفتاح القابل للنشر** مصمم ليوضع في صفحة ويب أو تطبيق. وحاليًا يطلب كل مسار في API مفتاحًا
  سريًا.
* **مفاتيح الاختبار** تعمل فور إنشائها. و**مفاتيح الوضع المباشر** تعمل بعد تفعيل حسابك.

لا ينشئ AdProMaxPay أي مفتاح بدلًا منك. تنشئ مفاتيح الاختبار من صفحة مفاتيح API في لوحة التحكم، بعد
التحقق من بريدك الإلكتروني، ولا يُعرض المفتاح السري إلا مرة واحدة، عند إنشائه: احفظه حينها.

## أرسل طلبك الأول

ضع مفتاحك السري للاختبار في متغير بيئة، ثم اسأل API من أنت. أرسل المفتاح كرمز Bearer، أو كاسم
المستخدم في مصادقة HTTP Basic مع كلمة مرور فارغة.

الاستجابة هي حسابك: معرّفه، وحالة تفعيله (`sandbox` إلى حين التفعيل)، وإصدار API الذي
يستخدمه.

```bash
curl https://pay-api.adpromax.com/v1/account \
  -u "$APX_SECRET_KEY:"
```

```js title="account.mjs"
const response = await fetch('https://pay-api.adpromax.com/v1/account', {
  headers: { Authorization: `Bearer ${process.env.APX_SECRET_KEY}` },
})
const account = await response.json()
if (!response.ok)
  throw new Error(account.error.message)
console.log(account.id, account.activation_status)
```

```ts title="account.ts"
interface Account {
  id: string
  object: 'account'
  business_name: string
  activation_status: string
  api_version: string
}

interface ApiError {
  error: { type: string, code: string, message: string, request_id: string }
}

const response = await fetch('https://pay-api.adpromax.com/v1/account', {
  headers: { Authorization: `Bearer ${process.env.APX_SECRET_KEY}` },
})
if (!response.ok) {
  const { error } = (await response.json()) as ApiError
  throw new Error(`${error.code}: ${error.message}`)
}
const account = (await response.json()) as Account
console.log(account.id, account.activation_status)
```

```python title="account.py"
import os

import requests

response = requests.get(
    "https://pay-api.adpromax.com/v1/account",
    auth=(os.environ["APX_SECRET_KEY"], ""),
)
account = response.json()
if not response.ok:
    raise RuntimeError(account["error"]["message"])
print(account["id"], account["activation_status"])
```

```php title="account.php"
<?php
$ch = curl_init('https://pay-api.adpromax.com/v1/account');
curl_setopt_array($ch, [
    CURLOPT_USERPWD => getenv('APX_SECRET_KEY') . ':',
    CURLOPT_RETURNTRANSFER => true,
]);
$account = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) {
    throw new RuntimeException($account['error']['message']);
}
echo $account['id'], ' ', $account['activation_status'], PHP_EOL;
```

```ruby title="account.rb"
require 'json'
require 'net/http'

uri = URI('https://pay-api.adpromax.com/v1/account')
request = Net::HTTP::Get.new(uri)
request.basic_auth(ENV.fetch('APX_SECRET_KEY'), '')

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(request)
end
account = JSON.parse(response.body)
raise account.dig('error', 'message') unless response.is_a?(Net::HTTPSuccess)

puts "#{account['id']} #{account['activation_status']}"
```

```go title="account.go"
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

type Account struct {
	ID               string `json:"id"`
	BusinessName     string `json:"business_name"`
	ActivationStatus string `json:"activation_status"`
	APIVersion       string `json:"api_version"`
}

type APIError struct {
	Error struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"error"`
}

func main() {
	req, err := http.NewRequest(http.MethodGet, "https://pay-api.adpromax.com/v1/account", nil)
	if err != nil {
		log.Fatal(err)
	}
	req.SetBasicAuth(os.Getenv("APX_SECRET_KEY"), "")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()

	if res.StatusCode >= 400 {
		var apiErr APIError
		json.NewDecoder(res.Body).Decode(&apiErr)
		log.Fatal(apiErr.Error.Message)
	}
	var account Account
	if err := json.NewDecoder(res.Body).Decode(&account); err != nil {
		log.Fatal(err)
	}
	fmt.Println(account.ID, account.ActivationStatus)
}
```

```java title="Account.java"
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Account {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://pay-api.adpromax.com/v1/account"))
            .header("Authorization", "Bearer " + System.getenv("APX_SECRET_KEY"))
            .GET()
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            throw new IllegalStateException(response.body());
        }
        // The account as JSON: read it with your JSON library (Jackson, Gson…).
        System.out.println(response.body());
    }
}
```

```csharp title="Account.cs"
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;

var json = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("APX_SECRET_KEY"));

using var response = await http.GetAsync("https://pay-api.adpromax.com/v1/account");
if (!response.IsSuccessStatusCode)
{
    var failure = await response.Content.ReadFromJsonAsync<ApiError>(json);
    throw new InvalidOperationException(failure?.Error.Message);
}
var account = await response.Content.ReadFromJsonAsync<Account>(json);
Console.WriteLine($"{account!.Id} {account.ActivationStatus}");

record Account(string Id, string BusinessName, string ActivationStatus, string ApiVersion);
record ApiError(ApiErrorBody Error);
record ApiErrorBody(string Code, string Message);
```

```rust title="main.rs"
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
//             serde = { version = "1", features = ["derive"] }
use serde::Deserialize;

#[derive(Deserialize)]
struct Account {
    id: String,
    activation_status: String,
}

#[derive(Deserialize)]
struct ApiError {
    error: ErrorBody,
}

#[derive(Deserialize)]
struct ErrorBody {
    message: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let response = reqwest::blocking::Client::new()
        .get("https://pay-api.adpromax.com/v1/account")
        .bearer_auth(std::env::var("APX_SECRET_KEY")?)
        .send()?;
    if !response.status().is_success() {
        let failure: ApiError = response.json()?;
        return Err(failure.error.message.into());
    }
    let account: Account = response.json()?;
    println!("{} {}", account.id, account.activation_status);
    Ok(())
}
```

```json title="200 OK" response
{
  "id": "org_01k7cz9q3m8v6t2x4b5n7p1r0s",
  "object": "account",
  "business_name": "Atlas Shop",
  "country": "MA",
  "default_currency": "mad",
  "activation_status": "sandbox",
  "capabilities": {
    "card_payments": "inactive",
    "cash_payments": "inactive"
  },
  "api_version": "2026-11-01",
  "created": 1790847000
}
```

## عندما يُرفض مفتاح

تجيب واجهة API بـ `401` أو `403` مع كائن خطأ؛ ويوضح حقله `code` السبب.

| الحالة | `code`                    | ما حدث                                                               |
| ------ | ------------------------- | -------------------------------------------------------------------- |
| 401    | `api_key_missing`         | لم يحمل الطلب أي مفتاح.                                              |
| 401    | `api_key_invalid`         | المفتاح غير موجود. تحقّق من عدم نقصان أي حرف.                        |
| 401    | `api_key_revoked`         | أُبطل المفتاح. استخدم مفتاحًا آخر.                                   |
| 401    | `api_key_expired`         | جُدِّد المفتاح وانتهت فترة التداخل الخاصة به. استخدم المفتاح الجديد. |
| 403    | `secret_key_required`     | استُخدم مفتاح قابل للنشر حيث يلزم مفتاح سري.                         |
| 403    | `account_inactive`        | الحساب موقوف أو مغلق.                                                |
| 403    | `live_mode_not_activated` | استُخدم مفتاح للوضع المباشر قبل تفعيل الحساب.                        |

يشرح حقل `message` الخطأ بلغة طلبك، ويحدد `request_id` الطلب إذا راسلت
الدعم.

## حافظ على سرية المفاتيح السرية

* اقرأ المفتاح من متغير بيئة أو من مخزن أسرار؛ ولا تودعه أبدًا في مستودع كود.
* لا تضع مفتاحًا سريًا أبدًا في صفحة ويب أو تطبيق جوال أو تذكرة دعم.
* إذا احتُمل تسرّب مفتاح سري، فأبطِله من لوحة التحكم وأنشئ مفتاحًا جديدًا.

التجديد والإبطال وغيرهما: [الأمان](https://pay-docs.adpromax.com/ar/account/security).
