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

# Calling Neurons

> Learn how to call Neurons using the REST API or the TypeScript SDK.

Neurons can be called using either the REST API directly or our official TypeScript SDK. This guide explains both methods and their options.

## REST API

Each Neuron has a unique API URL in the format:

```bash theme={null}
https://run.prompteus.com/<organization-slug>/<neuron-slug>
```

### Authentication Requirements

Authentication is only required if enforced by the Neuron's [access control settings](/neurons/settings/access-control). A Neuron can be configured with:

* **[Public Access](/neurons/settings/access-control#public-access)**: No authentication required
* **[Referer Restrictions](/neurons/settings/access-control#referer-restrictions)**: Only requests from specific domains are allowed
* **[IP Restrictions](/neurons/settings/access-control#ip-restrictions)**: Only requests from specific IP addresses are allowed
* **[API Key Authentication](/neurons/settings/access-control#api-key-authentication)**: Requires a Prompteus API key
* **[JWT Authentication](/neurons/settings/access-control#jwt-authentication)**: Requires a valid JWT token

When authentication is required, provide it using the `Authorization` header:

```bash theme={null}
Authorization: Bearer <your-jwt-or-api-key>
```

<Note>
  If your Neuron has public access enabled, you can skip the authentication step entirely. See the [Access Control documentation](/neurons/settings/access-control) for detailed configuration options.
</Note>

### Basic Usage

To call a Neuron, send a POST request to its API URL with your input in JSON format:

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://run.prompteus.com/<organization-slug>/<neuron-slug> \
    -H "Content-Type: application/json" \
    -d '{"input": "What is the meaning of life?"}'
  ```

  ```javascript Fetch (JavaScript) theme={null}
  const response = await fetch("https://run.prompteus.com/<organization-slug>/<neuron-slug>", {
    method: "POST",
    body: JSON.stringify({ input: "What is the meaning of life?" }),
  });
  ```

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

  response = requests.post(
    "https://run.prompteus.com/<organization-slug>/<neuron-slug>",
    json={"input": "What is the meaning of life?"}
  )

  print(response.json())
  ```
</CodeGroup>

### Complete Examples

Here are complete examples showing how to call Neurons with error handling and authentication:

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function callNeuron(orgSlug, neuronSlug, input, apiKey = null) {
    const url = `https://run.prompteus.com/${orgSlug}/${neuronSlug}`;
    const headers = {
      'Content-Type': 'application/json'
    };
    
    // Add authentication if provided
    if (apiKey) {
      headers['Authorization'] = `Bearer ${apiKey}`;
    }

    try {
      const response = await fetch(url, {
        method: 'POST',
        headers,
        body: JSON.stringify({ input }),
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(`API Error: ${error.error} (${response.status})`);
      }

      const data = await response.json();
      
      // Log if response was from cache
      if (data.fromCache) {
        console.log('Response served from cache');
      }

      return data;
    } catch (error) {
      console.error('Failed to call neuron:', error);
      throw error;
    }
  }

  // Example usage
  async function example() {
    try {
      // Call without authentication
      const publicResponse = await callNeuron(
        'my-org',
        'my-neuron',
        'What is the meaning of life?'
      );
      console.log('Public response:', publicResponse);

      // Call with authentication
      const authenticatedResponse = await callNeuron(
        'my-org',
        'my-neuron',
        'What is the meaning of life?',
        'your-api-key'
      );
      console.log('Authenticated response:', authenticatedResponse);

      // Call with cache bypass
      const url = new URL('https://run.prompteus.com/my-org/my-neuron');
      url.searchParams.append('bypassCache', 'true');
      
      const noCacheResponse = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ input: 'Fresh response please' })
      });
      console.log('No cache response:', await noCacheResponse.json());

    } catch (error) {
      console.error('Example failed:', error);
    }
  }
  ```

  ```python Python theme={null}
  import requests
  from typing import Optional, Dict, Any
  from urllib.parse import urljoin

  class NeuronClient:
      def __init__(self, base_url: str = "https://run.prompteus.com"):
          self.base_url = base_url
          self.api_key: Optional[str] = None

      def set_api_key(self, api_key: str) -> None:
          """Set the API key for authentication."""
          self.api_key = api_key

      def call_neuron(
          self,
          org_slug: str,
          neuron_slug: str,
          input_text: str,
          bypass_cache: bool = False,
          raw_output: bool = False
      ) -> Dict[str, Any]:
          """
          Call a Neuron with the given parameters.
          
          Args:
              org_slug: Organization slug
              neuron_slug: Neuron slug
              input_text: Input text for the neuron
              bypass_cache: Whether to bypass the cache
              raw_output: Whether to return raw output
          
          Returns:
              Dict containing the neuron response
          
          Raises:
              requests.exceptions.RequestException: If the API call fails
          """
          # Build URL with query parameters
          url = urljoin(self.base_url, f"{org_slug}/{neuron_slug}")
          params = {}
          if bypass_cache:
              params['bypassCache'] = 'true'
          if raw_output:
              params['rawOutput'] = 'true'

          # Prepare headers
          headers = {'Content-Type': 'application/json'}
          if self.api_key:
              headers['Authorization'] = f'Bearer {self.api_key}'

          try:
              response = requests.post(
                  url,
                  json={'input': input_text},
                  headers=headers,
                  params=params
              )
              response.raise_for_status()

              data = response.json()
              
              // Log if response was from cache
              if data.get('fromCache'):
                  print('Response served from cache')
                  
              return data

          except requests.exceptions.RequestException as e:
              if hasattr(e.response, 'json'):
                  error_data = e.response.json()
                  print(f"API Error: {error_data.get('error')} ({e.response.status_code})")
              raise

  # Example usage
  def example():
      client = NeuronClient()
      
      try:
          // Call without authentication
          public_response = client.call_neuron(
              'my-org',
              'my-neuron',
              'What is the meaning of life?'
          )
          print('Public response:', public_response)

          // Call with authentication
          client.set_api_key('your-api-key')
          auth_response = client.call_neuron(
              'my-org',
              'my-neuron',
              'What is the meaning of life?'
          )
          print('Authenticated response:', auth_response)

          // Call with cache bypass
          no_cache_response = client.call_neuron(
              'my-org',
              'my-neuron',
              'Fresh response please',
              bypass_cache=True
          )
          print('No cache response:', no_cache_response)

      except requests.exceptions.RequestException as e:
          print('Example failed:', e)
  ```
</CodeGroup>

### Query Parameters

The API supports the following query parameters:

| Parameter     | Type    | Description                                                                    |
| ------------- | ------- | ------------------------------------------------------------------------------ |
| `bypassCache` | boolean | When true, forces a new execution and bypasses both exact and semantic caching |
| `rawOutput`   | boolean | When true, returns the raw text output without any processing                  |

Example with query parameters:

```bash theme={null}
https://run.prompteus.com/<organization-slug>/<neuron-slug>?bypassCache=true&rawOutput=true
```

### Authentication

If your Neuron requires authentication, you can provide it using the `Authorization` header:

```bash theme={null}
Authorization: Bearer <your-jwt-or-api-key>
```

See [Access Control](/neurons/settings/access-control) for more details about authentication methods.

### Response Format

A successful response will have this structure:

```typescript theme={null}
{
  output?: string;         // The generated output
  fromCache?: boolean;     // Whether the response was served from cache
  executionStopped?: boolean; // Whether execution was stopped prematurely
}
```

### Error Handling

Errors are returned with appropriate HTTP status codes and a JSON response:

```typescript theme={null}
{
  error: string;      // Error message
  statusCode: number; // HTTP status code
}
```

The API uses standard HTTP status codes to indicate the success or failure of requests:

| Status Code                 | Description                | Common Causes                                                                                                                         |
| --------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `400` Bad Request           | Invalid request parameters | • Malformed input JSON<br />• Missing required fields                                                                                 |
| `401` Unauthorized          | Authentication failed      | • Invalid/expired token<br />• Malformed API key<br />• Missing authentication                                                        |
| `403` Forbidden             | Access denied              | • [Access control](/neurons/settings/access-control) restrictions<br />• IP not in allowed list<br />• Domain not in allowed referers |
| `404` Not Found             | Resource not found         | • Neuron not found<br />• Deployment not found<br />• Organization not found<br />• Invalid neuron configuration                      |
| `422` Unprocessable Entity  | Validation failed          | • Input validation failed<br />• Invalid parameter format                                                                             |
| `429` Too Many Requests     | Rate limit exceeded        | • [Rate limits](/neurons/settings/rate-limiting) exceeded<br />• Account paused (billing)<br />• Usage limits exceeded                |
| `500` Internal Server Error | Server-side error          | • Unexpected server errors<br />• Missing deployment<br />• Configuration issues                                                      |
| `503` Service Unavailable   | Service down               | • Maintenance mode<br />• System overload<br />• Upstream service failures                                                            |

<Note>
  For `429` responses, check the `Retry-After` header for the number of seconds to wait before retrying:

  ```bash theme={null}
  Retry-After: 120  # Seconds until the block expires
  ```
</Note>

### Error Handling Examples

Here's how to handle errors in different languages:

<CodeGroup>
  ```javascript JavaScript theme={null}
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ input: 'Hello' })
    });

    if (!response.ok) {
      const error = await response.json();
      
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After');
        console.log(`Rate limited. Retry after ${retryAfter} seconds`);
      }
      
      throw new Error(`API Error: ${error.error} (${response.status})`);
    }

    const data = await response.json();
    // Process successful response...

  } catch (error) {
    console.error('Request failed:', error);
  }
  ```

  ```python Python theme={null}
  try:
      response = requests.post(url,
          json={'input': 'Hello'},
          headers={'Content-Type': 'application/json'}
      )
      response.raise_for_status()
      
      data = response.json()
      // Process successful response...

  except requests.exceptions.HTTPError as e:
      if e.response.status_code == 429:
          retry_after = e.response.headers.get('Retry-After')
          print(f"Rate limited. Retry after {retry_after} seconds")
      
      error_data = e.response.json()
      print(f"API Error: {error_data.get('error')} ({e.response.status_code})")
      
  except requests.exceptions.RequestException as e:
      print(f"Request failed: {e}")
  ```

  ```typescript TypeScript SDK theme={null}
  try {
    const response = await client.callNeuron('org', 'neuron', {
      input: 'Hello'
    });
    // Process successful response...

  } catch (error) {
    if ('statusCode' in error) {
      // Handle specific error types
      switch (error.statusCode) {
        case 429:
          console.error('Rate limited:', error.error);
          // Implement retry logic
          break;
        case 401:
          console.error('Authentication failed:', error.error);
          // Refresh authentication
          break;
        default:
          console.error(`API Error ${error.statusCode}:`, error.error);
      }
    } else {
      console.error('Unexpected error:', error);
    }
  }
  ```
</CodeGroup>

<Note>
  For production applications, we recommend implementing proper retry logic with exponential backoff, especially for `429` and `503` errors. See [Rate Limiting](/neurons/settings/rate-limiting) for more details about handling rate limits.
</Note>

## TypeScript SDK

We provide an official TypeScript SDK for a more convenient integration experience.

### Installation

```bash theme={null}
npm install @prompteus-ai/neuron-runner
```

### Authentication

The SDK supports both authenticated and unauthenticated calls, depending on your [Neuron's access control settings](/neurons/settings/access-control). Authentication is only required if your Neuron is configured to use API Key or JWT authentication.

If authentication is needed, you can provide it in multiple ways:

1. During client creation:

```typescript theme={null}
const client = new Prompteus({ jwtOrApiKey: 'your-token' });
```

2. Using the setter method:

```typescript theme={null}
client.setJwtOrApiKey('your-token');
```

3. Per request:

```typescript theme={null}
await client.callNeuron('org', 'neuron', {
  input: 'Hello',
  jwtOrApiKey: 'your-token'
});
```

<Note>
  If your Neuron has [public access](/neurons/settings/access-control#public-access) enabled, you can omit the authentication token. The SDK will work without authentication for public Neurons.
</Note>

### Basic Usage

```typescript theme={null}
import { Prompteus } from '@prompteus-ai/neuron-runner';

// Create a client instance
const client = new Prompteus({
  jwtOrApiKey: 'your-jwt-token', // Optional
  baseURL: 'https://run.prompteus.com' // Optional, defaults to this value
});

// Call a neuron
try {
  const response = await client.callNeuron('your-org', 'your-neuron', {
    input: 'Hello, world!'
  });
  console.log(response);
} catch (error) {
  console.error(error);
}
```

### Complete Example

Here's a comprehensive example showing different ways to use the SDK:

```typescript theme={null}
import { Prompteus } from '@prompteus-ai/neuron-runner';

async function example() {
  // Create a client instance
  const client = new Prompteus({
    jwtOrApiKey: 'your-api-key', // Optional
    baseURL: 'https://run.prompteus.com' // Optional
  });

  try {
    // Basic call
    const basicResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'What is the meaning of life?'
      }
    );
    console.log('Basic response:', basicResponse);

    // Call with cache bypass and raw output
    const advancedResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'Fresh response please',
        bypassCache: true,
        rawOutput: true
      }
    );
    console.log('Advanced response:', advancedResponse);

    // Call with different authentication
    const authenticatedResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'Hello with different auth',
        jwtOrApiKey: 'different-api-key'
      }
    );
    console.log('Authenticated response:', authenticatedResponse);

    // Call with custom headers
    const customResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'Hello with custom headers',
        headers: {
          'Custom-Header': 'value'
        }
      }
    );
    console.log('Custom response:', customResponse);

  } catch (error) {
    if ('statusCode' in error) {
      console.error(
        `API Error ${error.statusCode}: ${error.error}`
      );
    } else {
      console.error('Unexpected error:', error);
    }
  }
}
```

### Advanced Options

The `callNeuron` method accepts these options:

```typescript theme={null}
interface CallNeuronOptions {
  bypassCache?: boolean;  // Force new execution, bypass caching
  input?: string;        // Input text for the neuron
  rawOutput?: boolean;   // Return raw text output
  headers?: Record<string, string>; // Additional headers
  jwtOrApiKey?: string;  // Auth token for this request
}
```

Example with options:

```typescript theme={null}
const response = await client.callNeuron('org', 'neuron', {
  input: 'Hello',
  bypassCache: true,
  rawOutput: true,
  headers: {
    'Custom-Header': 'value'
  }
});
```

### Type Safety

The SDK provides TypeScript types for all responses:

```typescript theme={null}
interface NeuronSuccessResponse {
  output?: string;
  fromCache?: boolean;
  executionStopped?: boolean;
}

interface NeuronErrorResponse {
  error: string;
  statusCode: number;
}
```

### Error Handling

The SDK provides built-in error handling with TypeScript types, and exposes the [error status code and message from the API](#error-handling). Here's how to handle different error scenarios:

```typescript theme={null}
try {
  const response = await client.callNeuron('org', 'neuron', {
    input: 'Hello'
  });
  // Process successful response...

} catch (error) {
  if ('statusCode' in error) {
    // Handle specific error types
    switch (error.statusCode) {
      case 429:
        console.error('Rate limited:', error.error);
        // Implement retry logic
        break;
      case 401:
        console.error('Authentication failed:', error.error);
        // Refresh authentication
        break;
      default:
        console.error(`API Error ${error.statusCode}:`, error.error);
    }
  } else {
    console.error('Unexpected error:', error);
  }
}
```

<Note>
  The SDK throws typed errors that include both the error message and status code, making it easy to implement specific error handling logic for different scenarios.
</Note>

### Complete Example

Here's a comprehensive example showing different ways to use the SDK:

```typescript theme={null}
import { Prompteus } from '@prompteus-ai/neuron-runner';

async function example() {
  // Create a client instance
  const client = new Prompteus({
    jwtOrApiKey: 'your-api-key', // Optional
    baseURL: 'https://run.prompteus.com' // Optional
  });

  try {
    // Basic call
    const basicResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'What is the meaning of life?'
      }
    );
    console.log('Basic response:', basicResponse);

    // Call with cache bypass and raw output
    const advancedResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'Fresh response please',
        bypassCache: true,
        rawOutput: true
      }
    );
    console.log('Advanced response:', advancedResponse);

    // Call with different authentication
    const authenticatedResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'Hello with different auth',
        jwtOrApiKey: 'different-api-key'
      }
    );
    console.log('Authenticated response:', authenticatedResponse);

    // Call with custom headers
    const customResponse = await client.callNeuron(
      'my-org',
      'my-neuron',
      {
        input: 'Hello with custom headers',
        headers: {
          'Custom-Header': 'value'
        }
      }
    );
    console.log('Custom response:', customResponse);

  } catch (error) {
    if ('statusCode' in error) {
      console.error(
        `API Error ${error.statusCode}: ${error.error}`
      );
    } else {
      console.error('Unexpected error:', error);
    }
  }
}
```

## Related Resources

* [Introduction to Neurons](/neurons/intro) - Learn about Neurons
* [Access Control](/neurons/settings/access-control) - Configure authentication
* [Rate Limiting](/neurons/settings/rate-limiting) - Understand usage limits
* [Caching](/neurons/settings/caching) - Learn about response caching
* [Execution Logs](/neurons/logging) - Monitor Neuron calls
