> ## Documentation Index
> Fetch the complete documentation index at: https://docs.accelebit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Server-to-Server Integration Guide for Accelebit

> Complete guide for integrating Accelebit card payments from your backend. Covers payment flow, 3D Secure, error handling, and idempotency.

Accelebit is a server-to-server payment API. Your backend collects card details from the customer, sends them directly to the Accelebit API over HTTPS, and handles the response—no redirects to hosted payment pages. This guide walks through the full payment flow, including 3D Secure handling, error management, and idempotency best practices.

## Payment flow

The diagram below shows the end-to-end flow for a card payment, including the 3D Secure branch.

```mermaid theme={null}
sequenceDiagram
    participant Customer
    participant Your Server
    participant Accelebit
    participant Provider

    Customer->>Your Server: Submit payment form
    Your Server->>Accelebit: POST /v1/payments
    Accelebit->>Provider: Route to best provider
    Provider-->>Accelebit: Payment result
    Accelebit-->>Your Server: Response (captured / 3DS required)
    alt 3DS Required
        Your Server->>Customer: Redirect to 3DS URL
        Customer->>Provider: Complete 3DS challenge
        Provider->>Accelebit: 3DS callback
        Accelebit->>Your Server: Webhook (payment.captured)
    end
    Your Server->>Customer: Order confirmation
```

## Create a payment

Send card details and billing information to `POST /v1/payments`. Amounts must be decimal strings (for example, `"55.00"`). Include an `Idempotency-Key` header on every request—see [Idempotency](#idempotency) for details.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.gateway.accelebit.com/v1/payments \
    -H "Content-Type: application/json" \
    -H "X-API-Key: smtgw_sk_test_your_secret_key" \
    -H "Idempotency-Key: pay_unique_id_123" \
    -d '{
      "amount": "55.00",
      "currency": "EUR",
      "paymentMethod": "card",
      "customerId": "user_12345",
      "card": {
        "number": "4111111111111111",
        "expiryMonth": "12",
        "expiryYear": "28",
        "cvv": "123",
        "holderName": "Jane Doe"
      },
      "billing": {
        "firstName": "Jane",
        "lastName": "Doe",
        "email": "jane@example.com",
        "phone": "+35699123456",
        "country": "MT",
        "address": "123 Main Street",
        "city": "Valletta",
        "postalCode": "VLT 1000"
      },
      "returnUrl": "https://yoursite.com/payment/callback",
      "merchantRef": "order_98765"
    }'
  ```

  ```typescript Node.js / TypeScript theme={null}
  const response = await fetch('https://api.gateway.accelebit.com/v1/payments', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.ACCELEBIT_SECRET_KEY!,
      'Idempotency-Key': `pay_${crypto.randomUUID()}`,
    },
    body: JSON.stringify({
      amount: '55.00',
      currency: 'EUR',
      paymentMethod: 'card',
      customerId: 'user_12345',
      card: {
        number: '4111111111111111',
        expiryMonth: '12',
        expiryYear: '28',
        cvv: '123',
        holderName: 'Jane Doe',
      },
      billing: {
        firstName: 'Jane',
        lastName: 'Doe',
        email: 'jane@example.com',
        phone: '+35699123456',
        country: 'MT',
        address: '123 Main Street',
        city: 'Valletta',
        postalCode: 'VLT 1000',
      },
      returnUrl: 'https://yoursite.com/payment/callback',
      merchantRef: 'order_98765',
    }),
  });

  const result = await response.json();

  if (result.data.threeDsRequired) {
    // Redirect customer to 3DS URL
    console.log('3DS redirect:', result.data.threeDsData);
  } else {
    console.log('Payment status:', result.data.status);
  }
  ```

  ```python Python theme={null}
  import requests
  import uuid

  response = requests.post(
      'https://api.gateway.accelebit.com/v1/payments',
      headers={
          'Content-Type': 'application/json',
          'X-API-Key': ACCELEBIT_SECRET_KEY,
          'Idempotency-Key': f'pay_{uuid.uuid4()}',
      },
      json={
          'amount': '55.00',
          'currency': 'EUR',
          'paymentMethod': 'card',
          'customerId': 'user_12345',
          'card': {
              'number': '4111111111111111',
              'expiryMonth': '12',
              'expiryYear': '28',
              'cvv': '123',
              'holderName': 'Jane Doe',
          },
          'billing': {
              'firstName': 'Jane',
              'lastName': 'Doe',
              'email': 'jane@example.com',
              'phone': '+35699123456',
              'country': 'MT',
              'address': '123 Main Street',
              'city': 'Valletta',
              'postalCode': 'VLT 1000',
          },
          'returnUrl': 'https://yoursite.com/payment/callback',
          'merchantRef': 'order_98765',
      },
  )

  result = response.json()

  if result['data']['threeDsRequired']:
      print('3DS redirect:', result['data']['threeDsData'])
  else:
      print('Payment status:', result['data']['status'])
  ```

  ```php PHP theme={null}
  $ch = curl_init('https://api.gateway.accelebit.com/v1/payments');

  $payload = json_encode([
      'amount' => '55.00',
      'currency' => 'EUR',
      'paymentMethod' => 'card',
      'customerId' => 'user_12345',
      'card' => [
          'number' => '4111111111111111',
          'expiryMonth' => '12',
          'expiryYear' => '28',
          'cvv' => '123',
          'holderName' => 'Jane Doe',
      ],
      'billing' => [
          'firstName' => 'Jane',
          'lastName' => 'Doe',
          'email' => 'jane@example.com',
          'phone' => '+35699123456',
          'country' => 'MT',
          'address' => '123 Main Street',
          'city' => 'Valletta',
          'postalCode' => 'VLT 1000',
      ],
      'returnUrl' => 'https://yoursite.com/payment/callback',
      'merchantRef' => 'order_98765',
  ]);

  curl_setopt_array($ch, [
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => $payload,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => [
          'Content-Type: application/json',
          'X-API-Key: ' . getenv('ACCELEBIT_SECRET_KEY'),
          'Idempotency-Key: pay_' . bin2hex(random_bytes(16)),
      ],
  ]);

  $response = curl_exec($ch);
  curl_close($ch);

  $result = json_decode($response, true);

  if ($result['data']['threeDsRequired']) {
      // Redirect customer to 3DS
      $threeDsData = $result['data']['threeDsData'];
  } else {
      echo 'Payment status: ' . $result['data']['status'];
  }
  ```
</CodeGroup>

## Response handling

A successful request returns a `data` object with a `status` field. Check this field to determine what to do next.

| Status        | Meaning                                                                 |
| ------------- | ----------------------------------------------------------------------- |
| `captured`    | Payment completed successfully. Funds will be settled.                  |
| `authorized`  | Payment authorized but not yet captured (rare for direct integrations). |
| `pending_3ds` | 3D Secure authentication required. Redirect the customer.               |
| `failed`      | Payment was declined or an error occurred.                              |

## 3D Secure

When a payment requires 3D Secure, the API response includes `threeDsRequired: true` alongside a `threeDsData` object containing the redirect URL and any POST parameters needed to initiate the challenge.

```json theme={null}
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "status": "pending_3ds",
    "threeDsRequired": true,
    "threeDsData": {
      "redirectUrl": "https://provider.com/3ds/challenge?id=abc123",
      "method": "POST",
      "parameters": {
        "PaReq": "base64encodeddata...",
        "TermUrl": "https://api.gateway.accelebit.com/v1/3ds/callback/abc123"
      }
    }
  }
}
```

Handle 3DS with the following steps:

<Steps>
  <Step title="Redirect the customer">
    Send the customer's browser to `threeDsData.redirectUrl`. If the method is `POST`, submit a form to that URL with the provided `parameters`.
  </Step>

  <Step title="Customer completes the challenge">
    The customer authenticates with their bank through the 3DS challenge page.
  </Step>

  <Step title="Bank redirects back to your returnUrl">
    After the challenge, the bank redirects the customer to the `returnUrl` you specified in the original payment request.
  </Step>

  <Step title="Accelebit sends a webhook">
    Accelebit delivers a `payment.captured` or `payment.failed` webhook to your server with the final payment status.
  </Step>

  <Step title="Confirm the status server-side">
    Call `GET /v1/payments/:id` to verify the payment status before fulfilling the order.
  </Step>
</Steps>

<Warning>
  Never fulfill an order based on the `returnUrl` redirect alone. The customer can manipulate URL parameters. Always verify the payment status server-side via the API or a webhook before marking an order as paid.
</Warning>

## Error handling

When a payment fails, the API returns an `error` object alongside a `null` data field. Read `error.name` to identify the failure reason and decide whether to retry or surface an error to the customer.

```json theme={null}
{
  "data": null,
  "error": {
    "status": 400,
    "name": "CARD_DECLINED",
    "message": "The card was declined by the issuing bank"
  }
}
```

| Error code          | Description                                                             |
| ------------------- | ----------------------------------------------------------------------- |
| `CARD_DECLINED`     | The card was declined by the issuer.                                    |
| `PROVIDER_ERROR`    | The upstream provider returned an error. A retry may succeed.           |
| `INVALID_REQUEST`   | The request body is missing required fields or contains invalid values. |
| `UNAUTHORIZED`      | The API key is invalid or missing.                                      |
| `DUPLICATE_REQUEST` | The idempotency key was already used with different request parameters. |

## Idempotency

Include an `Idempotency-Key` header on every `POST` request. If a network failure causes you to retry a request with the same key, the API returns the original response without creating a duplicate payment.

```bash theme={null}
-H "Idempotency-Key: pay_unique_id_123"
```

<Tip>
  Follow these practices to get the most out of idempotency keys:

  * Use a UUID or a composite key like `order_{orderId}_attempt_{n}`.
  * Store the idempotency key alongside your order record so you can retry safely.
  * Note that keys expire after 24 hours.
</Tip>

## Merchant reference

Use the `merchantRef` field to attach your own order or invoice ID to a payment. This lets you correlate Accelebit transactions with your internal records and look up payments without storing Accelebit's transaction ID separately.

```bash theme={null}
curl "https://api.gateway.accelebit.com/v1/payments?merchantRef=order_98765" \
  -H "X-API-Key: smtgw_sk_test_your_secret_key"
```
