# OpenAI API Documentation

## Overview

The **OpenAI API** provides access to powerful language models like GPT-4o, GPT-5, and o3 for text generation, chat completions, embeddings, and more. The API supports both the newer **Responses API** (recommended for new projects) and the traditional **Chat Completions API**.

**Official Documentation**: https://platform.openai.com/docs/  
**API Reference**: https://platform.openai.com/docs/api-reference  
**Pricing**: https://platform.openai.com/docs/pricing

---

## Base URL

```
https://api.openai.com/v1
```

---

## Authentication

The OpenAI API uses **API keys** for authentication via HTTP Bearer authentication.

### Getting an API Key

1. Visit https://platform.openai.com/api-keys
2. Create a new API key
3. **Keep it secret!** Never expose it in client-side code

### Using the API Key

**HTTP Header**:
```bash
Authorization: Bearer YOUR_OPENAI_API_KEY
```

**Example with curl**:
```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

### Organization and Project Headers (Optional)

If you belong to multiple organizations:

```bash
curl https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Organization: YOUR_ORG_ID" \
  -H "OpenAI-Project: $PROJECT_ID"
```

---

## Main APIs

### 1. Chat Completions API (Recommended for Most Use Cases)

The **Chat Completions API** generates model responses from a conversation consisting of messages.

**Endpoint**: `POST https://api.openai.com/v1/chat/completions`

#### Basic Request

```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "What is SEO?"}
    ]
  }'
```

#### Request Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `model` | string | **Yes** | Model ID (e.g., `gpt-4o-mini`, `gpt-4o`, `gpt-5`) |
| `messages` | array | **Yes** | Array of message objects with `role` and `content` |
| `temperature` | number | No | Sampling temperature (0-2). Default: 1. Lower = more deterministic |
| `max_tokens` | integer | No | Maximum tokens to generate |
| `top_p` | number | No | Nucleus sampling (0-1). Default: 1 |
| `n` | integer | No | Number of completions to generate. Default: 1 |
| `stream` | boolean | No | Stream responses. Default: false |
| `stop` | string/array | No | Stop sequences |
| `presence_penalty` | number | No | Penalize new tokens (-2.0 to 2.0). Default: 0 |
| `frequency_penalty` | number | No | Penalize repeated tokens (-2.0 to 2.0). Default: 0 |
| `response_format` | object | No | Force JSON output with `{"type": "json_object"}` |

#### Message Roles

| Role | Description |
|------|-------------|
| `system` | Instructions for the model's behavior (highest priority) |
| `user` | User messages/prompts |
| `assistant` | Model's previous responses (for conversation context) |
| `developer` | Developer-level instructions (in Responses API) |

#### Response Format

```json
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1677858242,
  "model": "gpt-4o-mini",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "SEO stands for Search Engine Optimization..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 20,
    "completion_tokens": 50,
    "total_tokens": 70
  }
}
```

#### Finish Reasons

- `stop`: Natural completion
- `length`: Max tokens reached
- `content_filter`: Content filtered
- `function_call`: Model called a function

---

### 2. Responses API (New, Recommended)

The **Responses API** is OpenAI's newest and most advanced interface, especially recommended for reasoning models like GPT-5 and o3.

**Endpoint**: `POST https://api.openai.com/v1/responses`

#### Basic Request

```bash
curl https://api.openai.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-5",
    "input": "Write a short bedtime story about a unicorn."
  }'
```

#### With Instructions

```bash
curl https://api.openai.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-5",
    "instructions": "You are an SEO expert.",
    "input": "What are the best keywords for an e-commerce site?"
  }'
```

#### Response Format

```json
{
  "id": "resp_abc123",
  "output": [
    {
      "id": "msg_67b73f697ba4819183a15cc17d011509",
      "type": "message",
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "Under the soft glow of the moon...",
          "annotations": []
        }
      ]
    }
  ],
  "output_text": "Under the soft glow of the moon..."
}
```

**Note**: The `output_text` property (available in official SDKs) aggregates all text outputs into a single string for convenience.

---

## Available Models

### Current Models (as of Oct 2025)

| Model | Description | Context Window | Best For |
|-------|-------------|----------------|----------|
| `gpt-5` | Best model for coding and agentic tasks | Large | Complex reasoning, coding |
| `gpt-5-mini` | Faster, cost-efficient version of GPT-5 | Large | Balanced performance/cost |
| `gpt-5-nano` | Fastest, most cost-efficient | Medium | Simple tasks, high volume |
| `gpt-4o` | Previous generation flagship | 128K | General purpose |
| `gpt-4o-mini` | Cost-effective GPT-4 class | 128K | Most common use case |
| `o3` | Advanced reasoning model | Large | Complex problem solving |

### Model Naming Convention

- **Pinned versions**: `gpt-4o-2024-08-06` (recommended for production)
- **Latest versions**: `gpt-4o` (auto-updates, not recommended for production)

**Best Practice**: Always pin to specific model snapshots in production to ensure consistent behavior.

---

## Code Examples

### PHP (Laravel)

```php
use Illuminate\Support\Facades\Http;

class OpenAIService
{
    private $apiKey;
    private $baseUrl = 'https://api.openai.com/v1';
    
    public function __construct()
    {
        $this->apiKey = config('services.openai.api_key');
    }
    
    public function chatCompletion(array $messages, string $model = 'gpt-4o-mini', array $options = [])
    {
        $payload = array_merge([
            'model' => $model,
            'messages' => $messages,
        ], $options);
        
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $this->apiKey,
            'Content-Type' => 'application/json',
        ])
        ->timeout(60)
        ->post($this->baseUrl . '/chat/completions', $payload);
        
        if ($response->successful()) {
            return $response->json();
        }
        
        throw new \Exception('OpenAI API error: ' . $response->body());
    }
    
    public function extractKeywords(string $content, string $pageType = 'product')
    {
        $messages = [
            [
                'role' => 'system',
                'content' => 'You are an SEO expert. Extract 15-20 relevant keyword candidates from the provided content. Return them as a JSON array with fields: keyword, relevance_score (0-100), and search_intent (informational/commercial/transactional).'
            ],
            [
                'role' => 'user',
                'content' => "Page type: {$pageType}\n\nContent:\n{$content}"
            ]
        ];
        
        $response = $this->chatCompletion($messages, 'gpt-4o-mini', [
            'temperature' => 0.3,
            'response_format' => ['type' => 'json_object'],
        ]);
        
        return json_decode($response['choices'][0]['message']['content'], true);
    }
}
```

### Usage in Laravel Job

```php
use App\Services\OpenAIService;

class ProcessPageAnalysis implements ShouldQueue
{
    protected $openai;
    
    public function __construct(OpenAIService $openai)
    {
        $this->openai = $openai;
    }
    
    public function handle()
    {
        $page = Page::where('status', 'content_fetched')->first();
        
        if (!$page) {
            return;
        }
        
        try {
            // Extract keywords using AI
            $keywords = $this->openai->extractKeywords(
                $page->content,
                $page->page_type
            );
            
            // Save keywords
            foreach ($keywords['keywords'] as $keyword) {
                KeywordRecommendation::create([
                    'page_id' => $page->id,
                    'keyword' => $keyword['keyword'],
                    'relevance_score' => $keyword['relevance_score'],
                    'search_intent' => $keyword['search_intent'],
                ]);
            }
            
            $page->update(['status' => 'analyzed']);
            
            // Rate limiting: 50ms delay
            usleep(50000);
            
        } catch (\Exception $e) {
            Log::error('OpenAI analysis failed', [
                'page_id' => $page->id,
                'error' => $e->getMessage(),
            ]);
            
            $page->update(['status' => 'failed']);
        }
    }
}
```

### JavaScript/Node.js

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

async function extractKeywords(content, pageType = 'product') {
  const response = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      {
        role: 'system',
        content: 'You are an SEO expert. Extract 15-20 relevant keyword candidates from the provided content. Return them as a JSON array.'
      },
      {
        role: 'user',
        content: `Page type: ${pageType}\n\nContent:\n${content}`
      }
    ],
    temperature: 0.3,
    response_format: { type: 'json_object' },
  });

  return JSON.parse(response.choices[0].message.content);
}

// Usage
const keywords = await extractKeywords(pageContent, 'product');
console.log(keywords);
```

### Python

```python
from openai import OpenAI
import json

client = OpenAI(api_key="your_api_key")

def extract_keywords(content, page_type='product'):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "You are an SEO expert. Extract 15-20 relevant keyword candidates from the provided content. Return them as a JSON array."
            },
            {
                "role": "user",
                "content": f"Page type: {page_type}\n\nContent:\n{content}"
            }
        ],
        temperature=0.3,
        response_format={"type": "json_object"}
    )
    
    return json.loads(response.choices[0].message.content)

# Usage
keywords = extract_keywords(page_content, 'product')
print(keywords)
```

---

## Advanced Features

### 1. Structured Outputs (JSON Mode)

Force the model to return valid JSON:

```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [
      {"role": "user", "content": "Extract keywords from this text: ..."}
    ],
    "response_format": {"type": "json_object"}
  }'
```

**Important**: When using JSON mode, you must include "JSON" in your prompt.

### 2. Function Calling

Allow the model to call external functions:

```json
{
  "model": "gpt-4o-mini",
  "messages": [
    {"role": "user", "content": "What's the weather in Paris?"}
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get the current weather in a location",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "City name"
            }
          },
          "required": ["location"]
        }
      }
    }
  ]
}
```

### 3. Streaming Responses

Get responses as they're generated:

```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Tell me a story"}],
    "stream": true
  }'
```

Response comes as Server-Sent Events (SSE):

```
data: {"choices":[{"delta":{"content":"Once"}}]}
data: {"choices":[{"delta":{"content":" upon"}}]}
data: [DONE]
```

---

## Rate Limits

Rate limits vary by tier and model. Check headers in API responses:

- `x-ratelimit-limit-requests`: Max requests per minute
- `x-ratelimit-limit-tokens`: Max tokens per minute
- `x-ratelimit-remaining-requests`: Remaining requests
- `x-ratelimit-remaining-tokens`: Remaining tokens
- `x-ratelimit-reset-requests`: Time until reset

**Best Practice**: Implement exponential backoff when hitting rate limits.

---

## Error Handling

### Common Error Codes

| Code | Meaning | Solution |
|------|---------|----------|
| 401 | Invalid API key | Check authentication |
| 429 | Rate limit exceeded | Implement backoff, reduce frequency |
| 500 | Server error | Retry with exponential backoff |
| 503 | Service unavailable | Retry later |

### Error Response Format

```json
{
  "error": {
    "message": "Rate limit exceeded",
    "type": "rate_limit_error",
    "param": null,
    "code": "rate_limit_exceeded"
  }
}
```

### PHP Error Handling Example

```php
try {
    $response = $this->openai->chatCompletion($messages);
} catch (\Exception $e) {
    $errorBody = $e->getMessage();
    
    if (str_contains($errorBody, 'rate_limit')) {
        // Wait and retry
        sleep(5);
        return $this->chatCompletion($messages);
    }
    
    if (str_contains($errorBody, '500') || str_contains($errorBody, '503')) {
        // Server error, retry with backoff
        sleep(2);
        return $this->chatCompletion($messages);
    }
    
    // Log and fail
    Log::error('OpenAI API error', ['error' => $errorBody]);
    throw $e;
}
```

---

## Best Practices for SEO Tool

### 1. Use Appropriate Model

For keyword extraction:
- **Recommended**: `gpt-4o-mini` (best balance of cost and quality)
- **Alternative**: `gpt-5-nano` (faster, cheaper for simple extraction)

### 2. Optimize Temperature

```php
$response = $this->chatCompletion($messages, 'gpt-4o-mini', [
    'temperature' => 0.3, // Lower for more consistent, focused output
]);
```

### 3. Limit Token Usage

```php
$response = $this->chatCompletion($messages, 'gpt-4o-mini', [
    'max_tokens' => 500, // Limit response length to control costs
]);
```

### 4. Use JSON Mode for Structured Data

```php
$response = $this->chatCompletion($messages, 'gpt-4o-mini', [
    'response_format' => ['type' => 'json_object'],
]);
```

### 5. Implement Rate Limiting

```php
// Add 50ms delay between API calls
usleep(50000);
```

### 6. Track API Usage

```php
// Log token usage for cost tracking
ApiUsageLog::create([
    'service' => 'openai',
    'model' => $response['model'],
    'prompt_tokens' => $response['usage']['prompt_tokens'],
    'completion_tokens' => $response['usage']['completion_tokens'],
    'total_tokens' => $response['usage']['total_tokens'],
    'cost' => $this->calculateCost($response),
]);
```

### 7. Cost Calculation

Approximate costs (check current pricing at https://platform.openai.com/pricing):

| Model | Input (per 1M tokens) | Output (per 1M tokens) |
|-------|----------------------|------------------------|
| gpt-4o-mini | $0.15 | $0.60 |
| gpt-4o | $2.50 | $10.00 |
| gpt-5-nano | ~$0.10 | ~$0.40 |

```php
private function calculateCost($response)
{
    $model = $response['model'];
    $inputTokens = $response['usage']['prompt_tokens'];
    $outputTokens = $response['usage']['completion_tokens'];
    
    // Prices per 1M tokens
    $prices = [
        'gpt-4o-mini' => ['input' => 0.15, 'output' => 0.60],
        'gpt-4o' => ['input' => 2.50, 'output' => 10.00],
    ];
    
    $price = $prices[$model] ?? $prices['gpt-4o-mini'];
    
    $inputCost = ($inputTokens / 1000000) * $price['input'];
    $outputCost = ($outputTokens / 1000000) * $price['output'];
    
    return $inputCost + $outputCost;
}
```

---

## Prompt Engineering Tips

### For Keyword Extraction

```php
$systemPrompt = <<<PROMPT
You are an expert SEO analyst. Analyze the provided webpage content and extract 15-20 keyword candidates.

For each keyword, provide:
1. keyword: The actual keyword phrase
2. relevance_score: 0-100 score based on how relevant it is to the content
3. search_intent: One of [informational, commercial, transactional, navigational]
4. keyword_type: One of [primary, secondary, long_tail]

Focus on:
- Keywords that naturally appear in the content
- Commercial intent keywords for product pages
- Long-tail variations with lower competition potential
- Semantic variations and related terms

Return ONLY valid JSON in this format:
{
  "keywords": [
    {
      "keyword": "example keyword",
      "relevance_score": 85,
      "search_intent": "commercial",
      "keyword_type": "primary"
    }
  ]
}
PROMPT;
```

### For Content Gap Analysis

```php
$systemPrompt = <<<PROMPT
You are an SEO content strategist. Analyze the target page content and competitor pages to identify content gaps.

Identify:
1. Topics covered by competitors but missing from target page
2. Common questions (People Also Ask) related to the keyword
3. Semantic keywords used by top-ranking competitors
4. Content depth comparison

Return JSON format:
{
  "missing_topics": ["topic1", "topic2"],
  "common_questions": ["question1", "question2"],
  "competitor_keywords": ["keyword1", "keyword2"],
  "recommendations": ["rec1", "rec2"]
}
PROMPT;
```

---

## Environment Configuration (.env)

```env
# OpenAI Configuration
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini
OPENAI_TEMPERATURE=0.3
OPENAI_MAX_TOKENS=500
```

---

## Additional Resources

- **Official Documentation**: https://platform.openai.com/docs/
- **API Reference**: https://platform.openai.com/docs/api-reference
- **Pricing**: https://platform.openai.com/pricing
- **Models Guide**: https://platform.openai.com/docs/models
- **Rate Limits**: https://platform.openai.com/docs/guides/rate-limits
- **Playground**: https://platform.openai.com/playground
- **Community Forum**: https://community.openai.com/
- **Status Page**: https://status.openai.com/

---

## Summary for SEO Tool Implementation

1. **Use Chat Completions API** with `gpt-4o-mini` model for keyword extraction
2. **Enable JSON mode** with `response_format: {type: "json_object"}`
3. **Set temperature to 0.3** for consistent, focused output
4. **Limit max_tokens to 500-1000** to control costs
5. **Add 50ms delay** between requests to respect rate limits
6. **Track token usage** for cost monitoring
7. **Implement error handling** with retry logic for rate limits and server errors
8. **Use system prompts** to guide the model's behavior as an SEO expert
9. **Pin to specific model version** in production (e.g., `gpt-4o-mini-2024-07-18`)

**Estimated Cost**: For 100-page analysis with ~500 tokens per page:
- Input: 100 pages × 500 tokens = 50,000 tokens
- Output: 100 pages × 300 tokens = 30,000 tokens
- **Total cost**: ~$0.03 per 100 pages with gpt-4o-mini

