Exa Contents
curl --request POST \
--url https://api.novita.ai/v3/exa/contents \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"urls": [
"<string>"
],
"ids": [
"<string>"
],
"compliance": "<string>",
"text": {
"maxCharacters": 123,
"includeHtmlTags": true,
"verbosity": "<string>",
"includeSections": [
"<string>"
],
"excludeSections": [
"<string>"
]
},
"highlights": {
"query": "<string>",
"maxCharacters": 123
},
"summary": {
"query": "<string>",
"schema": {}
},
"extras": {
"links": 123,
"imageLinks": 123,
"richImageLinks": 123,
"richLinks": 123,
"codeBlocks": 123
},
"livecrawlTimeout": 123,
"maxAgeHours": 123,
"subpages": 123,
"subpageTarget": [
"<string>"
]
}
'import requests
url = "https://api.novita.ai/v3/exa/contents"
payload = {
"urls": ["<string>"],
"ids": ["<string>"],
"compliance": "<string>",
"text": {
"maxCharacters": 123,
"includeHtmlTags": True,
"verbosity": "<string>",
"includeSections": ["<string>"],
"excludeSections": ["<string>"]
},
"highlights": {
"query": "<string>",
"maxCharacters": 123
},
"summary": {
"query": "<string>",
"schema": {}
},
"extras": {
"links": 123,
"imageLinks": 123,
"richImageLinks": 123,
"richLinks": 123,
"codeBlocks": 123
},
"livecrawlTimeout": 123,
"maxAgeHours": 123,
"subpages": 123,
"subpageTarget": ["<string>"]
}
headers = {
"Content-Type": "<content-type>",
"Authorization": "<authorization>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': '<content-type>', Authorization: '<authorization>'},
body: JSON.stringify({
urls: ['<string>'],
ids: ['<string>'],
compliance: '<string>',
text: {
maxCharacters: 123,
includeHtmlTags: true,
verbosity: '<string>',
includeSections: ['<string>'],
excludeSections: ['<string>']
},
highlights: {query: '<string>', maxCharacters: 123},
summary: {query: '<string>', schema: {}},
extras: {
links: 123,
imageLinks: 123,
richImageLinks: 123,
richLinks: 123,
codeBlocks: 123
},
livecrawlTimeout: 123,
maxAgeHours: 123,
subpages: 123,
subpageTarget: ['<string>']
})
};
fetch('https://api.novita.ai/v3/exa/contents', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.novita.ai/v3/exa/contents",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'urls' => [
'<string>'
],
'ids' => [
'<string>'
],
'compliance' => '<string>',
'text' => [
'maxCharacters' => 123,
'includeHtmlTags' => true,
'verbosity' => '<string>',
'includeSections' => [
'<string>'
],
'excludeSections' => [
'<string>'
]
],
'highlights' => [
'query' => '<string>',
'maxCharacters' => 123
],
'summary' => [
'query' => '<string>',
'schema' => [
]
],
'extras' => [
'links' => 123,
'imageLinks' => 123,
'richImageLinks' => 123,
'richLinks' => 123,
'codeBlocks' => 123
],
'livecrawlTimeout' => 123,
'maxAgeHours' => 123,
'subpages' => 123,
'subpageTarget' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.novita.ai/v3/exa/contents"
payload := strings.NewReader("{\n \"urls\": [\n \"<string>\"\n ],\n \"ids\": [\n \"<string>\"\n ],\n \"compliance\": \"<string>\",\n \"text\": {\n \"maxCharacters\": 123,\n \"includeHtmlTags\": true,\n \"verbosity\": \"<string>\",\n \"includeSections\": [\n \"<string>\"\n ],\n \"excludeSections\": [\n \"<string>\"\n ]\n },\n \"highlights\": {\n \"query\": \"<string>\",\n \"maxCharacters\": 123\n },\n \"summary\": {\n \"query\": \"<string>\",\n \"schema\": {}\n },\n \"extras\": {\n \"links\": 123,\n \"imageLinks\": 123,\n \"richImageLinks\": 123,\n \"richLinks\": 123,\n \"codeBlocks\": 123\n },\n \"livecrawlTimeout\": 123,\n \"maxAgeHours\": 123,\n \"subpages\": 123,\n \"subpageTarget\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "<content-type>")
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.novita.ai/v3/exa/contents")
.header("Content-Type", "<content-type>")
.header("Authorization", "<authorization>")
.body("{\n \"urls\": [\n \"<string>\"\n ],\n \"ids\": [\n \"<string>\"\n ],\n \"compliance\": \"<string>\",\n \"text\": {\n \"maxCharacters\": 123,\n \"includeHtmlTags\": true,\n \"verbosity\": \"<string>\",\n \"includeSections\": [\n \"<string>\"\n ],\n \"excludeSections\": [\n \"<string>\"\n ]\n },\n \"highlights\": {\n \"query\": \"<string>\",\n \"maxCharacters\": 123\n },\n \"summary\": {\n \"query\": \"<string>\",\n \"schema\": {}\n },\n \"extras\": {\n \"links\": 123,\n \"imageLinks\": 123,\n \"richImageLinks\": 123,\n \"richLinks\": 123,\n \"codeBlocks\": 123\n },\n \"livecrawlTimeout\": 123,\n \"maxAgeHours\": 123,\n \"subpages\": 123,\n \"subpageTarget\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.novita.ai/v3/exa/contents")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = '<content-type>'
request["Authorization"] = '<authorization>'
request.body = "{\n \"urls\": [\n \"<string>\"\n ],\n \"ids\": [\n \"<string>\"\n ],\n \"compliance\": \"<string>\",\n \"text\": {\n \"maxCharacters\": 123,\n \"includeHtmlTags\": true,\n \"verbosity\": \"<string>\",\n \"includeSections\": [\n \"<string>\"\n ],\n \"excludeSections\": [\n \"<string>\"\n ]\n },\n \"highlights\": {\n \"query\": \"<string>\",\n \"maxCharacters\": 123\n },\n \"summary\": {\n \"query\": \"<string>\",\n \"schema\": {}\n },\n \"extras\": {\n \"links\": 123,\n \"imageLinks\": 123,\n \"richImageLinks\": 123,\n \"richLinks\": 123,\n \"codeBlocks\": 123\n },\n \"livecrawlTimeout\": 123,\n \"maxAgeHours\": 123,\n \"subpages\": 123,\n \"subpageTarget\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"requestId": "string",
"results": [
{
"id": "string",
"title": "string",
"url": "string",
"publishedDate": "string",
"author": "string",
"image": "string",
"favicon": "string",
"text": "string",
"highlights": ["string"],
"summary": "string",
"subpages": [
{
"title": "string",
"url": "string",
"publishedDate": "string",
"author": "string",
"id": "string",
"image": "string",
"favicon": "string"
}
],
"extras": {
"links": ["string"],
"imageLinks": ["string"],
"richImageLinks": [{}],
"richLinks": [{}],
"codeBlocks": [{"text": "string", "source": "string"}]
},
"entities": [
{
"id": "string",
"type": "string",
"version": 0,
"properties": {}
}
]
}
],
"statuses": [
{
"id": "string",
"status": "string",
"source": "string",
"error": {
"tag": "string",
"httpStatusCode": 0
}
}
],
"searchTime": 0
}
{
"code": 400,
"reason": "INVALID_REQUEST_BODY",
"message": "Invalid request body | Validation error: must provide either ids or urls",
"metadata": {
"trace_id": "a4d532f86200dc7bb0df7fa6023860ca"
}
}
{
"code": 403,
"reason": "INVALID_API_KEY",
"message": "invalid api-key",
"metadata": {}
}
{
"code": 404,
"reason": "PATH_NOT_FOUND",
"message": "path not found for model",
"metadata": {
"trace_id": "3c3433f0cb475a04f9a4969b8c6ed903"
}
}
{
"code": 429,
"reason": "RATE_LIMIT_EXCEEDED",
"message": "rate limit exceeded, please retry later",
"metadata": {
"trace_id": "5f2a9c7e41b8d0a36e9f4c2b7d81a0e5"
}
}
{
"code": 500,
"reason": "TASK_FAILED",
"message": "upstream provider temporarily unavailable, please retry",
"metadata": {
"trace_id": "8846379c692d7218173460afe95640f1"
}
}
{
"code": 503,
"reason": "SERVICE_UNAVAILABLE",
"message": "service temporarily unavailable",
"metadata": {
"trace_id": "b7e3f1a9d24c05e8f63a1b9c7e05d2f4"
}
}
Exa
Exa Contents
POST
/
v3
/
exa
/
contents
Exa Contents
curl --request POST \
--url https://api.novita.ai/v3/exa/contents \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"urls": [
"<string>"
],
"ids": [
"<string>"
],
"compliance": "<string>",
"text": {
"maxCharacters": 123,
"includeHtmlTags": true,
"verbosity": "<string>",
"includeSections": [
"<string>"
],
"excludeSections": [
"<string>"
]
},
"highlights": {
"query": "<string>",
"maxCharacters": 123
},
"summary": {
"query": "<string>",
"schema": {}
},
"extras": {
"links": 123,
"imageLinks": 123,
"richImageLinks": 123,
"richLinks": 123,
"codeBlocks": 123
},
"livecrawlTimeout": 123,
"maxAgeHours": 123,
"subpages": 123,
"subpageTarget": [
"<string>"
]
}
'import requests
url = "https://api.novita.ai/v3/exa/contents"
payload = {
"urls": ["<string>"],
"ids": ["<string>"],
"compliance": "<string>",
"text": {
"maxCharacters": 123,
"includeHtmlTags": True,
"verbosity": "<string>",
"includeSections": ["<string>"],
"excludeSections": ["<string>"]
},
"highlights": {
"query": "<string>",
"maxCharacters": 123
},
"summary": {
"query": "<string>",
"schema": {}
},
"extras": {
"links": 123,
"imageLinks": 123,
"richImageLinks": 123,
"richLinks": 123,
"codeBlocks": 123
},
"livecrawlTimeout": 123,
"maxAgeHours": 123,
"subpages": 123,
"subpageTarget": ["<string>"]
}
headers = {
"Content-Type": "<content-type>",
"Authorization": "<authorization>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': '<content-type>', Authorization: '<authorization>'},
body: JSON.stringify({
urls: ['<string>'],
ids: ['<string>'],
compliance: '<string>',
text: {
maxCharacters: 123,
includeHtmlTags: true,
verbosity: '<string>',
includeSections: ['<string>'],
excludeSections: ['<string>']
},
highlights: {query: '<string>', maxCharacters: 123},
summary: {query: '<string>', schema: {}},
extras: {
links: 123,
imageLinks: 123,
richImageLinks: 123,
richLinks: 123,
codeBlocks: 123
},
livecrawlTimeout: 123,
maxAgeHours: 123,
subpages: 123,
subpageTarget: ['<string>']
})
};
fetch('https://api.novita.ai/v3/exa/contents', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.novita.ai/v3/exa/contents",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'urls' => [
'<string>'
],
'ids' => [
'<string>'
],
'compliance' => '<string>',
'text' => [
'maxCharacters' => 123,
'includeHtmlTags' => true,
'verbosity' => '<string>',
'includeSections' => [
'<string>'
],
'excludeSections' => [
'<string>'
]
],
'highlights' => [
'query' => '<string>',
'maxCharacters' => 123
],
'summary' => [
'query' => '<string>',
'schema' => [
]
],
'extras' => [
'links' => 123,
'imageLinks' => 123,
'richImageLinks' => 123,
'richLinks' => 123,
'codeBlocks' => 123
],
'livecrawlTimeout' => 123,
'maxAgeHours' => 123,
'subpages' => 123,
'subpageTarget' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.novita.ai/v3/exa/contents"
payload := strings.NewReader("{\n \"urls\": [\n \"<string>\"\n ],\n \"ids\": [\n \"<string>\"\n ],\n \"compliance\": \"<string>\",\n \"text\": {\n \"maxCharacters\": 123,\n \"includeHtmlTags\": true,\n \"verbosity\": \"<string>\",\n \"includeSections\": [\n \"<string>\"\n ],\n \"excludeSections\": [\n \"<string>\"\n ]\n },\n \"highlights\": {\n \"query\": \"<string>\",\n \"maxCharacters\": 123\n },\n \"summary\": {\n \"query\": \"<string>\",\n \"schema\": {}\n },\n \"extras\": {\n \"links\": 123,\n \"imageLinks\": 123,\n \"richImageLinks\": 123,\n \"richLinks\": 123,\n \"codeBlocks\": 123\n },\n \"livecrawlTimeout\": 123,\n \"maxAgeHours\": 123,\n \"subpages\": 123,\n \"subpageTarget\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "<content-type>")
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.novita.ai/v3/exa/contents")
.header("Content-Type", "<content-type>")
.header("Authorization", "<authorization>")
.body("{\n \"urls\": [\n \"<string>\"\n ],\n \"ids\": [\n \"<string>\"\n ],\n \"compliance\": \"<string>\",\n \"text\": {\n \"maxCharacters\": 123,\n \"includeHtmlTags\": true,\n \"verbosity\": \"<string>\",\n \"includeSections\": [\n \"<string>\"\n ],\n \"excludeSections\": [\n \"<string>\"\n ]\n },\n \"highlights\": {\n \"query\": \"<string>\",\n \"maxCharacters\": 123\n },\n \"summary\": {\n \"query\": \"<string>\",\n \"schema\": {}\n },\n \"extras\": {\n \"links\": 123,\n \"imageLinks\": 123,\n \"richImageLinks\": 123,\n \"richLinks\": 123,\n \"codeBlocks\": 123\n },\n \"livecrawlTimeout\": 123,\n \"maxAgeHours\": 123,\n \"subpages\": 123,\n \"subpageTarget\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.novita.ai/v3/exa/contents")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = '<content-type>'
request["Authorization"] = '<authorization>'
request.body = "{\n \"urls\": [\n \"<string>\"\n ],\n \"ids\": [\n \"<string>\"\n ],\n \"compliance\": \"<string>\",\n \"text\": {\n \"maxCharacters\": 123,\n \"includeHtmlTags\": true,\n \"verbosity\": \"<string>\",\n \"includeSections\": [\n \"<string>\"\n ],\n \"excludeSections\": [\n \"<string>\"\n ]\n },\n \"highlights\": {\n \"query\": \"<string>\",\n \"maxCharacters\": 123\n },\n \"summary\": {\n \"query\": \"<string>\",\n \"schema\": {}\n },\n \"extras\": {\n \"links\": 123,\n \"imageLinks\": 123,\n \"richImageLinks\": 123,\n \"richLinks\": 123,\n \"codeBlocks\": 123\n },\n \"livecrawlTimeout\": 123,\n \"maxAgeHours\": 123,\n \"subpages\": 123,\n \"subpageTarget\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"requestId": "string",
"results": [
{
"id": "string",
"title": "string",
"url": "string",
"publishedDate": "string",
"author": "string",
"image": "string",
"favicon": "string",
"text": "string",
"highlights": ["string"],
"summary": "string",
"subpages": [
{
"title": "string",
"url": "string",
"publishedDate": "string",
"author": "string",
"id": "string",
"image": "string",
"favicon": "string"
}
],
"extras": {
"links": ["string"],
"imageLinks": ["string"],
"richImageLinks": [{}],
"richLinks": [{}],
"codeBlocks": [{"text": "string", "source": "string"}]
},
"entities": [
{
"id": "string",
"type": "string",
"version": 0,
"properties": {}
}
]
}
],
"statuses": [
{
"id": "string",
"status": "string",
"source": "string",
"error": {
"tag": "string",
"httpStatusCode": 0
}
}
],
"searchTime": 0
}
{
"code": 400,
"reason": "INVALID_REQUEST_BODY",
"message": "Invalid request body | Validation error: must provide either ids or urls",
"metadata": {
"trace_id": "a4d532f86200dc7bb0df7fa6023860ca"
}
}
{
"code": 403,
"reason": "INVALID_API_KEY",
"message": "invalid api-key",
"metadata": {}
}
{
"code": 404,
"reason": "PATH_NOT_FOUND",
"message": "path not found for model",
"metadata": {
"trace_id": "3c3433f0cb475a04f9a4969b8c6ed903"
}
}
{
"code": 429,
"reason": "RATE_LIMIT_EXCEEDED",
"message": "rate limit exceeded, please retry later",
"metadata": {
"trace_id": "5f2a9c7e41b8d0a36e9f4c2b7d81a0e5"
}
}
{
"code": 500,
"reason": "TASK_FAILED",
"message": "upstream provider temporarily unavailable, please retry",
"metadata": {
"trace_id": "8846379c692d7218173460afe95640f1"
}
}
{
"code": 503,
"reason": "SERVICE_UNAVAILABLE",
"message": "service temporarily unavailable",
"metadata": {
"trace_id": "b7e3f1a9d24c05e8f63a1b9c7e05d2f4"
}
}
Retrieve page content, summaries, metadata, and fetch statuses for URLs or Exa document IDs. This is a passthrough to Exa’s Get Contents API, exposed through the Novita gateway with a platform route prefix.
To authenticate with your Novita API key, get one from the Novita dashboard. Base URL:
Running the quickstart above returns:
For validation failures,
https://api.novita.ai.
Quickstart
curl -X POST 'https://api.novita.ai/v3/exa/contents' \
-H 'Authorization: Bearer <api_key>' \
-H 'Content-Type: application/json' \
-d '{
"urls": ["https://arxiv.org/abs/1706.03762"],
"text": true
}'
{
"requestId": "0a6bd28991288444b8748646c5bd4bd9",
"results": [
{
"id": "https://arxiv.org/abs/1706.03762",
"title": "Attention Is All You Need",
"url": "https://arxiv.org/abs/1706.03762",
"publishedDate": "2025-08-23T00:00:00.000Z",
"author": "Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, et al.",
"text": "# Attention Is All You Need\n\n2025. Preprint. 6,569 citations.\n\n## Authors\n\n- Ashish Vaswani (Google (United States)): h-index 28; 10,049 citations…",
"entities": [
{
"id": "https://exa.ai/library/publication/985dxcclwqj",
"type": "publication",
"version": 1,
"properties": {
"title": "Attention Is All You Need",
"year": 2025,
"date": "2025-08-23",
"type": "preprint",
"language": "en",
"citationCount": 6569,
"authors": [
{"name": "Ashish Vaswani", "id": null}
]
}
}
]
}
],
"statuses": [
{
"id": "https://arxiv.org/abs/1706.03762",
"status": "success",
"source": "cached"
}
],
"searchTime": 8.12
}
Request Headers
All endpoints require platform API authentication.string
required
Use
application/json.string
default:"Bearer YOUR_API_KEY"
required
Platform API key, formatted as
Bearer YOUR_API_KEY.Request Body
string[]
required
URLs to retrieve. This field is also backwards compatible with values previously supplied through
ids. Range is 1 to 100 entries; each URL may be up to 2048 characters. Provide either urls or ids, but not both — supplying both returns a 400.string[]
Exa document IDs to retrieve. Range is
1 to 100 entries; each ID may be up to 2048 characters. Provide either urls or ids, but not both — supplying both returns a 400.string
Enterprise compliance mode. Only
hipaa is supported.boolean | object
Text extraction options. Default is
false.Show text properties
Show text properties
integer
Maximum number of text characters to return. Range is
1 to 10000.boolean
Include lightweight HTML tags instead of plain text.
string
default:"compact"
Requested text verbosity. One of
compact, standard, or full.string[]
Semantic page sections to keep. Best-effort classification. Each entry is one of
header, navigation, banner, body, sidebar, footer, or metadata.string[]
Semantic page sections to drop. Best-effort classification. Each entry is one of
header, navigation, banner, body, sidebar, footer, or metadata.boolean | object
boolean | object
object
Extra outputs to return from each page.
Show extras properties
Show extras properties
integer
Live crawl timeout in milliseconds. Range is greater than
0 and up to 90000; default is 10000.integer
Maximum cache age in hours. Use
0 for fresh content and -1 to always use cache. Range is -1 to 720.integer
Number of subpages to crawl. Range is
0 to 100; default is 0.string | string[]
Term or terms used to find targeted subpages. String values are limited to 100 characters.
Examples
Extract text and highlights
curl -X POST 'https://api.novita.ai/v3/exa/contents' \
-H 'Authorization: Bearer <api_key>' \
-H 'Content-Type: application/json' \
-d '{
"urls": ["https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching"],
"text": {
"maxCharacters": 4000
},
"highlights": {
"query": "cache invalidation"
}
}'
Summarize a page
Usesummary with a query to get a focused summary instead of raw text.
curl -X POST 'https://api.novita.ai/v3/exa/contents' \
-H 'Authorization: Bearer <api_key>' \
-H 'Content-Type: application/json' \
-d '{
"urls": ["https://en.wikipedia.org/wiki/CRISPR"],
"summary": {
"query": "What is this technology used for?"
}
}'
Include linked subpages
Usesubpages with subpageTarget to also pull related pages the URL links to.
curl -X POST 'https://api.novita.ai/v3/exa/contents' \
-H 'Authorization: Bearer <api_key>' \
-H 'Content-Type: application/json' \
-d '{
"urls": ["https://docs.astro.build"],
"text": true,
"subpages": 3,
"subpageTarget": "installation"
}'
Force fresh content
SetmaxAgeHours to 0 to bypass the cache and live-crawl the page.
curl -X POST 'https://api.novita.ai/v3/exa/contents' \
-H 'Authorization: Bearer <api_key>' \
-H 'Content-Type: application/json' \
-d '{
"urls": ["https://www.githubstatus.com"],
"text": true,
"maxAgeHours": 0
}'
Response
string
Unique request identifier.
object[]
Content results.
Show result properties
Show result properties
string
Page title.
string
Page URL.
string
Published date when available.
string
Author when available.
string
Exa document ID.
string
Associated image URL.
string
Site favicon URL.
string
Extracted text when requested.
string[]
Highlight snippets when requested.
string
Generated summary when requested.
object[]
object
Container for extra page data. Each child field is present only when its matching
extras count is requested, and may be an empty array when the page has no such data.Show extras properties
Show extras properties
string[]
Extracted links when
extras.links is requested.string[]
Image links when
extras.imageLinks is requested.object[]
Rich image links when
extras.richImageLinks is requested.object[]
Rich links when
extras.richLinks is requested.object[]
Structured entities extracted from the page. Each entity is a
company, person, or publication. It may be absent or empty depending on the page.Show entity properties
Show entity properties
string
Stable entity identifier.
string
Entity discriminator. One of
company, person, or publication.integer
Entity schema version.
object
Type-specific fields. The shape depends on
type.Show company properties
Show company properties
string
Company name.
integer
Year the company was founded.
string
Short company description.
object
object
object
Web traffic data.
Show webTraffic properties
Show webTraffic properties
object
Research output.
Show research properties
Show research properties
integer
Number of published works.
integer
Total citations.
string[]
Research areas.
object[]
Notable works.
Show person properties
Show person properties
string
Full name.
string
First name.
string
Last name.
string
Location.
object[]
object[]
object
Research output.
Show research properties
Show research properties
integer
Number of published works.
integer
Total citations.
integer
h-index.
integer
Year of first publication.
integer
Year of most recent publication.
string[]
Research areas.
object[]
Notable works.
Show publication properties
Show publication properties
string
Publication title.
integer
Publication year.
string
Publication date.
string
Publication type. One of
article, book, book-chapter, dataset, dissertation, preprint, report, or review.string
Language.
integer
Number of citations.
integer
Number of references.
string
Abstract text.
object[]
Fetch status for each requested URL or document ID.
Show status properties
Show status properties
string
Requested URL or document ID.
string
Fetch status, such as
success or error.string
Content source, such as
cached or crawled.number
Time taken to serve the request, in milliseconds. Requests served from Exa’s cache (
source: "cached") return in a few milliseconds, while pages that must be crawled live (source: "crawled") typically take on the order of one to several seconds.Errors
Errors are returned as a JSON envelope withcode, reason, message, and metadata. The platform validates and authenticates the request before forwarding it to Exa, so some errors originate at the platform and others are surfaced from upstream.
| Status | reason | Meaning |
|---|---|---|
400 | MISSING_API_KEY | The Authorization header is absent. |
400 | INVALID_REQUEST_BODY | The body failed validation, such as omitting both urls and ids. |
403 | INVALID_API_KEY | The API key is invalid or not authorized. |
404 | PATH_NOT_FOUND | The route does not exist. |
429 | RATE_LIMIT_EXCEEDED | Too many requests. Slow down and retry with backoff. |
500 | TASK_FAILED | Internal or upstream provider failure. Transient failures are safe to retry. |
503 | SERVICE_UNAVAILABLE | The service is temporarily overloaded or down. Retry with backoff. |
message is a JSON-encoded string carrying the detailed error and tag. The examples below show that inner detail decoded for readability.
{
"requestId": "string",
"results": [
{
"id": "string",
"title": "string",
"url": "string",
"publishedDate": "string",
"author": "string",
"image": "string",
"favicon": "string",
"text": "string",
"highlights": ["string"],
"summary": "string",
"subpages": [
{
"title": "string",
"url": "string",
"publishedDate": "string",
"author": "string",
"id": "string",
"image": "string",
"favicon": "string"
}
],
"extras": {
"links": ["string"],
"imageLinks": ["string"],
"richImageLinks": [{}],
"richLinks": [{}],
"codeBlocks": [{"text": "string", "source": "string"}]
},
"entities": [
{
"id": "string",
"type": "string",
"version": 0,
"properties": {}
}
]
}
],
"statuses": [
{
"id": "string",
"status": "string",
"source": "string",
"error": {
"tag": "string",
"httpStatusCode": 0
}
}
],
"searchTime": 0
}
{
"code": 400,
"reason": "INVALID_REQUEST_BODY",
"message": "Invalid request body | Validation error: must provide either ids or urls",
"metadata": {
"trace_id": "a4d532f86200dc7bb0df7fa6023860ca"
}
}
{
"code": 403,
"reason": "INVALID_API_KEY",
"message": "invalid api-key",
"metadata": {}
}
{
"code": 404,
"reason": "PATH_NOT_FOUND",
"message": "path not found for model",
"metadata": {
"trace_id": "3c3433f0cb475a04f9a4969b8c6ed903"
}
}
{
"code": 429,
"reason": "RATE_LIMIT_EXCEEDED",
"message": "rate limit exceeded, please retry later",
"metadata": {
"trace_id": "5f2a9c7e41b8d0a36e9f4c2b7d81a0e5"
}
}
{
"code": 500,
"reason": "TASK_FAILED",
"message": "upstream provider temporarily unavailable, please retry",
"metadata": {
"trace_id": "8846379c692d7218173460afe95640f1"
}
}
{
"code": 503,
"reason": "SERVICE_UNAVAILABLE",
"message": "service temporarily unavailable",
"metadata": {
"trace_id": "b7e3f1a9d24c05e8f63a1b9c7e05d2f4"
}
}
Notes
- All request bodies are JSON.
- Extra Exa parameters not listed here may be passed through.
- Response shapes can vary depending on request options.
- This document intentionally omits billing-related fields.
References
For more details, see the Exa Contents API reference.Last modified on July 30, 2026
Was this page helpful?
⌘I