# Configuration

Configure the Pinecone SDK for your application needs.

## API Key

The SDK requires an API key for authentication. Provide it in one of two ways:

### Environment Variable (Recommended)

```bash
export PINECONE_API_KEY="your-api-key"
```

```python
from pinecone import Pinecone

pc = Pinecone()  # Reads from environment
```

### Direct Parameter

```python
from pinecone import Pinecone

pc = Pinecone(api_key="your-api-key")
```

## Base URL Override

Override the default API endpoint:

```python
from pinecone import Pinecone

pc = Pinecone(
    api_key="your-api-key",
    base_url="https://custom-api.example.com"
)
```

## HTTP Client Configuration

Customize HTTP client behavior:

```python
from pinecone import Pinecone, HTTPConfig

config = HTTPConfig(
    timeout=30.0,
    max_retries=3,
    max_connections=100,
    max_keepalive_connections=20
)

pc = Pinecone(api_key="your-api-key", http_config=config)
```

### Timeout Settings

Control request timeouts:

```python
from pinecone import HTTPConfig

# Single timeout value for all operations
config = HTTPConfig(timeout=30.0)

# Separate timeouts for connect and read
config = HTTPConfig(
    timeout=(5.0, 30.0)  # (connect_timeout, read_timeout)
)
```

### Retry Configuration

Configure retry behavior:

```python
from pinecone import HTTPConfig

config = HTTPConfig(
    max_retries=3,
    retry_on_status_codes=[429, 500, 502, 503, 504]
)
```

## Async Client Configuration

Configure the async client:

```python
from pinecone import AsyncPinecone, HTTPConfig

async def main():
    config = HTTPConfig(
        timeout=30.0,
        max_connections=100
    )

    async with AsyncPinecone(
        api_key="your-api-key",
        http_config=config
    ) as pc:
        # Use client
        pass
```

### Async Client Lifecycle

The async client uses lazy initialization for thread and event loop safety. You can create the client in any context, and it will properly initialize when first used:

```python
from pinecone import AsyncPinecone

# Safe to create before event loop exists or in different thread
pc = AsyncPinecone(api_key="your-api-key")

async def use_client():
    # Client initializes on first async call
    response = await pc.inference.embed(model="...", texts=["..."])

    # Always clean up
    await pc.close()
```

For web applications, create the client once and reuse it across requests:

```python
# Module-level client (created once)
pc = AsyncPinecone(api_key="your-api-key")

async def request_handler():
    # Reuses same client across all requests
    response = await pc.inference.embed(model="...", texts=["..."])
    return response
```

## Environment Variables

The SDK recognizes these environment variables:

- `PINECONE_API_KEY` - API key for authentication
- `PINECONE_BASE_URL` - Override default API endpoint
- `PINECONE_TIMEOUT` - Default timeout in seconds
- `PINECONE_MAX_RETRIES` - Maximum retry attempts

## Best Practices

### Production Configuration

For production use:

```python
from pinecone import Pinecone, HTTPConfig

config = HTTPConfig(
    timeout=60.0,
    max_retries=3,
    max_connections=100,
    max_keepalive_connections=20
)

pc = Pinecone(http_config=config)
```

### Development Configuration

For development and testing:

```python
from pinecone import Pinecone, HTTPConfig

config = HTTPConfig(
    timeout=10.0,
    max_retries=1
)

pc = Pinecone(http_config=config)
```

### Connection Pooling

The SDK uses connection pooling by default. Configure pool size:

```python
from pinecone import HTTPConfig

config = HTTPConfig(
    max_connections=100,        # Total connections
    max_keepalive_connections=20  # Keep-alive connections
)
```

## Logging

The SDK uses Python's standard logging:

```python
import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)

# Or configure specifically for Pinecone
logger = logging.getLogger("pinecone")
logger.setLevel(logging.DEBUG)
```

## Next Steps

- Learn about [error handling](error-handling.md)
- Explore the [API reference](../api/client.rst)
