PHPackages                             oyi77/metaapi-cloud-php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. oyi77/metaapi-cloud-php-sdk

ActiveLibrary[API Development](/categories/api)

oyi77/metaapi-cloud-php-sdk
===========================

PHP SDK for MetaApi, a professional cloud forex API

2.1.0(5mo ago)022MITPHPPHP ^8.1|^8.2

Since Dec 13Pushed 5mo agoCompare

[ Source](https://github.com/oyi77/metaapi-cloud-php-sdk)[ Packagist](https://packagist.org/packages/oyi77/metaapi-cloud-php-sdk)[ Docs](https://github.com/oyi77/metaapi-cloud-php-sdk)[ RSS](/packages/oyi77-metaapi-cloud-php-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (2)Used By (0)

Metaapi PHP SDK
===============

[](#metaapi-php-sdk)

A PHP Package that let you seamlessly perform API calls to MetaApi

This SDK provides access to:

- Account Management API
- CopyFactory (Copy Trading) API
- MetaStats (Trading Statistics) API
- Provisioning Profile API
- Token Management API
- Risk Management API

Installation
------------

[](#installation)

To install the SDK in your project you need to install the package via composer:

```
composer require oyi77/metaapi-cloud-php-sdk
```

Usage
-----

[](#usage)

MetaApi Websocket (RPC &amp; Real-time streaming)
-------------------------------------------------

[](#metaapi-websocket-rpc--real-time-streaming)

This SDK now includes a minimal Socket.IO-based websocket client for **MetaApi RPC API** and **MetaApi real-time streaming API** (see the guideline docs in `guideline/` and the official websocket docs on `metaapi.cloud`).

### RPC Connection (Request/Response)

[](#rpc-connection-requestresponse)

```
use Oyi77\MetaapiCloudPhpSdk\MetaApi\MetaApi;

$token = 'AUTH_TOKEN';
$accountId = 'ACCOUNT_ID';

$metaApi = new MetaApi($token, ['region' => 'new-york']);

// RPC connection for query-and-response workflows
$rpc = $metaApi->rpcConnection($accountId);
$rpc->connect();
$rpc->waitSynchronized();

// Query terminal state
$accountInfo = $rpc->getAccountInformation();
$positions = $rpc->getPositions();
$symbols = $rpc->getSymbols();
$serverTime = $rpc->getServerTime();

// Calculate margin
$marginInfo = $rpc->calculateMargin([
    'symbol' => 'GBPUSD',
    'type' => 'ORDER_TYPE_BUY',
    'volume' => 0.1,
    'openPrice' => 1.25,
]);

// Execute trades with convenience methods
$result = $rpc->createMarketBuyOrder('EURUSD', 0.01, 1.0900, 1.1100, [
    'comment' => 'Trade from PHP',
    'clientId' => 'php_' . time(),
    'trailingStopLoss' => [
        'distance' => ['distance' => 50, 'units' => 'RELATIVE_POINTS'],
    ],
]);

$rpc->close();
```

### Streaming Connection (Continuous Synchronization)

[](#streaming-connection-continuous-synchronization)

```
use Oyi77\MetaapiCloudPhpSdk\MetaApi\MetaApi;
use Oyi77\MetaapiCloudPhpSdk\MetaApi\Streaming\SynchronizationListener;

// Streaming connection for real-time updates
$stream = $metaApi->streamingConnection($accountId);

// Add typed listener for market data events
class MyListener implements SynchronizationListener {
    public function onSymbolPriceUpdated(int $instanceIndex, array $price): void {
        echo "Price update: {$price['symbol']} bid={$price['bid']} ask={$price['ask']}\n";
    }

    public function onCandlesUpdated(int $instanceIndex, array $candles, ?float $equity = null, ?float $margin = null, ?float $freeMargin = null, ?float $marginLevel = null): void {
        // Handle candle updates
    }

    // Implement other methods as needed (ticks, books, positions, orders, etc.)
    public function onTicksUpdated(...$args): void {}
    public function onBooksUpdated(...$args): void {}
    public function onSubscriptionDowngraded(...$args): void {}
    public function onPositionsUpdated(...$args): void {}
    public function onOrdersUpdated(...$args): void {}
    public function onHistoryOrdersUpdated(...$args): void {}
    public function onDealsUpdated(...$args): void {}
}

$stream->addTypedSynchronizationListener(new MyListener());
$stream->connect();
$stream->waitSynchronized();

// Subscribe to market data
$stream->subscribeToMarketData('EURUSD', [
    ['type' => 'quotes', 'intervalInMilliseconds' => 5000],
    ['type' => 'candles', 'timeframe' => '1m'],
    ['type' => 'ticks'],
]);

// Access cached terminal state
$price = $stream->terminalState->price('EURUSD');
$spec = $stream->terminalState->specification('EURUSD');
$accountInfo = $stream->terminalState->accountInformation;
$positions = $stream->terminalState->positions;

// Access history storage
$historyOrders = $stream->historyStorage->getHistoryOrders();
$deals = $stream->historyStorage->getDeals();

// Poll for events
while (true) {
    $stream->poll(0.25);
}

$stream->close();
```

### Examples

[](#examples)

For complete working examples, see the [`examples/`](examples/) directory:

**MetaApi Examples:**

- [`examples/metaapi/rpc_example.php`](examples/metaapi/rpc_example.php) - RPC connection usage
- [`examples/metaapi/streaming_example.php`](examples/metaapi/streaming_example.php) - Streaming with typed listeners
- [`examples/metaapi/historical_data_example.php`](examples/metaapi/historical_data_example.php) - Historical candles and ticks

**CopyFactory Examples:**

- [`examples/copyfactory/copy_trade_example.php`](examples/copyfactory/copy_trade_example.php) - CopyFactory strategy setup
- [`examples/copyfactory/webhooks_example.php`](examples/copyfactory/webhooks_example.php) - Webhook CRUD operations

**Risk Management Examples:**

- [`examples/risk_management/equity_tracking_example.php`](examples/risk_management/equity_tracking_example.php) - Equity tracker CRUD

Account Management
------------------

[](#account-management)

You can create an instance of the SDK like so for Account Management:

```
use Oyi77\MetaapiCloudPhpSdk\AccountApi;

$account = new AccountApi('AUTH_TOKEN');
```

All methods throws exceptions when the request is not successful, so be sure to put your code in a try and catch block.

```
 when statusCode >= 200 && statusCode < 300;
```

You can add a trading account and starts a cloud API server for the trading account like so:

```
try {
    return $account->create([
        "login" => "123456",
        "password" => "password",
        "name" => "testAccount",
        "server" => "ICMarketsSC-Demo",
        "platform" => "mt5",
        "magic" => 123456
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

if the request was successful , you will get the the account id and state, else an Exception will be thrown

```
    [
        "id" => "1eda642a-a9a3-457c-99af-3bc5e8d5c4c9",
        "state" => "DEPLOYED"
    ]
```

You can read an account by the id

```
try {
     return $account->readById("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

You can read all trading accounts in your metaapi account

```
try {
    // Using the legacy method (deprecated)
    return $account->readAll();

    // Using infinite scroll pagination (recommended)
    return $account->readAllWithInfiniteScroll([
        'limit' => 10,
        'offset' => 0,
        'query' => 'ICMarketsSC-MT5',
        'state' => ['DEPLOYED']
    ]);

    // Using classic pagination (returns count for page calculation)
    $result = $account->readAllWithClassicPagination([
        'limit' => 10,
        'offset' => 0
    ]);
    // $result['items'] contains accounts
    // $result['count'] contains total count
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

You can update an account

```
try {
    return  $account->update("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9",[
        "password" => "password",
        "name" => "testAccount",
        "server" => "ICMarketsSC-Demo",
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Undeploy an account

```
try {
    return $account->unDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
    // you can pass other parameters
    return $account->unDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", false);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Deploy an account

```
try {
    return $account->deploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
     // you can pass other parameters
    return $account->deploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", false);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Redeploy an account

```
try {
    return $account->reDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
     // you can pass other parameters
    return $account->reDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", false);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Delete an account

```
try {
    return $account->delete("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
     // you can pass other parameters
    return $account->delete("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", true);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Create configuration link for end-user account setup

```
try {
    // Create a link that allows end users to configure their account
    $link = $account->createConfigurationLink("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", 7); // 7 days validity
    // Use $link['url'] to redirect users to account configuration page
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

CopyFactory
-----------

[](#copyfactory)

You can create an instance of the SDK like so for Copyfactory:

```
use Oyi77\MetaapiCloudPhpSdk\CopyFactory;

$copyfactory = new CopyFactory('AUTH_TOKEN');
```

To generate a strategy id

```
try {
   return $copyfactory->generateStrategyId();
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To get all your strategies

```
try {
   // Using legacy method (deprecated)
   return $copyfactory->strategies();

   // Using infinite scroll pagination (recommended)
   return $copyfactory->strategiesWithInfiniteScroll([
       'includeRemoved' => false,
       'limit' => 1000,
       'offset' => 0
   ]);

   // Using classic pagination
   return $copyfactory->strategiesWithClassicPagination([
       'includeRemoved' => false,
       'limit' => 1000,
       'offset' => 0
   ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To get a single strategy

```
try {
   return $copyfactory->strategy("strategid");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To update a strategy

```
try {
   return $copyfactory->updateStrategy("strategid", [
        "name" => "Test strategy",
        "description" => "Some useful description about your strategy",
        "accountId" => "105646d8-8c97-4d4d-9b74-413bd66cd4ed"
   ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To remove a strategy

```
try {
   return $copyfactory->removeStrategy("strategid");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To get all your subscribers

```
try {
   // Using legacy method (deprecated)
   return $copyfactory->subscribers();

   // Using infinite scroll pagination (recommended)
   return $copyfactory->subscribersWithInfiniteScroll([
       'includeRemoved' => false,
       'limit' => 1000,
       'offset' => 0
   ]);

   // Using classic pagination
   return $copyfactory->subscribersWithClassicPagination([
       'includeRemoved' => false,
       'limit' => 1000,
       'offset' => 0
   ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To get a subscriber

```
try {
   return $copyfactory->subscriber("subscriberiId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To update a subscriber data

```
try {
   return $copyfactory->updateSubscriber("subsciberId", [
        'name' => "Copy Trade Subscriber",
        'subscriptions' => [
            [
                'strategyId' => 'dJZq',
                'multiplier' => 1,
            ]
        ]
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To remove a subscriber

```
try {
   return $copyfactory->removeSubscriber("subsciberId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To delete a subscription

```
try {
   return $copyfactory->deleteSubscription("subsciberId", "strategyId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Webhooks
--------

[](#webhooks)

CopyFactory supports webhooks for receiving trading signals.

Create a webhook

```
try {
    $webhook = $copyfactory->createWebhook("strategyId", [
        'symbolMapping' => [
            ['from' => 'EURUSD.m', 'to' => 'EURUSD']
        ],
        'magic' => 100
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Update a webhook

```
try {
    $copyfactory->updateWebhook("strategyId", "webhookId", [
        'symbolMapping' => [
            ['from' => 'EURUSD.m', 'to' => 'EURUSD'],
            ['from' => 'BTCUSD.m', 'to' => 'BTCUSD']
        ],
        'magic' => 100
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get webhooks

```
try {
    // Infinite scroll pagination
    $webhooks = $copyfactory->webhooksWithInfiniteScroll("strategyId");

    // Classic pagination
    $webhooks = $copyfactory->webhooksWithClassicPagination("strategyId", [
        'limit' => 10,
        'offset' => 0
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Delete a webhook

```
try {
    $copyfactory->deleteWebhook("strategyId", "webhookId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Copy Trade
----------

[](#copy-trade)

To Copy a trade from provider to subscriber. I recommend you create a strategy before hand and save to your database before you perform a copy trade, but its not compulsory as the package will create one for you. You can always read all your strategies in your account with the " $copyfactory-&gt;strategies()".

To Copy trade do:

```
try {
    $strategyId = "yd24";
    $providerAccountId = "Enter your provider account ID";
    $subAccountId = "Enter Subscriber Account ID";

    return $copyfactory->copy($providerAccountId, $subAccountId, $strategyId);

    /*
    * You can ommit the strategy Id and just copy the trade
    * The package will create a strategy as part of the copy process.
    */

    return $copyfactory->copy($providerAccountId, $subAccountId);

} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Note: copying a trade will take some seconds to finish, you you can have a loading indicator as feedback.

MetaStats
---------

[](#metastats)

You can get metrics for you account

You can create an instance of the SDK like so for MetaStats:

```
use Oyi77\MetaapiCloudPhpSdk\MetaStats;

$stats = new MetaStats('AUTH_TOKEN');
```

To get metrics:

```
try {
   return  $stats->metrics("accountId");
    //  You can pass a boolean as second parameter if you want to include open positions in your metrics
     return  $stats->metrics("accountId", true);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To get open trades for MetaApi account:

```
try {
   return  $stats->openTrades("accountId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

To get account trades for a time range:

```
try {
   return $stats->accountTrades("accountId", "2020-01-01 00:00:00.000", "2021-01-01 00:00:00.000");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Provisioning Profile API
------------------------

[](#provisioning-profile-api)

Provisioning profiles can be used as an alternative way to create MetaTrader accounts if automatic broker settings detection has failed.

```
use Oyi77\MetaapiCloudPhpSdk\ProvisioningProfileApi;

$provisioning = new ProvisioningProfileApi('AUTH_TOKEN');
```

Create a provisioning profile

```
try {
    $profile = $provisioning->createProfile([
        'name' => 'My profile',
        'version' => 5, // 4 for MT4, 5 for MT5
        'brokerTimezone' => 'EET',
        'brokerDSTSwitchTimezone' => 'EET'
    ]);

    // Upload servers.dat file for MT5 (or .srv file for MT4)
    $provisioning->uploadFile($profile['id'], 'servers.dat', '/path/to/servers.dat');
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get provisioning profiles

```
try {
    // Infinite scroll pagination
    $profiles = $provisioning->getProfilesWithInfiniteScroll([
        'limit' => 10,
        'offset' => 0,
        'query' => 'ICMarketsSC-MT5',
        'version' => 5
    ]);

    // Classic pagination
    $result = $provisioning->getProfilesWithClassicPagination([
        'limit' => 10,
        'offset' => 0
    ]);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get, update, and delete provisioning profile

```
try {
    // Get profile by ID
    $profile = $provisioning->getProfile("profileId");

    // Update profile
    $provisioning->updateProfile("profileId", [
        'name' => 'New name'
    ]);

    // Delete profile
    $provisioning->deleteProfile("profileId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Token Management API
--------------------

[](#token-management-api)

Generate narrowed-down tokens for use in Web or Mobile applications.

```
use Oyi77\MetaapiCloudPhpSdk\TokenManagementApi;

$tokenManagement = new TokenManagementApi('AUTH_TOKEN');
```

Narrow down token to specific applications

```
try {
    $narrowedToken = $tokenManagement->narrowDownTokenApplications(
        ['trading-account-management-api', 'metastats-api'],
        24 // validity in hours
    );
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Narrow down token to specific roles

```
try {
    $narrowedToken = $tokenManagement->narrowDownTokenRoles(
        ['reader'], // read-only access
        24
    );
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Narrow down token to specific resources

```
try {
    $narrowedToken = $tokenManagement->narrowDownTokenResources(
        [['entity' => 'account', 'id' => 'account-id']],
        24
    );
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Narrow down token with combined restrictions

```
try {
    $narrowedToken = $tokenManagement->narrowDownToken([
        'applications' => ['metaapi-api'],
        'roles' => ['reader'],
        'resources' => [['entity' => 'account', 'id' => 'account-id']]
    ], 24);
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get access rules manifest

```
try {
    $manifest = $tokenManagement->getAccessRules();
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Risk Management API
-------------------

[](#risk-management-api)

Risk Management API for executing trading challenges and competitions.

```
use Oyi77\MetaapiCloudPhpSdk\RiskManagementApi;

$riskManagement = new RiskManagementApi('AUTH_TOKEN');
```

Create and manage trackers

```
try {
    // Create a tracker
    $tracker = $riskManagement->createTracker("accountId", [
        'name' => 'Test tracker',
        'period' => 'day',
        'absoluteDrawdownThreshold' => 100
    ]);

    // Get all trackers
    $trackers = $riskManagement->getTrackers("accountId");

    // Get tracker by ID
    $tracker = $riskManagement->getTracker("accountId", "trackerId");

    // Update tracker
    $riskManagement->updateTracker("accountId", "trackerId", [
        'name' => 'Updated name'
    ]);

    // Delete tracker
    $riskManagement->deleteTracker("accountId", "trackerId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get tracker events and statistics

```
try {
    // Get tracker events
    $events = $riskManagement->getTrackerEvents(
        "2022-04-13 09:30:00.000",
        "2022-05-14 09:30:00.000",
        ['accountId' => 'account-id', 'trackerId' => 'tracker-id']
    );

    // Get tracking statistics
    $statistics = $riskManagement->getTrackingStatistics("accountId", "trackerId");

    // Get equity chart
    $equityChart = $riskManagement->getEquityChart("accountId", [
        'startTime' => '2022-04-13 09:30:00.000',
        'endTime' => '2022-05-14 09:30:00.000'
    ]);

    // Get period statistics
    $periodStats = $riskManagement->getPeriodStatistics("accountId", "trackerId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Expert Advisor Management
-------------------------

[](#expert-advisor-management)

Manage custom expert advisors (EAs) for MT4 accounts on G1 infrastructure. Note: EAs using DLLs are not supported.

```
use Oyi77\MetaapiCloudPhpSdk\AccountApi;

$account = new AccountApi('AUTH_TOKEN');
```

Create an expert advisor

```
try {
    // Note: preset field should be base64-encoded preset file
    $expert = $account->createExpertAdvisor("accountId", "expertId", [
        'period' => '1h',
        'symbol' => 'EURUSD',
        'preset' => 'a2V5MT12YWx1ZTEKa2V5Mj12YWx1ZTIKa2V5Mz12YWx1ZTMKc3VwZXI9dHJ1ZQ'
    ]);

    // Upload EA file
    $account->uploadExpertAdvisorFile("accountId", "expertId", "/path/to/custom-ea");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get expert advisors

```
try {
    // Get all expert advisors
    $experts = $account->getExpertAdvisors("accountId");

    // Get expert advisor by ID
    $expert = $account->getExpertAdvisor("accountId", "expertId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Update and delete expert advisor

```
try {
    // Update expert advisor
    $account->updateExpertAdvisor("accountId", "expertId", [
        'period' => '4h',
        'symbol' => 'EURUSD',
        'preset' => 'a2V5MT12YWx1ZTEKa2V5Mj12YWx1ZTIKa2V5Mz12YWx1ZTMKc3VwZXI9dHJ1ZQ'
    ]);
    $account->uploadExpertAdvisorFile("accountId", "expertId", "/path/to/custom-ea");

    // Delete expert advisor
    $account->deleteExpertAdvisor("accountId", "expertId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Historical Data API
-------------------

[](#historical-data-api)

Retrieve historical market data (candles and ticks). Available on G1 and MT4 G2 instances only.

```
use Oyi77\MetaapiCloudPhpSdk\AccountApi;

$account = new AccountApi('AUTH_TOKEN');
```

Get historical candles

```
try {
    // Get latest 1000 candles
    $candles = $account->getHistoricalCandles("accountId", "EURUSD", "1m", null, 1000);

    // Get candles from specific time
    $candles = $account->getHistoricalCandles(
        "accountId",
        "EURUSD",
        "1m",
        "2021-05-01 00:00:00.000",
        1000
    );
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Get historical ticks

```
try {
    // Get latest 1000 ticks
    $ticks = $account->getHistoricalTicks("accountId", "EURUSD", null, 0, 1000);

    // Get ticks from specific time with offset
    $ticks = $account->getHistoricalTicks(
        "accountId",
        "EURUSD",
        "2021-05-01 00:00:00.000",
        5,
        1000
    );
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Demo Account Generator API
--------------------------

[](#demo-account-generator-api)

Create MT4 and MT5 demo accounts. Note: Not all MT4/MT5 servers allow creating demo accounts using this method.

```
use Oyi77\MetaapiCloudPhpSdk\DemoAccountGeneratorApi;

$generator = new DemoAccountGeneratorApi('AUTH_TOKEN');
```

Create MT4 demo account

```
try {
    $demoAccount = $generator->createMt4DemoAccount([
        'balance' => 100000,
        'accountType' => 'type',
        'email' => 'example@example.com',
        'leverage' => 100,
        'serverName' => 'Exness-Trial4',
        'name' => 'Test User',
        'phone' => '+12345678901',
        'keywords' => ["Exness Technologies Ltd"]
    ]);

    // Optionally specify provisioning profile ID
    $demoAccount = $generator->createMt4DemoAccount([
        'balance' => 100000,
        'accountType' => 'type',
        'email' => 'example@example.com',
        'leverage' => 100,
        'serverName' => 'Exness-Trial4',
        'name' => 'Test User',
        'phone' => '+12345678901'
    ], "profileId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Create MT5 demo account

```
try {
    $demoAccount = $generator->createMt5DemoAccount([
        'accountType' => 'type',
        'balance' => 100000,
        'email' => 'example@example.com',
        'leverage' => 100,
        'serverName' => 'ICMarketsSC-Demo',
        'keywords' => ["Raw Trading Ltd"]
    ]);

    // Optionally specify provisioning profile ID
    $demoAccount = $generator->createMt5DemoAccount([
        'accountType' => 'type',
        'balance' => 100000,
        'email' => 'example@example.com',
        'leverage' => 100,
        'serverName' => 'Exness-Trial4',
        'name' => 'Test User',
        'phone' => '+12345678901'
    ], "profileId");
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Manager API
-----------

[](#manager-api)

Access and manage MT4 and MT5 servers. For detailed endpoint documentation, see:

```
use Oyi77\MetaapiCloudPhpSdk\ManagerApi;

$manager = new ManagerApi('AUTH_TOKEN');
```

The Manager API provides generic methods for accessing MT Manager endpoints:

```
try {
    // GET request
    $result = $manager->get('servers', ['limit' => 10]);

    // POST request
    $result = $manager->post('servers', ['name' => 'My Server']);

    // PUT request
    $result = $manager->put('servers/serverId', ['name' => 'Updated Name']);

    // DELETE request
    $result = $manager->delete('servers/serverId');
} catch (\Throwable $th) {
    $response = json_decode($th->getMessage());
    return $response->message;
}
```

Latency Monitor
---------------

[](#latency-monitor)

Track API latencies for monitoring and optimization.

```
use Oyi77\MetaapiCloudPhpSdk\Support\LatencyMonitor;

$monitor = new LatencyMonitor();

// Record latencies
$monitor->recordTradeLatency(150.5);
$monitor->recordRequestLatency(45.2);
$monitor->recordUpdateLatency(120.0);
$monitor->recordQuoteLatency(80.3);

// Get latency arrays
$tradeLatencies = $monitor->getTradeLatencies();
$requestLatencies = $monitor->getRequestLatencies();

// Get statistics
$tradeStats = $monitor->getTradeLatencyStats();
// Returns: ['count' => 1, 'min' => 150.5, 'max' => 150.5, 'avg' => 150.5, 'median' => 150.5]

$requestStats = $monitor->getRequestLatencyStats();
// Returns: ['count' => 1, 'min' => 45.2, 'max' => 45.2, 'avg' => 45.2, 'median' => 45.2]

// Clear all records
$monitor->clear();
```

Logging Support
---------------

[](#logging-support)

Enable logging for debugging and monitoring. Supports PSR-3 compatible loggers and file logging.

```
use Oyi77\MetaapiCloudPhpSdk\Support\Logger;

// Enable logging with PSR-3 logger
use Psr\Log\LoggerInterface;
$psrLogger = new YourPSR3Logger();
Logger::enable($psrLogger);

// Or enable file logging
Logger::enableFileLogging('./logs/metaapi.log');

// Use logging
Logger::info('API request completed', ['endpoint' => '/accounts']);
Logger::debug('Debug information', ['data' => $data]);
Logger::warning('Warning message');
Logger::error('Error occurred', ['error' => $error]);

// Disable logging
Logger::disable();
```

Pagination Helper
-----------------

[](#pagination-helper)

The SDK includes a pagination helper utility for working with paginated responses:

```
use Oyi77\MetaapiCloudPhpSdk\Support\Pagination;

// Get items from paginated response
$accounts = $account->readAllWithClassicPagination(['limit' => 10, 'offset' => 0]);
$items = Pagination::getItems($accounts);

// Get total count (for classic pagination)
$totalCount = Pagination::getCount($accounts);

// Check if there are more pages
$hasMore = Pagination::hasMore($accounts, 10);

// Calculate total pages
$totalPages = Pagination::getTotalPages($accounts, 10);
```

Testing
-------

[](#testing)

```
composer test
```

API Reference
-------------

[](#api-reference)

All API references can be found on Metaapi documentation website.

Security
--------

[](#security)

If you discover any security related issues, please open an issue.

Contributing
------------

[](#contributing)

Pull requests are welcome.

How can I thank you?
--------------------

[](#how-can-i-thank-you)

Why not star the github repo? I'd love the attention! you can share the link for this repository on Twitter or HackerNews?

Don't forget to [follow me on twitter!](https://twitter.com/EfekpoguaVicto4)

Thanks! Efekpogua Victory.

About This Repository
---------------------

[](#about-this-repository)

So here's the story - I was working on a project that needed to integrate with MetaApi, and I found this PHP SDK that looked promising. Turned out it was created by [Efekpogua Victory](https://github.com/victorycodedev) a couple years back, and it worked fine for basic stuff. But when I dug deeper, I realized it was missing a bunch of features that the Python SDK already had.

The original SDK hadn't been touched in like 2 years, and I really needed those missing APIs. Instead of starting from scratch (which would've been a pain), I decided to fork it and bring it up to speed. I spent some time going through the Python SDK docs and examples, figuring out what was missing, then added all the REST API stuff that should've been there.

Now I'm maintaining this actively, so if you find bugs or need something added, just open an issue. I'll get to it faster than the previous maintainer did (no offense to the original author - we all get busy).

Credits
-------

[](#credits)

Big shoutout to [Efekpogua Victory](https://github.com/victorycodedev) for building the initial version of this SDK. He did the hard work of setting up the foundation, and without that, I'd still be writing HTTP wrappers from scratch. So thanks for that!

I (Oyi77) forked it and updated everything to match what the Python SDK can do. The goal is to keep this thing maintained and useful for anyone who needs a PHP SDK for MetaApi.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](./LICENSE.md) or more information.

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance72

Regular maintenance activity

Popularity6

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 94.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

156d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7add2bee635fcf54d8dfb037986a88d82d59d1e5aa9c54eaa4afb159d9785744?d=identicon)[oyi77](/maintainers/oyi77)

---

Top Contributors

[![victorycodedev](https://avatars.githubusercontent.com/u/45511695?v=4)](https://github.com/victorycodedev "victorycodedev (50 commits)")[![oyi77](https://avatars.githubusercontent.com/u/14921983?v=4)](https://github.com/oyi77 "oyi77 (3 commits)")

---

Tags

forexforex-tradingmeta-tradermt4mt5MetaApiphp-metaapi-sdkoyi77

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/oyi77-metaapi-cloud-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/oyi77-metaapi-cloud-php-sdk/health.svg)](https://phpackages.com/packages/oyi77-metaapi-cloud-php-sdk)
```

###  Alternatives

[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3731.2M42](/packages/tencentcloud-tencentcloud-sdk-php)[convertkit/convertkitapi

Kit PHP SDK for the Kit API

2167.1k1](/packages/convertkit-convertkitapi)[mapado/rest-client-sdk

Rest Client SDK for hydra API

1125.9k2](/packages/mapado-rest-client-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
