# Async Account Creation

The `POST /accounts` endpoint supports **asynchronous account creation** via a callback URL.

> See [Open API Spec](https://api.metacopier.io/rest/api/documentation/swagger-ui/index.html#/Account%20API/createAccount)

## How It Works

1. You send a `POST /accounts` request with a `callbackUrl` field in the body.
2. The API validates the request and returns **202 Accepted** immediately with a `requestId`.
3. The account is created in the background.
4. Once finished (success or failure), the result is **POSTed to your callback URL**.

> **Without** `callbackUrl`, the endpoint behaves exactly as before — synchronous, blocking until the account is created.

***

## Timeouts

| Mode                                              | Recommended Read Timeout     | Why                                                                                                                                             |
| ------------------------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sync** (`POST /accounts` without `callbackUrl`) | **100 seconds**              | The synchronous endpoint completes within 100 seconds. If it takes longer, the request is likely stuck.                                         |
| **Async** (`POST /accounts` with `callbackUrl`)   | **N/A**                      | The API returns `202 Accepted` instantly. The result arrives via callback — no timeout to worry about.                                          |
| **Polling** (`GET /accounts/async/{requestId}`)   | **300 seconds** (if waiting) | Async account creation includes internal retries and can take up to 300 seconds. Poll periodically until the status is `COMPLETED` or `FAILED`. |

> **Important**: The async flow internally retries broker connections and waits for system capacity, which is why it can take up to 300 seconds. This is handled entirely server-side — your client just needs to wait for the callback or poll.

***

## Quick Start

### 1. Create Account (Async)

```bash
curl -X POST https://api.metacopier.io/rest/api/backend/v1/accounts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": { "id": 1 },
    "region": { "id": 1 },
    "loginServer": "ICMarketsSC-MT5-4",
    "loginAccountNumber": "12345678",
    "loginAccountPassword": "your_password",
    "callbackUrl": "https://your-server.com/webhook/account-created"
  }'
```

### Response — 202 Accepted

```json
{
  "requestId": "acc_a1b2c3d4e5f67890",
  "message": "Account creation request accepted. The result will be POSTed to the provided callback URL.",
  "callbackUrl": "https://your-server.com/webhook/account-created",
  "status": "QUEUED"
}
```

***

## Callback Payload

When the account creation completes, a **POST** request is sent to your `callbackUrl`.

### On Success

```json
{
  "requestId": "acc_a1b2c3d4e5f67890",
  "success": true,
  "account": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "type": { "id": 1, "name": "MT5" },
    "region": { "id": 1, "name": "New York" },
    "loginServer": "ICMarketsSC-MT5-4",
    "loginAccountNumber": "12345678",
    "accountInformation": {
      "connected": true
    }
  },
  "error": null
}
```

### On Failure

```json
{
  "requestId": "acc_a1b2c3d4e5f67890",
  "success": false,
  "account": null,
  "error": "[WRONG_CREDENTIALS]"
}
```

### Callback Headers

| Header         | Description                     |
| -------------- | ------------------------------- |
| `Content-Type` | `application/json`              |
| `X-Request-Id` | The `requestId` for correlation |

### Retry Policy

If your callback endpoint is unavailable, the request is retried:

* **3 attempts** total
* **Backoff**: 2 seconds after attempt 1, 4 seconds after attempt 2
* Each retry uses a **different IP address** (rotating proxy)

***

## Polling (Optional)

You can also poll for status instead of (or in addition to) using callbacks.

### Get Status of a Single Request

```bash
curl https://api.metacopier.io/rest/api/backend/v1/accounts/async/acc_a1b2c3d4e5f67890 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "requestId": "acc_a1b2c3d4e5f67890",
  "status": "COMPLETED",
  "account": { ... },
  "error": null
}
```

### Get All Async Requests

```bash
curl https://api.metacopier.io/rest/api/backend/v1/accounts/async \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns an array of all tracked async requests for your project.

***

## Status Lifecycle

| Status       | Description                                             |
| ------------ | ------------------------------------------------------- |
| `QUEUED`     | Request accepted, waiting to be processed               |
| `PROCESSING` | Account is currently being created                      |
| `COMPLETED`  | Account created successfully (includes `account` field) |
| `FAILED`     | Account creation failed (includes `error` field)        |

> Statuses are retained for **1 hour** after completion, then automatically removed.

***

## Processing Rules

* **Sequential per project**: Only 1 account creation runs at a time per project. Additional requests are queued and processed in order.

***

## Callback URL Requirements

| Rule         | Details                                             |
| ------------ | --------------------------------------------------- |
| **Protocol** | `https://` or `http://`                             |
| **Format**   | Must be a valid URL                                 |
| **Method**   | Your endpoint must accept `POST` requests           |
| **Response** | Return any `2xx` status code to acknowledge receipt |

If the URL is invalid, the API returns `400 Bad Request` with one of:

* `[CALLBACK_URL_REQUIRED]` — field is present but empty
* `[CALLBACK_URL_INVALID]` — malformed URL
* `[CALLBACK_URL_INVALID_PROTOCOL]` — protocol is not http/https

***

## Error Codes

All standard `POST /accounts` errors apply. These are returned synchronously (before the 202) if validation fails:

| Error                                            | HTTP Status | Description                         |
| ------------------------------------------------ | ----------- | ----------------------------------- |
| `[CALLBACK_URL_INVALID]`                         | 400         | Malformed callback URL              |
| `[CALLBACK_URL_INVALID_PROTOCOL]`                | 400         | Callback URL must use http or https |
| `[REGION_NOT_FOUND]`                             | 404         | Invalid region ID                   |
| `[ACCOUNT_TYPE_NOT_FOUND]`                       | 404         | Invalid account type ID             |
| `[ACCOUNT_LEVEL_API_KEY_CANNOT_CREATE_ACCOUNTS]` | 403         | Must use a project-level API key    |

Errors that occur **during** async processing are delivered via the callback payload and the polling endpoint (status = `FAILED`).

***

## Example: Node.js Callback Server

```javascript
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhook/account-created', (req, res) => {
  const { requestId, success, account, error } = req.body;

  if (success) {
    console.log(`Account created: ${account.id} (request: ${requestId})`);
    // Store the account, update your database, etc.
  } else {
    console.error(`Account creation failed: ${error} (request: ${requestId})`);
    // Handle the error, notify your user, etc.
  }

  res.status(200).send('OK');
});

app.listen(3000);
```
