Search a workspace's articles and changelog
:::openapi-operation GET /api/v1/workspaces/{workspace}/search AUTH bearerAuth :::
Returns an object with results. An article hit has a slug, a changelog hit has an id, and every hit has a status, a url and a plain-text snippet. When nothing matches, suggestions holds up to 3 articles with close titles. A page that people and agents opened after similar searches ranks higher, and its hit has learned set to true. Without a key, the search finds only the articles that an anonymous reader can open, and it returns no suggestions. Send question with the question of the user, so the docs team sees what agents ask.
:::codesamples open Code examples
curl -X GET "https://contextowl.co/api/v1/workspaces/string/search?limit=0&published_only=true&q=string&question=string&semantic=true" \
-H "Accept: application/json" \
-H "Authorization: Bearer <token>"
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://contextowl.co/api/v1/workspaces/string/search?limit=0&published_only=true&q=string&question=string&semantic=true"))
.header("Accept", "application/json")
.header("Authorization", "Bearer <token>")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}
import urllib.request
url = "https://contextowl.co/api/v1/workspaces/string/search?limit=0&published_only=true&q=string&question=string&semantic=true"
headers = {
"Accept": "application/json",
"Authorization": "Bearer <token>",
}
data = None
req = urllib.request.Request(url, data=data, headers=headers, method="GET")
with urllib.request.urlopen(req) as res:
print(res.status)
print(res.read().decode())
const response = await fetch("https://contextowl.co/api/v1/workspaces/string/search?limit=0&published_only=true&q=string&question=string&semantic=true", {
method: "GET",
headers: {
"Accept": "application/json",
"Authorization": "Bearer <token>",
}
});
console.log(response.status);
console.log(await response.json());
package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://contextowl.co/api/v1/workspaces/string/search?limit=0&published_only=true&q=string&question=string&semantic=true", nil)
if err != nil {
panic(err)
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Authorization", "Bearer <token>")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
bodyBytes, err := io.ReadAll(io.LimitReader(res.Body, 10<<20))
if err != nil {
panic(err)
}
fmt.Println(res.StatusCode)
fmt.Println(string(bodyBytes))
}
// cargo add reqwest --features blocking
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::blocking::Client::new();
let response = client.request(reqwest::Method::GET, "https://contextowl.co/api/v1/workspaces/string/search?limit=0&published_only=true&q=string&question=string&semantic=true")
.header("Accept", "application/json")
.header("Authorization", "Bearer <token>")
.send()?;
println!("{}", response.status());
println!("{}", response.text()?);
Ok(())
}
:::
:::details open Parameters (6)
| NAME | IN | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|---|
workspace |
path | string | yes | Workspace id, or - for the key's bound workspace |
q |
query | string | yes | Search text. The search uses the first 256 characters |
question |
query | string | no | The question of the user in the user's own words, without names, email addresses or secrets. The docs team sees it, so it can write the docs that agents miss. The search uses query, not question. The first 256 characters are kept |
limit |
query | integer | no | Maximum number of hits, 1 to 50. The default is 10. In semantic mode, up to this number of matching changelog entries follow the article hits |
semantic |
query | boolean | no | Rank articles by meaning. Without embeddings the search is full-text and semantic is false |
published_only |
query | boolean | no | Leave out DRAFT and IN REVIEW articles. When GET /api/v1/me shows readsDrafts false, the result never holds them |
:::
:::details open Success responses (200)
200
Success
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
results |
array items: SearchHit object | yes | - |
semantic |
boolean | yes | - |
suggestions |
array items: ArticleSuggestion object | no | - |
{
"results": [
{
"anchor": "string",
"id": 0,
"learned": true,
"publishedAt": "string",
"revision": "string",
"score": 0,
"section": "string",
"sectionKey": "string",
"sectionUrl": "string",
"slug": "string",
"snippet": "string",
"status": "string",
"title": "string",
"type": "string",
"updatedAt": "string",
"url": "string"
}
],
"semantic": true,
"suggestions": [
{
"slug": "string",
"title": "string",
"url": "string"
}
]
}
:::
:::details Error responses (400, 401, 403, 404, 429, 500)
400
invalid_request: a parameter or the body is not valid.
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
error |
object | yes | - |
{
"error": {
"code": "string",
"details": null,
"message": "string",
"status": 0
}
}
401
unauthorized: the access key is missing, invalid or expired.
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
error |
object | yes | - |
{
"error": {
"code": "string",
"details": null,
"message": "string",
"status": 0
}
}
403
permission_denied: the key lacks the permission. two_factor_required: the org requires admins to turn on two-factor authentication.
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
error |
object | yes | - |
{
"error": {
"code": "string",
"details": null,
"message": "string",
"status": 0
}
}
404
not_found: the object does not exist, or the key cannot reach it.
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
error |
object | yes | - |
{
"error": {
"code": "string",
"details": null,
"message": "string",
"status": 0
}
}
429
rate_limited: too many requests. Wait for the time in the Retry-After header.
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
error |
object | yes | - |
{
"error": {
"code": "string",
"details": null,
"message": "string",
"status": 0
}
}
500
internal: the server failed.
Content-Type: application/json
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
error |
object | yes | - |
{
"error": {
"code": "string",
"details": null,
"message": "string",
"status": 0
}
}
:::