## Accessing citations

The Chat endpoint generates fine-grained citations for its RAG response. This capability is included out-of-the-box with the Command family of models.

The following sections describe how to access the citations in both the non-streaming and streaming modes.

### Non-streaming

First, define the documents to be passed as the context of the model's response.

::::tabs
:::tab{title="Cohere platform"}
```python PYTHON
# ! pip install -U cohere
import cohere
import json

co = cohere.ClientV2(
    "COHERE_API_KEY"
)  # Get your free API key here: https://dashboard.cohere.com/api-keys
```
:::

:::tab{title="Private deployment"}
```python PYTHON
# ! pip install -U cohere
import cohere

co = cohere.ClientV2(
    api_key="",  # Leave this blank
    base_url="<YOUR_DEPLOYMENT_URL>",
)

```
:::
::::

```python PYTHON
documents = [
    {
        "data": {
            "title": "Tall penguins",
            "snippet": "Emperor penguins are the tallest.",
        }
    },
    {
        "data": {
            "title": "Penguin habitats",
            "snippet": "Emperor penguins only live in Antarctica.",
        }
    },
]
```

In the non-streaming mode (using `chat` to generate the model response), the citations are provided in the `message.citations` field of the response object.

Each citation object contains:

- `start` and `end`: the start and end indices of the text that cites a source(s)
- `text`: its corresponding span of text
- `sources`: the source(s) that it references

:::code-group
```python PYTHON
messages = [
    {"role": "user", "content": "Where do the tallest penguins live?"}
]

response = co.chat(
    model="command-r-08-2024",
    messages=messages,
    documents=documents,
)

print(response.message.content[0].text)

for citation in response.message.citations:
    print(citation, "\n")

```

```bash cURL
curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer $CO_API_KEY" \
  --data '{
  "model": "command-r-08-2024",
  "messages": [
    {
      "role": "user",
      "content": "Where do the tallest penguins live?"
    }
  ],
  "documents": [
    {
      "data": {
        "title": "Tall penguins",
        "snippet": "Emperor penguins are the tallest."
      }
    },
    {
      "data": {
        "title": "Penguin habitats",
        "snippet": "Emperor penguins only live in Antarctica."
      }
    }
  ]
}'
```
:::

Example response:

```mdx wordWrap
The tallest penguins are the Emperor penguins. They only live in Antarctica.

start=29 end=46 text='Emperor penguins.' sources=[DocumentSource(type='document', id='doc:0', document={'id': 'doc:0', 'snippet': 'Emperor penguins are the tallest.', 'title': 'Tall penguins'})] type='TEXT_CONTENT' 

start=65 end=76 text='Antarctica.' sources=[DocumentSource(type='document', id='doc:1', document={'id': 'doc:1', 'snippet': 'Emperor penguins only live in Antarctica.', 'title': 'Penguin habitats'})] type='TEXT_CONTENT' 

```

### Streaming

In a streaming scenario (using `chat_stream` to generate the model response), the citations are provided in the `citation-start` events.

Each citation object contains the same fields as the [non-streaming scenario](#non-streaming).

:::code-group
```python PYTHON
messages = [
    {"role": "user", "content": "Where do the tallest penguins live?"}
]

response = co.chat_stream(
    model="command-a-plus-05-2026",
    messages=messages,
    documents=documents,
)

response_text = ""
citations = []
for chunk in response:
    if chunk:
        if chunk.type == "content-delta":
            response_text += chunk.delta.message.content.text
            print(chunk.delta.message.content.text, end="")
        if chunk.type == "citation-start":
            citations.append(chunk.delta.message.citations)

for citation in citations:
    print(citation, "\n")

```

```bash cURL
curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: text/event-stream' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer $CO_API_KEY" \
  --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "Where do the tallest penguins live?"
    }
  ],
  "documents": [
    {
      "data": {
        "title": "Tall penguins",
        "snippet": "Emperor penguins are the tallest."
      }
    },
    {
      "data": {
        "title": "Penguin habitats",
        "snippet": "Emperor penguins only live in Antarctica."
      }
    }
  ],
  "stream": true
}'
```
:::

Example response:

```mdx wordWrap
The tallest penguins are the Emperor penguins, which only live in Antarctica.

start=29 end=45 text='Emperor penguins' sources=[DocumentSource(type='document', id='doc:0', document={'id': 'doc:0', 'snippet': 'Emperor penguins are the tallest.', 'title': 'Tall penguins'})] type='TEXT_CONTENT' 

start=66 end=77 text='Antarctica.' sources=[DocumentSource(type='document', id='doc:1', document={'id': 'doc:1', 'snippet': 'Emperor penguins only live in Antarctica.', 'title': 'Penguin habitats'})] type='TEXT_CONTENT' 
```

## Document ID

When passing the documents as context, you can optionally add custom IDs to the `id` field in the `document` object. These IDs will be used by the endpoint as the citation reference.

If you don't provide the `id` field, the ID will be auto-generated in the the format of `doc:<auto_generated_id>`. Example: `doc:0`.

Here is an example of using custom IDs. Here, we are adding custom IDs `100` and `101` to each of the two documents we are passing as context.

```python PYTHON
# ! pip install -U cohere
import cohere
import json

co = cohere.ClientV2(
    "COHERE_API_KEY"
)  # Get your free API key here: https://dashboard.cohere.com/api-keys

documents = [
    {
        "data": {
            "title": "Tall penguins",
            "snippet": "Emperor penguins are the tallest.",
        },
        "id": "100",
    },
    {
        "data": {
            "title": "Penguin habitats",
            "snippet": "Emperor penguins only live in Antarctica.",
        },
        "id": "101",
    },
]
```

When document IDs are provided, the citation will refer to the documents using these IDs.

:::code-group
```python PYTHON
messages = [
    {"role": "user", "content": "Where do the tallest penguins live?"}
]

response = co.chat(
    model="command-a-plus-05-2026",
    messages=messages,
    documents=documents,
)

print(response.message.content[0].text)

```

```bash cURL
curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer $CO_API_KEY" \
  --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "Where do the tallest penguins live?"
    }
  ],
  "documents": [
    {
      "data": {
        "title": "Tall penguins",
        "snippet": "Emperor penguins are the tallest."
      },
      "id": "100"
    },
    {
      "data": {
        "title": "Penguin habitats",
        "snippet": "Emperor penguins only live in Antarctica."
      },
      "id": "101"
    }
  ]
}'
```
:::

Note the `id` fields in the citations, which refer to the IDs in the `document` object.

Example response:

```mdx wordWrap
The tallest penguins are the Emperor penguins, which only live in Antarctica.

start=29 end=45 text='Emperor penguins' sources=[DocumentSource(type='document', id='100', document={'id': '100', 'snippet': 'Emperor penguins are the tallest.', 'title': 'Tall penguins'})] type='TEXT_CONTENT' 

start=66 end=77 text='Antarctica.' sources=[DocumentSource(type='document', id='101', document={'id': '101', 'snippet': 'Emperor penguins only live in Antarctica.', 'title': 'Penguin habitats'})] type='TEXT_CONTENT' 
```

In contrast, here's an example citation when the IDs are not provided.

Example response:

```mdx wordWrap
The tallest penguins are the Emperor penguins, which only live in Antarctica.

start=29 end=45 text='Emperor penguins' sources=[DocumentSource(type='document', id='doc:0', document={'id': 'doc:0', 'snippet': 'Emperor penguins are the tallest.', 'title': 'Tall penguins'})] type='TEXT_CONTENT' 

start=66 end=77 text='Antarctica.' sources=[DocumentSource(type='document', id='doc:1', document={'id': 'doc:1', 'snippet': 'Emperor penguins only live in Antarctica.', 'title': 'Penguin habitats'})] type='TEXT_CONTENT' 

```

## Citation modes

When running RAG in streaming mode, it’s possible to configure how citations are generated and presented. You can choose between fast citations or accurate citations, depending on your latency and precision needs.

### Accurate citations

The model produces its answer first, and then, after the entire response is generated, it provides citations that map to specific segments of the response text. This approach may incur slightly higher latency, but it ensures the citation indices are more precisely aligned with the final text segments of the model’s answer.

This is the default option, or you can explicitly specify it by adding the `citation_options={"mode": "accurate"}` argument in the API call.

Here is an example using the same list of pre-defined `messages` as the above.

With the `citation_options` mode set to `accurate`, we get the citations after the entire response is generated.

:::code-group
```python PYTHON
documents = [
    {
        "data": {
            "title": "Tall penguins",
            "snippet": "Emperor penguins are the tallest.",
        },
        "id": "100",
    },
    {
        "data": {
            "title": "Penguin habitats",
            "snippet": "Emperor penguins only live in Antarctica.",
        },
        "id": "101",
    },
]

messages = [
    {"role": "user", "content": "Where do the tallest penguins live?"}
]

response = co.chat_stream(
    model="command-a-plus-05-2026",
    messages=messages,
    documents=documents,
    citation_options={"mode": "fast"},
)

response_text = ""
citations = []
for chunk in response:
    if chunk:
        if chunk.type == "content-delta":
            response_text += chunk.delta.message.content.text
            print(chunk.delta.message.content.text, end="")
        if chunk.type == "citation-start":
            citations.append(chunk.delta.message.citations)

print("\n")
for citation in citations:
    print(citation, "\n")

```

```bash cURL
curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: text/event-stream' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer $CO_API_KEY" \
  --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "Where do the tallest penguins live?"
    }
  ],
  "documents": [
    {
      "data": {
        "title": "Tall penguins",
        "snippet": "Emperor penguins are the tallest."
      },
      "id": "100"
    },
    {
      "data": {
        "title": "Penguin habitats",
        "snippet": "Emperor penguins only live in Antarctica."
      },
      "id": "101"
    }
  ],
  "citation_options": {
    "mode": "fast"
  },
  "stream": true
}'
```
:::

Example response:

```mdx wordWrap
The tallest penguins are the Emperor penguins. They live in Antarctica.

start=29 end=46 text='Emperor penguins.' sources=[DocumentSource(type='document', id='100', document={'id': '100', 'snippet': 'Emperor penguins are the tallest.', 'title': 'Tall penguins'})] type='TEXT_CONTENT' 

start=60 end=71 text='Antarctica.' sources=[DocumentSource(type='document', id='101', document={'id': '101', 'snippet': 'Emperor penguins only live in Antarctica.', 'title': 'Penguin habitats'})] type='TEXT_CONTENT' 

```

### Fast citations

The model generates citations inline, as the response is being produced. In streaming mode, you will see citations injected at the exact moment the model uses a particular piece of external context. This approach provides immediate traceability at the expense of slightly less precision in citation relevance.

You can specify it by adding the `citation_options={"mode": "fast"}` argument in the API call.

With the `citation_options` mode set to `fast`, we get the citations inline as the model generates the response.

:::code-group
```python PYTHON
documents = [
    {
        "data": {
            "title": "Tall penguins",
            "snippet": "Emperor penguins are the tallest.",
        },
        "id": "100",
    },
    {
        "data": {
            "title": "Penguin habitats",
            "snippet": "Emperor penguins only live in Antarctica.",
        },
        "id": "101",
    },
]

messages = [
    {"role": "user", "content": "Where do the tallest penguins live?"}
]

response = co.chat_stream(
    model="command-a-plus-05-2026",
    messages=messages,
    documents=documents,
    citation_options={"mode": "fast"},
)

response_text = ""
for chunk in response:
    if chunk:
        if chunk.type == "content-delta":
            response_text += chunk.delta.message.content.text
            print(chunk.delta.message.content.text, end="")
        if chunk.type == "citation-start":
            print(
                f" [{chunk.delta.message.citations.sources[0].id}]",
                end="",
            )
```

```bash cURL
curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: text/event-stream' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer $CO_API_KEY" \
  --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "Where do the tallest penguins live?"
    }
  ],
  "documents": [
    {
      "data": {
        "title": "Tall penguins",
        "snippet": "Emperor penguins are the tallest."
      },
      "id": "100"
    },
    {
      "data": {
        "title": "Penguin habitats",
        "snippet": "Emperor penguins only live in Antarctica."
      },
      "id": "101"
    }
  ],
  "citation_options": {
    "mode": "fast"
  },
  "stream": true
}'
```
:::

Example response:

```mdx wordWrap
The tallest penguins [100] are the Emperor penguins [100] which only live in Antarctica. [101]
```

## Related pages

- [Retrieval Augmented Generation (RAG)](./text-generation-v2-rag-retrieval-augmented-generation-rag.md)
- [End-to-end example of RAG with Chat, Embed, and Rerank](./text-generation-v2-rag-rag-complete-example.md)
- [RAG Streaming](./text-generation-v2-rag-rag-streaming.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
