Skip to main content
Lesson 16 of 16 · Responses API: Primary Endpoint

Automatic Citations and Best Practices

Lesson 16 of 16 Updated July 30, 2026 Developer
On this page
  1. Sourced and Reliable Responses
  2. How Citations Work
  3. Display Citations in Your Application
  4. Production Best Practices
  5. Deployment Checklist
  6. Key Takeaways
  7. Test Your Knowledge

Sourced and Reliable Responses

When the model uses web search or X search, the Responses API automatically includes citations in the response. These citations let your users verify sources and build trust in generated answers.

How Citations Work

Citations appear in the annotations array of each content item:

{
  "output": [{
    "type": "message",
    "content": [{
      "type": "output_text",
      "text": "According to the latest data, the AI market...",
      "annotations": [
        {
          "type": "url_citation",
          "url": "https://example.com/article",
          "title": "AI Market Analysis in 2026",
          "start_index": 35,
          "end_index": 68
        }
      ]
    }]
  }]
}

Citation Fields

FieldDescription
typeAlways url_citation
urlSource URL
titleSource page title
start_indexStart position in text
end_indexEnd position in text

Display Citations in Your Application

response = client.responses.create(
    model="grok-4.20-0309-reasoning",
    input="What are the latest advancements in AI?",
    tools=[{"type": "web_search"}]
)

text = response.output[0].content[0].text
annotations = response.output[0].content[0].annotations

# Build text with footnotes
footnotes = []
for i, ann in enumerate(annotations, 1):
    footnotes.append(f"[{i}] {ann.title} — {ann.url}")

print(text)
print("\n--- Sources ---")
for fn in footnotes:
    print(fn)

In HTML

def render_with_citations(text, annotations):
    # Sort by position (end to start to avoid shifting indices)
    sorted_anns = sorted(annotations, key=lambda a: a.start_index, reverse=True)
    html = text
    for i, ann in enumerate(sorted_anns):
        ref_num = len(sorted_anns) - i
        link = f'<a href="{ann.url}" title="{ann.title}" target="_blank">[{ref_num}]</a>'
        html = html[:ann.end_index] + link + html[ann.end_index:]
    return html

Production Best Practices

1. Always Validate Status

response = client.responses.create(...)
if response.status != "completed":
    handle_error(response)
    return

2. Handle Empty Responses

if not response.output or not response.output[0].content:
    return "The model did not generate a response."
text = response.output[0].content[0].text

3. Log Metrics

For every production request, log:

  • response.id for traceability
  • usage.total_tokens for consumption
  • usage.cost_in_nano_usd for costs
  • Client-side response time
  • Response status

4. Secure Your API Key

  • Store it in an environment variable, never in code
  • Use a secrets manager in production (Vault, AWS Secrets Manager)
  • Rotate your keys regularly
  • Never expose them client-side (browser)

5. Manage Generated Content

Model responses may contain inappropriate content despite filters. Implement a moderation layer if you display responses publicly.

6. Plan for Scalability

  • Use streaming to reduce perceived wait time
  • Implement a queue system for heavy requests
  • Cache frequent responses
  • Monitor your rate limiting quotas

Deployment Checklist

  • Timeout set to 3600 seconds
  • Retry with exponential backoff
  • Client-side rate limiting
  • Log metrics (tokens, costs, latency)
  • Error handling (401, 429, 500, timeout)
  • Secure API key
  • Content moderation if needed
  • Cost monitoring and alerts
  • Circuit breaker for resilience

Key Takeaways

  • Citations are automatic when the model uses web_search or x_search
  • They contain the URL, title, and position in text
  • Always validate status and handle empty responses
  • Secure your API key—never in source code or client-side
  • Implement logging, retry, rate limiting, and monitoring before going to production

Test Your Knowledge

The Responses API in depth: the final check.

1. What does the Responses API offer compared to Chat Completions?

Answer: The modern format: server-side response persistence (GET/DELETE, chaining by ID), built-in tools, and recent features—the API where xAI focuses evolution.

2. How do you chain a conversation?

Answer: By referencing the previous response: context is kept server-side—no need to resend the entire history each turn.

3. What is encrypted reasoning?

Answer: The model’s internal reasoning returned in encrypted form: reusable in following turns without being readable—the thought process travels, confidentiality remains.

4. What does mixing server and client tools allow?

Answer: Combine built-in tools executed by xAI (web search, etc.) and your custom functions executed by your code—each tool in the right place, orchestrated in the same request.

5. What are the best practices for production?

Answer: Handle timeout and retry, track billing (tokens, tools), and leverage automatic citations for verifiable responses—robustness and trust together.

Persistence, tools, encrypted reasoning, citations: the Responses API is the modern foundation—your Grok applications are built here.