Write data and keep indexes in sync
Write a record first, then add the search indexes your application needs. This guide explains which changes happen together and which require separate requests.
- Save the source recordChoose a stable ID and validate its field types.
- Prepare the search representationGenerate vectors or prepare document text when your query needs them.
- Write the required index dataReuse the source ID in each explicit write.
- Verify search and sourceFind a known match, then open the record using its ID.
Before you write
Complete the quickstart to create quickstart.products.
The request below uses the explicit-tenant API: OC_BASE_URL, OC_TENANT and OC_BEARER must come from the connection settings supplied for that API. Do not extract a tenant from the current Connect URL. For a complete OC_URL, use the URL exactly as supplied, as shown in the quickstart. Add the database identity headers when required.
1. Write a record
curl --fail-with-body -X POST "$OC_BASE_URL/v1/tenants/$OC_TENANT/rows/quickstart.products" \
-H "Authorization: Bearer $OC_BEARER" \
-H "Content-Type: application/json" \
-d '{"id":"product-002","name":"Travel flask","price_cents":2490}'The row endpoint is an upsert by primary key. Reusing an ID can replace an existing row; it is not an insert-only operation. Use the documented expect=insert precondition when an existing key must produce a conflict, or use SQL INSERT. See row CRUD for partial updates, concurrency checks and deletion.
2. Import multiple rows
Use Migrate for a source database or supported file import. The batch HTTP endpoint accepts its own documented payload and limits. Check each response and any per-row failures before advancing an import checkpoint; a successful connection is not proof that all source rows arrived.
3. Add semantic search
Use a saved embedder and embedding run to populate vectors from table columns, or generate embeddings in your application and call the vector-table API. Keep the dimension and model consistent. A vector write is separate from a row write and does not create the source record.
4. Add full-text search
There are two workflows. A table full-text index is maintained as its source rows change. The explicit /fts/:table/:field document endpoint indexes the text your application sends; update those entries when the source changes. Use the row’s primary key as doc_id so a hit can be resolved to a record. See full-text search.
Requests have body limits; this is not an unlimited document-upload API. Split large text into useful chunks, keep their IDs stable and retain a mapping to the source record.
5. Maintain relationships
Declare a relation in the schema or use the supported ALTER TABLE … ADD RELATIONSHIP workflow. Writes to its source column maintain the relation’s graph indexes. Adding a foreign key enforces referential integrity; declaring a graph relation alone does not prove the target exists. See graph setup.
6. Know the transaction boundary
Three independent HTTP calls do not form one transaction. A row write and its maintained graph indexes share the row operation. Explicit vector and full-text calls commit separately. If the vector call fails after a successful row call, the row remains saved.
- Use the same stable record ID across the relevant indexes.
- Check each operation before marking the record ready for retrieval.
- Record pending index work and retry only the failed operation under its supported idempotency contract.
- Reconcile missing or stale index entries periodically. A timeout can leave the outcome unknown; read back or reconcile before repeating a mutation.
A helper that sends all three calls makes application code simpler but does not make them atomic. Use a documented transaction surface only for operations that surface actually supports. The multi-model examples explain how to coordinate these writes.
Write from your application
Use an SDK version that matches your connection, or call the HTTP endpoints from your application. The SDK directory separates published versions from upcoming clients. A client library does not change transaction boundaries: check each operation and handle partial failures just as you would with HTTP.