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

# 10-Minute Quickstart

> Complete your first H2H payment with webhook verification in under 10 minutes

# 10-Minute H2H Quickstart

Get your first Host-to-Host payment running in under 10 minutes with this step-by-step guide.

## Prerequisites

* Caibo merchant account with API keys ([Get API Keys](/ipg/authentication))
* Development environment (Node.js, Python, or PHP)
* Webhook endpoint capability

<Note>
  **Need API Keys?** If you don't have API keys yet, follow our [Authentication Guide](/ipg/authentication) to learn how to log into the Control Panel and generate your API keys.
</Note>

## Step 1: Environment Setup (2 minutes)

Set your environment variables:

```bash theme={null}
export Caibo_H2H_ENDPOINT="https://apay.caibo.digital"
export Caibo_API_KEY="your_sandbox_api_key"
export WEBHOOK_URL="https://your-server.com/webhook"
```

<Tip>
  Your API key should start with `caibo_test_sk_` for sandbox or `caibo_live_sk_` for production. Learn more about [API key formats](/ipg/authentication#key-types).
</Tip>

## Step 2: Create Payment Request (3 minutes)

<CodeGroup>
  ```javascript Node.js theme={null}
  const axios = require('axios');

  async function createPayment() {
    const response = await axios.post(
      `${process.env.Caibo_H2H_ENDPOINT}/payments/h2h/1`,
      {
        name: "John Doe",
        email: "john@example.com",
        phoneNumber: "+1234567890",
        address: "123 Main St",
        city: "New York",
        state: "NY",
        postalCode: "10001",
        country: "US",
        amount: 10.00,
        unit: "USD",
        originDomain: "localhost",
        notifyUrl: process.env.WEBHOOK_URL,
        successUrl: "http://localhost:3000/success",
        failureUrl: "http://localhost:3000/failure"
      },
      {
        headers: {
          'X-API-Key': process.env.Caibo_API_KEY,
          'Content-Type': 'application/json'
        }
      }
    );
    
    console.log('Payment created:', response.data);
    return response.data;
  }

  createPayment();
  ```

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

  def create_payment():
      response = requests.post(
          f"{os.getenv('Caibo_H2H_ENDPOINT')}/payments/h2h/1",
          json={
              "name": "John Doe",
              "email": "john@example.com",
              "phoneNumber": "+1234567890",
              "address": "123 Main St",
              "city": "New York",
              "state": "NY",
              "postalCode": "10001",
              "country": "US",
              "amount": 10.00,
              "unit": "USD",
              "originDomain": "localhost",
              "notifyUrl": os.getenv('WEBHOOK_URL'),
              "successUrl": "http://localhost:3000/success",
              "failureUrl": "http://localhost:3000/failure"
          },
          headers={
              'X-API-Key': os.getenv('Caibo_API_KEY'),
              'Content-Type': 'application/json'
          }
      )
      
      print('Payment created:', response.json())
      return response.json()

  create_payment()
  ```

  ```php PHP theme={null}
  <?php
  $endpoint = $_ENV['Caibo_H2H_ENDPOINT'];
  $apiKey = $_ENV['Caibo_API_KEY'];
  $webhookUrl = $_ENV['WEBHOOK_URL'];

  $data = [
      'name' => 'John Doe',
      'email' => 'john@example.com',
      'phoneNumber' => '+1234567890',
      'address' => '123 Main St',
      'city' => 'New York',
      'state' => 'NY',
      'postalCode' => '10001',
      'country' => 'US',
      'amount' => 10.00,
      'unit' => 'USD',
      'originDomain' => 'localhost',
      'notifyUrl' => $webhookUrl,
      'successUrl' => 'http://localhost:3000/success',
      'failureUrl' => 'http://localhost:3000/failure'
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "$endpoint/payments/h2h/1");
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . $apiKey,
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

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

  echo 'Payment created: ' . $response;
  ?>
  ```
</CodeGroup>

## Step 3: Handle Webhook (3 minutes)

<CodeGroup>
  ```javascript Node.js theme={null}
  const express = require('express');
  const crypto = require('crypto');
  const app = express();

  app.use(express.json());

  app.post('/webhook', (req, res) => {
    const signature = req.headers['x-caibo-signature'];
    const payload = JSON.stringify(req.body);
    
    // Verify webhook signature
    const expectedSignature = crypto
      .createHmac('sha512', process.env.WEBHOOK_SECRET)
      .update(payload)
      .digest('hex');
    
    if (signature !== expectedSignature) {
      return res.status(401).send('Invalid signature');
    }
    
    const { paymentRequestId, status, transactionId } = req.body;
    
    console.log(`Payment ${paymentRequestId} status: ${status}`);
    
    // Process payment status
    switch (status) {
      case 'completed':
        console.log('✅ Payment successful!');
        break;
      case 'failed':
        console.log('❌ Payment failed');
        break;
      case 'pending':
        console.log('⏳ Payment pending');
        break;
    }
    
    res.status(200).send('OK');
  });

  app.listen(3000, () => {
    console.log('Webhook server running on port 3000');
  });
  ```

  ```python Python theme={null}
  from flask import Flask, request, jsonify
  import hmac
  import hashlib
  import json
  import os

  app = Flask(__name__)

  @app.route('/webhook', methods=['POST'])
  def webhook():
      signature = request.headers.get('X-Caibo-Signature')
      payload = request.get_data()
      
      # Verify webhook signature
      expected_signature = hmac.new(
          os.getenv('WEBHOOK_SECRET').encode(),
          payload,
          hashlib.sha512
      ).hexdigest()
      
      if signature != expected_signature:
          return 'Invalid signature', 401
      
      data = request.json
      payment_id = data['paymentRequestId']
      status = data['status']
      
      print(f'Payment {payment_id} status: {status}')
      
      # Process payment status
      if status == 'completed':
          print('✅ Payment successful!')
      elif status == 'failed':
          print('❌ Payment failed')
      elif status == 'pending':
          print('⏳ Payment pending')
      
      return 'OK', 200

  if __name__ == '__main__':
      app.run(port=3000)
  ```

  ```php PHP theme={null}
  <?php
  $signature = $_SERVER['HTTP_X_Caibo_SIGNATURE'] ?? '';
  $payload = file_get_contents('php://input');

  // Verify webhook signature
  $expectedSignature = hash_hmac('sha512', $payload, $_ENV['WEBHOOK_SECRET']);

  if ($signature !== $expectedSignature) {
      http_response_code(401);
      exit('Invalid signature');
  }

  $data = json_decode($payload, true);
  $paymentId = $data['paymentRequestId'];
  $status = $data['status'];

  echo "Payment $paymentId status: $status\n";

  // Process payment status
  switch ($status) {
      case 'completed':
          echo "✅ Payment successful!\n";
          break;
      case 'failed':
          echo "❌ Payment failed\n";
          break;
      case 'pending':
          echo "⏳ Payment pending\n";
          break;
  }

  http_response_code(200);
  echo 'OK';
  ?>
  ```
</CodeGroup>

## Step 4: Check Payment Status (2 minutes)

<CodeGroup>
  ```javascript Node.js theme={null}
  async function checkPaymentStatus(paymentRequestId) {
    const response = await axios.get(
      `${process.env.Caibo_H2H_ENDPOINT}/payment-requests/status/${paymentRequestId}`,
      {
        headers: {
          'X-API-Key': process.env.Caibo_API_KEY
        }
      }
    );
    
    console.log('Payment status:', response.data);
    return response.data;
  }

  // Check status every 5 seconds
  setInterval(() => {
    checkPaymentStatus('your_payment_request_id');
  }, 5000);
  ```

  ```python Python theme={null}
  import time

  def check_payment_status(payment_request_id):
      response = requests.get(
          f"{os.getenv('Caibo_H2H_ENDPOINT')}/payment-requests/status/{payment_request_id}",
          headers={'X-API-Key': os.getenv('Caibo_API_KEY')}
      )
      
      print('Payment status:', response.json())
      return response.json()

  # Check status every 5 seconds
  while True:
      check_payment_status('your_payment_request_id')
      time.sleep(5)
  ```

  ```php PHP theme={null}
  <?php
  function checkPaymentStatus($paymentRequestId) {
      $endpoint = $_ENV['Caibo_H2H_ENDPOINT'];
      $apiKey = $_ENV['Caibo_API_KEY'];
      
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, "$endpoint/payment-requests/status/$paymentRequestId");
      curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: $apiKey"]);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      
      $response = curl_exec($ch);
      curl_close($ch);
      
      echo "Payment status: $response\n";
      return json_decode($response, true);
  }

  // Check status
  checkPaymentStatus('your_payment_request_id');
  ?>
  ```
</CodeGroup>

## Testing Your Integration

### Test with Sandbox Data

Use these test values in sandbox:

```json theme={null}
{
  "name": "Test User",
  "email": "test@example.com",
  "phoneNumber": "+1234567890",
  "amount": 10.00,
  "unit": "USD"
}
```

### Expected Flow

1. **Payment Created** → Status: `pending`
2. **User Completes Payment** → Webhook received
3. **Payment Confirmed** → Status: `completed`

## Troubleshooting

### Common Issues

| Issue                | Solution                            |
| -------------------- | ----------------------------------- |
| 401 Unauthorized     | Check API key in `X-API-Key` header |
| 400 Bad Request      | Validate required fields            |
| Webhook not received | Check webhook URL and firewall      |
| Invalid signature    | Verify webhook secret               |

### Debug Checklist

* ✅ API key is correct
* ✅ Webhook URL is accessible
* ✅ Webhook signature verification
* ✅ Required fields provided
* ✅ Amount format is correct

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication Guide" icon="key" href="/ipg/authentication">
    Learn about API key management and security
  </Card>

  <Card title="Credit Card Payments" icon="credit-card" href="/h2h/payments/credit-card-payments">
    Implement credit card processing
  </Card>

  <Card title="UPI Payments" icon="mobile" href="/h2h/payments/upi">
    Add UPI payment support
  </Card>

  <Card title="Testing Guide" icon="flask" href="/h2h/testing-sandbox">
    Comprehensive testing scenarios
  </Card>

  <Card title="Error Handling" icon="exclamation-triangle" href="/h2h/errors">
    Handle errors and edge cases
  </Card>
</CardGroup>

## Success! 🎉

You've successfully:

* Created your first H2H payment request
* Set up webhook handling with signature verification
* Implemented payment status checking
* Tested the complete payment flow

Your H2H integration is now ready for production!
