Search API
The Search API provides managed full-text search with App Engine Search semantics: structured documents; text, atom, number, date, and geo fields; a boolean query language; facets; sorting; and pagination. All paths below are relative to a search instance you provision in the console.
Authentication and base URL
Send requests to https://api.altengine.net with an organization API key as a bearer token. Reads require a read grant, writes a write grant, and deletes a full grant — see Authentication.
Authorization: Bearer ae_yourkeyid.your-api-key-secretEvery path is scoped to an instance: /v1/search/{instance}/…. Within an instance, documents live in named indexes. An optional namespace partitions data for multi-tenancy; set it with a ?namespace= query parameter or an X-Namespace header (the default namespace is empty).
Endpoints
| Method & path | Purpose |
|---|---|
PUT /v1/search/{instance}/indexes/{index}/documents | Batch put documents (creates the index on first write). |
GET /v1/search/{instance}/indexes/{index}/documents/{id} | Get one document by id. |
GET /v1/search/{instance}/indexes/{index}/documents | List documents in id order. |
POST /v1/search/{instance}/indexes/{index}/documents/delete | Batch delete documents by id. |
POST /v1/search/{instance}/indexes/{index}/search | Run a search query. |
GET /v1/search/{instance}/indexes/{index}/schema | Get the union field schema for an index. |
GET /v1/search/{instance}/indexes | List indexes in the instance. |
DELETE /v1/search/{instance}/indexes/{index} | Drop an index and all its documents. |
Documents
A document has a string id, an optional numeric rank (used as the default sort — descending — when a query specifies no sort), a list of fields, and an optional list of facets. Fields are multi-valued and dynamic: two documents in the same index may carry different fields.
{
"id": "f1",
"rank": 12345,
"fields": [
{ "name": "title", "type": "text", "value": "Up in the Air" },
{ "name": "genre", "type": "atom", "value": "drama" },
{ "name": "rating", "type": "number", "value": 4 },
{ "name": "released", "type": "date", "value": "2009-12-04" },
{ "name": "loc", "type": "geo", "value": { "lat": 37.77, "lng": -122.41 } }
],
"facets": [
{ "name": "genre", "type": "atom", "value": "drama" },
{ "name": "year", "type": "number", "value": 2009 }
]
}Field types
| Type | Description |
|---|---|
text | Tokenized full-text; supports term, phrase, and stem matching. |
html | Like text, but tags are stripped before tokenizing. |
atom | An exact-match string (not tokenized). Up to 500 bytes. |
number | A numeric value; supports range comparisons and sorting. |
date | An YYYY-MM-DD date; supports range comparisons and sorting. |
geo | A { "lat", "lng" } point; supports distance() filtering. |
tokenprefix | Tokenized text with prefix matching (autocomplete over words). |
untokenprefix | Whole-value prefix matching (autocomplete over a full string). |
Put documents
Send up to 200 documents per request. Putting a document with an existing id replaces it. The response returns the ids written.
curl -X PUT https://api.altengine.net/v1/search/catalog/indexes/films/documents \
-H "Authorization: Bearer $ALTENGINE_KEY" \
-H "Content-Type: application/json" \
-d '{ "documents": [ { "id": "f1", "fields": [ { "name": "title", "type": "text", "value": "Up in the Air" } ] } ] }'
# → { "ids": ["f1"] }Get, list, and delete
# Get one document
GET /v1/search/catalog/indexes/films/documents/f1
# → { "document": { … } }
# List documents (id order). Params: start_id, include_start, limit, ids_only
GET /v1/search/catalog/indexes/films/documents?limit=50
# → { "documents": [ … ] } (or { "ids": [ … ] } when ids_only=true)
# Batch delete by id (requires a full grant)
POST /v1/search/catalog/indexes/films/documents/delete
{ "ids": ["f1", "f2"] }
# → { "deleted": 2 }Search
Post a search request to an index. Only query is required; an empty query matches all documents.
{
"query": "genre:comedy rating > 3",
"limit": 20,
"offset": 0,
"ids_only": false,
"returned_fields": ["title", "rating"],
"sort": [{ "expr": "rating", "desc": true, "default": 0 }],
"facet_discover": 5,
"facet_refinements": [{ "name": "genre", "value": "scifi" }],
"total_hits_accuracy": 1000
}Request fields
| Field | Description |
|---|---|
query | The query string (see Query language). Empty matches all. |
limit | Page size. Default 20, max 1000. 0 returns counts and facets only. |
offset | Result offset. Max 1000. Prefer cursor for deep pagination. |
cursor | Opaque cursor from a prior response's cursor field; fetches the next page. |
ids_only | When true, results omit the document body and return ids only. |
returned_fields | Restrict returned documents to these field names. |
sort | Array of { expr, desc, default }; sorts by a field or expression. Falls back to rank. |
facet_discover | Auto-discover up to N of the most common facets over the matches. |
facet_refinements | Array of { name, value } to constrain results to a facet value. |
total_hits_accuracy | Count matches exactly up to this many. Default 20, max 10000. |
Response
{
"total_hits": 42,
"total_hits_exact": true,
"returned": 1,
"results": [
{
"id": "f1",
"rank": 12345,
"score": 1.7,
"document": {
"id": "f1",
"fields": [
{ "name": "title", "type": "text", "value": "Up in the Air" }
]
}
}
],
"cursor": "eyJvIjoyMH0",
"facets": [
{
"name": "genre",
"type": "atom",
"values": [
{ "value": "drama", "count": 12 },
{ "value": "comedy", "count": 8 }
]
}
]
}total_hits is the number of matches, counted exactly only up to total_hits_accuracy. When total_hits_exact is false, total_hits is a lower bound — render it as "N+". Pagination is independent of the count: a cursor is present whenever more pages remain, so keep following it until it is absent.
Query language
The query language mirrors App Engine's Search syntax. Terms are combined with implicit AND.
| Form | Example |
|---|---|
| Bare term | air |
| Field scope | title:air, genre = "sci fi" |
| Numeric / date compare | rating > 3, released < 2011-02-28 |
| Boolean | comedy OR drama, NOT scifi, -scifi |
| Grouping | genre:(comedy OR drama) |
| Phrase | "very important" |
| Stemming | ~running |
| Geo distance | distance(loc, geopoint(37.7, -122.4)) < 1000 |
Facets
Attach facets to documents to enable faceted navigation. Set facet_discover in a search to have altengine return the most common facet values over the matches, then pass the ones a user picks back as facet_refinements to narrow the result set. Atom facets return value counts; number facets return half-open [min, max) ranges with counts.
Limits
| Limit | Value |
|---|---|
| Documents per put | 200 |
| Ids per delete | 200 |
| Document id length | 500 bytes |
| Atom value length | 500 bytes |
| Index name length | 100 bytes |
Search limit | 1000 (default 20) |
Search offset | 1000 |
total_hits_accuracy | 10000 (default 20) |
Index and document ids must be printable ASCII, may not start with !, and may not use the reserved __*__ form.