> For the complete documentation index, see [llms.txt](https://docs.neurochain.ai/nc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.neurochain.ai/nc/neurochainai-guides/clients/http-client.md).

# HTTP Client

Complete guide for integrating with NCN Network using HTTP REST API.

***

## Overview

The HTTP API provides:

* Simple REST interface
* JSON request/response format
* Easy integration with any language
* Web browser compatibility

***

## Base URL

| Environment | URL                                  |
| ----------- | ------------------------------------ |
| Local       | `http://localhost:8080`              |
| Testnet     | `https://api.testnet.ncn-network.io` |
| Mainnet     | `https://api.ncn-network.io`         |

***

## Endpoints

### Health Check

```http
GET /health
```

**Response:**

```json
{
  "status": "healthy",
  "version": "0.1.0",
  "uptime_seconds": 3600
}
```

### Submit Inference

```http
POST /api/v1/inference
Content-Type: application/json

{
  "model_uuid": "bark_semantic",
  "input_data": "{\"text\": \"Hello, world!\"}"
}
```

**Response:**

```json
{
  "request_id": "req-abc123",
  "status": "queued",
  "payment_required": false
}
```

### Get Task Status

```http
GET /api/v1/inference/{request_id}
```

**Response:**

```json
{
  "request_id": "req-abc123",
  "status": "completed",
  "output_data": "{\"tokens\": [1, 2, 3]}",
  "error_message": null
}
```

### List Models

```http
GET /api/v1/models
```

**Response:**

```json
{
  "models": [
    {
      "model_uuid": "bark_semantic",
      "name": "Bark Semantic Model",
      "category": "audio",
      "description": "Text to semantic tokens"
    }
  ]
}
```

***

## Client Examples

### cURL

```bash
# Submit inference
curl -X POST http://localhost:8080/api/v1/inference \
  -H "Content-Type: application/json" \
  -d '{
    "model_uuid": "bark_semantic",
    "input_data": "{\"text\": \"Hello, world!\"}"
  }'

# Get status
curl http://localhost:8080/api/v1/inference/req-abc123

# Health check
curl http://localhost:8080/health
```

### Python (requests)

```python
import requests
import json
import time

class NCNHttpClient:
    def __init__(self, base_url='http://localhost:8080'):
        self.base_url = base_url
        self.session = requests.Session()
    
    def submit_inference(self, model_uuid, input_data):
        """Submit an inference request."""
        response = self.session.post(
            f"{self.base_url}/api/v1/inference",
            json={
                "model_uuid": model_uuid,
                "input_data": json.dumps(input_data) if isinstance(input_data, dict) else input_data
            }
        )
        response.raise_for_status()
        return response.json()
    
    def get_status(self, request_id):
        """Get task status."""
        response = self.session.get(
            f"{self.base_url}/api/v1/inference/{request_id}"
        )
        response.raise_for_status()
        return response.json()
    
    def inference(self, model_uuid, input_data, timeout=60, poll_interval=1):
        """Submit inference and wait for result."""
        # Submit
        result = self.submit_inference(model_uuid, input_data)
        request_id = result['request_id']
        
        # Poll for result
        start_time = time.time()
        while time.time() - start_time < timeout:
            status = self.get_status(request_id)
            
            if status['status'] == 'completed':
                return json.loads(status['output_data'])
            elif status['status'] == 'failed':
                raise Exception(status.get('error_message', 'Unknown error'))
            
            time.sleep(poll_interval)
        
        raise TimeoutError(f"Request {request_id} timed out")
    
    def health_check(self):
        """Check if gateway is healthy."""
        response = self.session.get(f"{self.base_url}/health")
        response.raise_for_status()
        return response.json()

# Usage
client = NCNHttpClient()
result = client.inference(
    model_uuid="bark_semantic",
    input_data={"text": "Hello, world!"}
)
print(result)
```

### JavaScript (fetch)

```javascript
class NCNHttpClient {
  constructor(baseUrl = 'http://localhost:8080') {
    this.baseUrl = baseUrl;
  }

  async submitInference(modelUuid, inputData) {
    const response = await fetch(`${this.baseUrl}/api/v1/inference`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        model_uuid: modelUuid,
        input_data: typeof inputData === 'object' 
          ? JSON.stringify(inputData) 
          : inputData
      })
    });
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${await response.text()}`);
    }
    
    return response.json();
  }

  async getStatus(requestId) {
    const response = await fetch(`${this.baseUrl}/api/v1/inference/${requestId}`);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${await response.text()}`);
    }
    
    return response.json();
  }

  async inference(modelUuid, inputData, timeout = 60000, pollInterval = 1000) {
    // Submit
    const result = await this.submitInference(modelUuid, inputData);
    const requestId = result.request_id;
    
    // Poll for result
    const startTime = Date.now();
    while (Date.now() - startTime < timeout) {
      const status = await this.getStatus(requestId);
      
      if (status.status === 'completed') {
        return JSON.parse(status.output_data);
      } else if (status.status === 'failed') {
        throw new Error(status.error_message || 'Unknown error');
      }
      
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    }
    
    throw new Error(`Request ${requestId} timed out`);
  }

  async healthCheck() {
    const response = await fetch(`${this.baseUrl}/health`);
    return response.json();
  }
}

// Usage
const client = new NCNHttpClient();
const result = await client.inference('bark_semantic', { text: 'Hello, world!' });
console.log(result);
```

### Go

```go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "time"
)

type NCNClient struct {
    BaseURL string
    Client  *http.Client
}

type InferenceRequest struct {
    ModelUUID string `json:"model_uuid"`
    InputData string `json:"input_data"`
}

type InferenceStatus struct {
    RequestID    string `json:"request_id"`
    Status       string `json:"status"`
    OutputData   string `json:"output_data"`
    ErrorMessage string `json:"error_message"`
}

func NewNCNClient(baseURL string) *NCNClient {
    return &NCNClient{
        BaseURL: baseURL,
        Client:  &http.Client{Timeout: 30 * time.Second},
    }
}

func (c *NCNClient) SubmitInference(modelUUID string, inputData interface{}) (*InferenceStatus, error) {
    inputJSON, _ := json.Marshal(inputData)
    
    reqBody, _ := json.Marshal(InferenceRequest{
        ModelUUID: modelUUID,
        InputData: string(inputJSON),
    })
    
    resp, err := c.Client.Post(
        c.BaseURL+"/api/v1/inference",
        "application/json",
        bytes.NewBuffer(reqBody),
    )
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    var status InferenceStatus
    json.NewDecoder(resp.Body).Decode(&status)
    return &status, nil
}

func (c *NCNClient) GetStatus(requestID string) (*InferenceStatus, error) {
    resp, err := c.Client.Get(c.BaseURL + "/api/v1/inference/" + requestID)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    var status InferenceStatus
    json.NewDecoder(resp.Body).Decode(&status)
    return &status, nil
}

func (c *NCNClient) Inference(modelUUID string, inputData interface{}, timeout time.Duration) (map[string]interface{}, error) {
    result, err := c.SubmitInference(modelUUID, inputData)
    if err != nil {
        return nil, err
    }
    
    deadline := time.Now().Add(timeout)
    for time.Now().Before(deadline) {
        status, err := c.GetStatus(result.RequestID)
        if err != nil {
            return nil, err
        }
        
        if status.Status == "completed" {
            var output map[string]interface{}
            json.Unmarshal([]byte(status.OutputData), &output)
            return output, nil
        } else if status.Status == "failed" {
            return nil, fmt.Errorf("task failed: %s", status.ErrorMessage)
        }
        
        time.Sleep(1 * time.Second)
    }
    
    return nil, fmt.Errorf("timeout")
}

func main() {
    client := NewNCNClient("http://localhost:8080")
    
    result, err := client.Inference("bark_semantic", map[string]string{
        "text": "Hello, world!",
    }, 60*time.Second)
    
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    
    fmt.Printf("Result: %v\n", result)
}
```

***

## Error Handling

### HTTP Status Codes

| Code | Meaning      | Action             |
| ---- | ------------ | ------------------ |
| 200  | Success      | Process response   |
| 400  | Bad Request  | Check input format |
| 404  | Not Found    | Check request\_id  |
| 429  | Rate Limited | Retry with backoff |
| 500  | Server Error | Retry or report    |
| 503  | Unavailable  | Retry later        |

### Error Response Format

```json
{
  "error": {
    "code": "INVALID_MODEL",
    "message": "Model 'unknown' not found",
    "details": {}
  }
}
```

### Retry Logic

```python
import time
from requests.exceptions import RequestException

def retry_request(func, max_retries=3, backoff=1.0):
    for attempt in range(max_retries):
        try:
            return func()
        except RequestException as e:
            if attempt < max_retries - 1:
                if hasattr(e.response, 'status_code'):
                    if e.response.status_code in [429, 503]:
                        time.sleep(backoff * (2 ** attempt))
                        continue
            raise
```

***

## Authentication (Future)

When API keys are implemented:

```http
Authorization: Bearer YOUR_API_KEY
```

```python
client = NCNHttpClient()
client.session.headers['Authorization'] = 'Bearer YOUR_API_KEY'
```

***

## Rate Limiting

### Limits

| Endpoint                 | Limit    |
| ------------------------ | -------- |
| POST /api/v1/inference   | 100/min  |
| GET /api/v1/inference/\* | 1000/min |
| GET /health              | No limit |

### Rate Limit Headers

```http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704067260
```

### Handle Rate Limits

```python
def handle_rate_limit(response):
    if response.status_code == 429:
        reset_time = int(response.headers.get('X-RateLimit-Reset', 0))
        wait_time = max(reset_time - time.time(), 1)
        time.sleep(wait_time)
        return True
    return False
```

***

## Next Steps

* [gRPC Client](/nc/neurochainai-guides/clients/grpc-client.md) - Higher performance option
* [Payment Integration](/nc/neurochainai-guides/clients/payment-integration.md) - Handle payments
* [Examples](/nc/neurochainai-guides/clients/examples.md) - More code examples
