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

# PHP SDK

> Complete guide for yativo/crypto-sdk — Composer installation, all resources, exception handling, and static webhook verification

# PHP SDK

The `yativo/crypto-sdk` Composer package provides a clean, object-oriented PHP interface to the Yativo Crypto API with automatic token refresh and static webhook signature verification.

[![Packagist version](https://img.shields.io/packagist/v/yativo/crypto-sdk?label=Packagist\&color=F28D1A)](https://packagist.org/packages/yativo/crypto-sdk)

## Installation

```bash theme={null}
composer require yativo/crypto-sdk
```

**Package:** [`yativo/crypto-sdk`](https://packagist.org/packages/yativo/crypto-sdk) · **Latest:** `1.0.0` · **Requirements:** PHP 7.4 or higher, `ext-json`, Guzzle HTTP 7+.

***

## Quick Start

<Tabs>
  <Tab title="Passwordless Auth">
    ```php theme={null}
    <?php
    require __DIR__ . '/vendor/autoload.php';

    use Yativo\YativoSDK;

    $sdk = new YativoSDK([
        'base_url' => 'https://crypto-api.yativo.com/api/v1/',
    ]);

    // Register
    $sdk->auth->register([
        'email'      => 'user@example.com',
        'password'   => 'SecurePass123!',
        'first_name' => 'Ada',
        'last_name'  => 'Lovelace',
    ]);

    // Step 1 — Send OTP to the user's email
    $sdk->auth->login('user@example.com');

    // Step 2 — Verify the OTP to complete login
    // Token is stored and auto-refreshed on 401
    $session = $sdk->auth->verifyOTP('123456', 'user@example.com');

    echo 'Logged in as: ' . $session['user']['email'] . PHP_EOL;
    ```
  </Tab>

  <Tab title="API Key Auth">
    ```php theme={null}
    <?php
    require __DIR__ . '/vendor/autoload.php';

    use Yativo\YativoSDK;

    $sdk = new YativoSDK([
        'api_key'    => getenv('YATIVO_API_KEY'),
        'api_secret' => getenv('YATIVO_API_SECRET'),
        'base_url'   => 'https://crypto-api.yativo.com/api/v1/',
    ]);

    // No login needed — requests are signed automatically
    $wallets = $sdk->assets->list();
    print_r($wallets);
    ```
  </Tab>
</Tabs>

***

## Constructor Options

```php theme={null}
new \Yativo\YativoSDK([
    'api_key'                 => 'your_api_key',       // optional
    'api_secret'              => 'your_api_secret',    // optional
    'base_url'                => 'https://crypto-api.yativo.com/api/v1/',
    'timeout'                 => 30,                   // seconds, default 30
    'standalone_iban_enabled' => false,                // default false
]);
```

***

## Authentication (`$sdk->auth`)

### Register

```php theme={null}
$user = $sdk->auth->register([
    'email'        => 'user@example.com',
    'password'     => 'SecurePass123!',
    'first_name'   => 'Ada',
    'last_name'    => 'Lovelace',
    'phone_number' => '+14155552671', // optional
]);
```

### Login (Passwordless)

Login is passwordless. Call `login($email)` to send an OTP, then call `verifyOTP($otp, $email)` to complete authentication.

```php theme={null}
// Step 1 — Send OTP
$sdk->auth->login('user@example.com');

// Step 2 — Verify OTP to complete auth
$session = $sdk->auth->verifyOTP('123456', 'user@example.com');
```

### 2FA Setup (Google Authenticator)

```php theme={null}
// Get QR code and secret for Google Authenticator setup
$details = $sdk->auth->get2faDetails();
// $details['qr_code'] — display as QR image
// $details['secret']  — manual entry fallback

// Activate 2FA on the account
$sdk->auth->enable2fa();

// Verify a TOTP code (use instead of verifyOTP when 2FA is enabled)
$session = $sdk->auth->verify2FA('654321', 'user@example.com');
```

### Passkey (WebAuthn) Auth

```php theme={null}
// Get WebAuthn challenge
$options = $sdk->auth->passkeyAuthOptions('user@example.com');

// Verify WebAuthn credential
$session = $sdk->auth->passkeyAuthVerify($credential);
```

### Exchange API Key for Bearer Token

```php theme={null}
$tokenResp = $sdk->auth->getToken(
    getenv('YATIVO_API_KEY'),
    getenv('YATIVO_API_SECRET')
);
```

***

## Accounts (`$sdk->accounts`)

```php theme={null}
// Create an account
$account = $sdk->accounts->create([
    'name'     => 'Main Treasury',
    'currency' => 'USD',
]);

// List accounts
$result = $sdk->accounts->list(['page' => 1, 'limit' => 20]);
echo 'Total: ' . $result['total'] . PHP_EOL;

// Get a single account
$account = $sdk->accounts->get('acct_abc123');
```

***

## Assets / Wallets (`$sdk->assets`)

### Create a Wallet

```php theme={null}
$wallet = $sdk->assets->createWallet([
    'account_id' => 'acct_abc123',
    'asset'      => 'USDC',
    'network'    => 'SOLANA',
]);
echo 'Deposit address: ' . $wallet['address'] . PHP_EOL;
```

### Batch Create Wallets

```php theme={null}
$wallets = $sdk->assets->batchCreate([
    'account_id' => 'acct_abc123',
    'assets'     => [
        ['asset' => 'USDC', 'network' => 'SOLANA'],
        ['asset' => 'XDC',  'network' => 'XDC'],
        ['asset' => 'ETH',  'network' => 'ETHEREUM'],
    ],
]);
```

### List Wallets

```php theme={null}
$wallets = $sdk->assets->list(['account_id' => 'acct_abc123']);
```

### Check Balance

```php theme={null}
$balance = $sdk->assets->getBalance(['wallet_id' => 'wallet_xyz789']);
echo "Balance: {$balance['amount']} {$balance['asset']}" . PHP_EOL;
```

***

## Transactions (`$sdk->transactions`)

### Send Funds (with Idempotency)

```php theme={null}
$tx = $sdk->transactions->send([
    'from_wallet_id'  => 'wallet_xyz789',
    'to_address'      => 'BjhiXKt...',
    'amount'          => '100.00',
    'asset'           => 'USDC',
    'network'         => 'SOLANA',
    'idempotency_key' => bin2hex(random_bytes(16)), // prevents double-sends
    'memo'            => 'Invoice #INV-2026-001',
]);
echo "Transaction ID: {$tx['id']}, Status: {$tx['status']}" . PHP_EOL;
```

### Estimate Gas Fee

```php theme={null}
$fee = $sdk->transactions->estimateGas([
    'from_wallet_id' => 'wallet_xyz789',
    'to_address'     => 'BjhiXKt...',
    'amount'         => '100.00',
    'asset'          => 'USDC',
    'network'        => 'SOLANA',
]);
echo "Estimated fee: {$fee['fee']} {$fee['fee_asset']}" . PHP_EOL;
```

### List Transactions

```php theme={null}
$result = $sdk->transactions->list([
    'account_id' => 'acct_abc123',
    'page'       => 1,
    'limit'      => 25,
    'status'     => 'COMPLETED',      // optional
    'start_date' => '2026-01-01',     // optional
    'end_date'   => '2026-03-31',     // optional
]);
foreach ($result['transactions'] as $t) {
    echo "{$t['id']} | {$t['status']} | {$t['amount']}" . PHP_EOL;
}
```

### Get a Transaction

```php theme={null}
$tx = $sdk->transactions->get('txn_def456');
```

***

## Swap (`$sdk->swap`)

```php theme={null}
// Get a swap quote
$quote = $sdk->swap->getQuote([
    'from_asset' => 'USDC',
    'to_asset'   => 'XDC',
    'amount'     => '500.00',
    'network'    => 'SOLANA',
]);
echo "You receive: {$quote['to_amount']} XDC at rate {$quote['rate']}" . PHP_EOL;

// Execute the swap (quote expires after ~30 seconds)
$result = $sdk->swap->execute([
    'quote_id'       => $quote['id'],
    'from_wallet_id' => 'wallet_xyz789',
    'to_wallet_id'   => 'wallet_xdc001',
]);
echo 'Swap status: ' . $result['status'] . PHP_EOL;
```

***

## Cards (`$sdk->cards`)

### Onboard a Cardholder

```php theme={null}
$cardholder = $sdk->cards->onboard([
    'customer_id'   => 'cust_111',
    'first_name'    => 'Ada',
    'last_name'     => 'Lovelace',
    'date_of_birth' => '1990-05-15',
    'address'       => [
        'line1'   => '1 Infinite Loop',
        'city'    => 'Cupertino',
        'state'   => 'CA',
        'zip'     => '95014',
        'country' => 'US',
    ],
]);
```

### Create a Virtual Card

```php theme={null}
$card = $sdk->cards->create([
    'cardholder_id' => $cardholder['id'],
    'currency'      => 'USD',
    'label'         => 'Engineering expenses',
]);
echo "Card {$card['id']}, last 4: {$card['last4']}" . PHP_EOL;
```

### Get Card Funding Address

```php theme={null}
$funding = $sdk->cards->getFundingAddress(['card_id' => $card['id']]);
echo "Fund at: {$funding['address']} on {$funding['network']}" . PHP_EOL;
```

### Get Card Transactions

```php theme={null}
$result = $sdk->cards->getTransactions([
    'card_id' => $card['id'],
    'page'    => 1,
    'limit'   => 20,
]);
```

***

## Webhooks (`$sdk->webhooks`)

### Create a Webhook

```php theme={null}
$webhook = $sdk->webhooks->create([
    'url'    => 'https://your-app.com/webhooks/yativo',
    'events' => ['transaction.completed', 'deposit.received', 'card.transaction'],
    'secret' => 'whsec_your_generated_secret',
]);
echo 'Webhook ID: ' . $webhook['id'] . PHP_EOL;
```

### Verify a Webhook Signature (Static Method)

```php theme={null}
use Yativo\Auth;

// In your webhook controller (Laravel example):
public function handle(Request $request): Response
{
    $payload   = $request->getContent();
    $signature = $request->header('X-Yativo-Signature', '');

    if (!Auth::verifySignature($payload, $signature, config('yativo.webhook_secret'))) {
        abort(401, 'Invalid webhook signature');
    }

    $event = json_decode($payload, true);
    // Handle event...
    Log::info('Yativo event', ['type' => $event['type']]);

    return response()->noContent();
}
```

<Note>
  `Auth::verifySignature()` is a static helper — you do not need an SDK instance to call it. This makes it easy to use in lightweight webhook endpoints that do not initialise the full SDK.
</Note>

### List / Delete Webhooks

```php theme={null}
$webhooks = $sdk->webhooks->list();
$sdk->webhooks->delete('wh_ghi789');
```

***

## API Keys (`$sdk->apiKeys`)

```php theme={null}
// Create an API key
$key = $sdk->apiKeys->create([
    'key_name'        => 'Production Server',
    'scopes'          => ['transactions:read', 'transactions:write', 'wallets:read'],
    'expires_in_days' => 90,               // optional
    'allowed_ips'     => ['203.0.113.10'], // optional
]);
// Store $key['secret'] securely — shown only once
echo 'API Key: '    . $key['key']    . PHP_EOL;
echo 'API Secret: ' . $key['secret'] . PHP_EOL;

// List API keys
$result = $sdk->apiKeys->list();

// Revoke a key (simple DELETE — no 2FA token required)
$sdk->apiKeys->revoke('key_jkl012');
```

***

## Auto-Forwarding (`$sdk->autoForwarding`)

Auto-forwarding rules automatically sweep incoming deposits to a destination address.

```php theme={null}
// List all auto-forwarding rules
$result = $sdk->autoForwarding->list();

// Create a rule
$rule = $sdk->autoForwarding->create([
    'source_wallet_id'     => 'wallet_xyz789',
    'destination_address'  => 'BjhiXKt...',
    'asset'                => 'USDC',
    'network'              => 'SOLANA',
    'min_amount'           => '10.00', // optional — only forward if amount >= this
]);
echo 'Rule ID: ' . $rule['id'] . PHP_EOL;

// Update a rule
$sdk->autoForwarding->update($rule['id'], ['min_amount' => '25.00']);

// Delete a rule
$sdk->autoForwarding->delete($rule['id']);
```

***

## Customers (`$sdk->customers`)

```php theme={null}
$customer = $sdk->customers->create([
    'external_id' => 'usr_from_your_db',
    'email'       => 'customer@example.com',
    'first_name'  => 'Charles',
    'last_name'   => 'Babbage',
    'kyc_level'   => 'BASIC',
]);

$result   = $sdk->customers->list(['page' => 1, 'limit' => 50]);
$customer = $sdk->customers->get('cust_abc');
$sdk->customers->update('cust_abc', ['kyc_level' => 'FULL']);
```

***

## Analytics (`$sdk->analytics`)

```php theme={null}
$report = $sdk->analytics->getSummary([
    'account_id' => 'acct_abc123',
    'start_date' => '2026-01-01',
    'end_date'   => '2026-03-31',
]);
echo 'Total volume: ' . $report['total_volume'] . PHP_EOL;
echo 'Total fees: '   . $report['total_fees']   . PHP_EOL;
```

***

## IBAN (`$sdk->standaloneIban`)

<Warning>
  Pass `'standalone_iban_enabled' => true` in the constructor options to unlock this resource.
</Warning>

```php theme={null}
$sdk = new YativoSDK([
    'api_key'                 => getenv('YATIVO_API_KEY'),
    'api_secret'              => getenv('YATIVO_API_SECRET'),
    'standalone_iban_enabled' => true,
]);

$iban = $sdk->standaloneIban->create([
    'customer_id' => 'cust_111',
    'currency'    => 'EUR',
    'label'       => 'EU Collections',
]);
echo "IBAN: {$iban['iban']}, BIC: {$iban['bic']}" . PHP_EOL;

$ibans = $sdk->standaloneIban->list(['customer_id' => 'cust_111']);
```

***

## Exception Handling

```php theme={null}
use Yativo\Exceptions\YativoException;
use Yativo\Exceptions\AuthenticationException;
use Yativo\Exceptions\ValidationException;
use Yativo\Exceptions\RateLimitException;
use Yativo\Exceptions\NotFoundException;

try {
    $tx = $sdk->transactions->send([
        'from_wallet_id'  => 'wallet_xyz789',
        'to_address'      => 'BjhiXKt...',
        'amount'          => '100.00',
        'asset'           => 'USDC',
        'network'         => 'SOLANA',
        'idempotency_key' => bin2hex(random_bytes(16)),
    ]);
} catch (AuthenticationException $e) {
    // Invalid or expired credentials
    error_log('Auth failed: ' . $e->getMessage());
} catch (ValidationException $e) {
    // Server-side validation failed
    error_log('Validation: ' . json_encode($e->getErrors()));
} catch (RateLimitException $e) {
    // 60 req/min per endpoint exceeded
    $retryAfter = $e->getRetryAfter(); // seconds
    error_log("Rate limited. Retry after {$retryAfter}s");
} catch (NotFoundException $e) {
    error_log('Not found: ' . $e->getResourceId());
} catch (YativoException $e) {
    error_log("API error {$e->getStatusCode()}: {$e->getMessage()}");
}
```

### Exception Hierarchy

```
\Yativo\Exceptions\YativoException
├── AuthenticationException   (HTTP 401)
├── AuthorizationException    (HTTP 403)
├── ValidationException       (HTTP 422)  — getErrors(): array
├── NotFoundException         (HTTP 404)  — getResourceId(): string
├── RateLimitException        (HTTP 429)  — getRetryAfter(): int
└── ServerException           (HTTP 5xx)
```

***

## Laravel Service Provider Example

```php theme={null}
// config/yativo.php
return [
    'api_key'        => env('YATIVO_API_KEY'),
    'api_secret'     => env('YATIVO_API_SECRET'),
    'base_url'       => env('YATIVO_BASE_URL', 'https://crypto-api.yativo.com/api/v1/'),
    'webhook_secret' => env('YATIVO_WEBHOOK_SECRET'),
];

// app/Providers/YativoServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Yativo\YativoSDK;

class YativoServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(YativoSDK::class, fn() => new YativoSDK([
            'api_key'    => config('yativo.api_key'),
            'api_secret' => config('yativo.api_secret'),
            'base_url'   => config('yativo.base_url'),
        ]));
    }
}

// Usage in a controller
use Yativo\YativoSDK;

class PaymentController extends Controller
{
    public function __construct(private YativoSDK $yativo) {}

    public function send(Request $request)
    {
        $tx = $this->yativo->transactions->send([
            'from_wallet_id'  => $request->wallet_id,
            'to_address'      => $request->to_address,
            'amount'          => $request->amount,
            'asset'           => 'USDC',
            'network'         => 'SOLANA',
            'idempotency_key' => (string) \Str::uuid(),
        ]);
        return response()->json($tx);
    }
}
```
