Encrypted records, read one field at a time
Keep a customer's SSN and address as one sealed record in your Vault, filed under the ID you already use for them. Your app names the fields it needs and no other field is sent. Each value arrives as a Spark that burns on its first read, and a write built on stale data is refused. SparkVault's own sign-in keeps every person this way.
Your endpoint: https://api.sparkvault.com/
Where a record lives, and what a read returns
A Structured Ingot is one customer's record: named fields and their values, sealed as one Ingot in your Vault. Your app reaches it by the ID it already holds for that customer.
| Part | What happens | What to know |
|---|---|---|
| One record per person | Your app creates one Structured Ingot per customer, up to 10,000 fields in it, and names it with the ID it already uses for them, such as :customer_12345. |
A name the Vault already holds is refused, so a second create cannot replace the first. Change a record with a PATCH, and read or delete it by the same name. |
| A read names its fields | A read asks for the fields it needs, up to 100 at a time, and gets one Spark per field found. The response carries nothing else. | Your code reads each Spark once to get the value. A second read is turned away, and a Spark nobody reads expires, after 15 minutes unless the read set another lifetime. |
| A write that cannot clobber | A PATCH sets and deletes fields in one request, and lands only if the record is still the version it was built from. | When two writers race, one lands and the other is refused with nothing written. It reads the record again and rebuilds its change from the current version. |
| Keys and seats | Every request carries your API key and a Vault Access Token from a Vault you have unsealed. Writing a record takes a Full License seat. View Only members can read. | Each create and each read is written to the record's audit log, and each delete to the Vault's, under the API key or member who asked, with the address and client the request came from. |
| Secure Identity | SparkVault's own sign-in product keeps each person's profile, verified emails and phones, and passkeys as one Structured Ingot, and reads and patches it through this API. |
Every person who signs in to SparkVault is kept as one of these records. See secure identity |
- Fields in one record
- 10,000
- Each field name up to 256 characters.
- Text in one value
- 1 MB
- A value can also be a number, a boolean, a list or an object.
- Fields in one read
- 100
- Each value found becomes its own Spark.
- Characters in a record's name
- 255
- Unique among the Vault's Structured Ingots.
Each value comes back as a Spark you read once
The answer to a read holds no values. It holds one Spark ID per field it found, and your code reads each Spark once, with your API key, to get the value. That read burns the Spark. Ask again and the answer is 403, and a Spark nobody reads expires when its time runs out.
- Lifetime
- From one minute to 24 hours, set in seconds with
ttl. 15 minutes when you set none. - Sealing
- Each Spark has its own AES-256-GCM key, derived from SparkVault's key and your account's key.
GET /vlt_abc123/:customer_12345
?keys=email,ssn&ttl=300
X-API-Key: sv_live_...
X-Vault-Access-Token: vat_...
{
"data": {
"ingot_id": "ing_4e1...",
"version": 7,
"values": {
"email": {
"spark_id": "spk_9f2...",
"expires_at": 1702000300
},
"ssn": {
"spark_id": "spk_b2d...",
"expires_at": 1702000300
}
},
"missing_keys": []
}
}
GET /v1/sparks/spk_9f2...
X-API-Key: sv_live_...
{
"data": {
"spark_id": "spk_9f2...",
"payload": "ada@example.com",
"content_type": "text/plain",
"status": "ash"
}
}
A PATCH built on stale data is refused
One PATCH sets and deletes fields together. We replace the whole record only if it is still the version the PATCH was built from, so when two PATCHes race, one lands and the other gets a 412. Send the version your read returned as expected_version, and a PATCH computed from values that have changed since is refused the same way.
- After a 412
- Nothing was written. Read the record again, rebuild the change from what you get, and send it with the new version.
- Checked first
- A malformed PATCH, or one with a field name or a value the record cannot hold, stops at 400 before the record is opened.
- Versions
- A new Structured Ingot is version 1, and each PATCH that lands adds one.
Seven requests do the work
Each carries your API key and a Vault Access Token. Paths are relative to your endpoint, and a record is addressed by its ID or by your own name for it after a colon.
Read the Structured Ingots reference- Create
POST /{vault_id}- List
GET /{vault_id}- Read the field names
GET /{vault_id}/{ingot_id}- Read values
GET /{vault_id}/{ingot_id}?keys=email,ssn&ttl=300 - Check it exists
GET /{vault_id}/{ingot_id}/info - Patch
PATCH /{vault_id}/{ingot_id}- Delete
DELETE /{vault_id}/{ingot_id}
Who can open a Structured Ingot
A Structured Ingot is an Ingot, sealed the way a file in your Vault is sealed: AES-256-GCM, under a key derived from SparkVault's key, your account's key and your Vault Master Key.
Read the security architecture- Vault Access Token
- Every request carries one, minted by unsealing the Vault with its VMK or a Delegated Vault Access Key (DVAK). It lasts an hour by default and up to 24 hours.
- Read-only keys
- A session opened with a read-only DVAK reads records and changes none.
- Kept from file routes
- The Vault's file routes refuse to download, replace, rename or delete a Structured Ingot (403). Every request here that names a record refuses one this product does not manage.
- At rest
- To read fields or apply a PATCH, our servers decrypt the record in memory, inside the request your Vault Access Token authorizes. It is encrypted at rest, not end-to-end.
What it costs
See the pricingStructured Ingots have no price of their own and come with every SparkVault plan. Writing one takes a Full License seat, $79 per month, which adds 25 GB of storage and 50 GB of bandwidth to your account's pools.
A record's encrypted body counts against pooled storage. Reading its fields moves the whole body, and a PATCH moves it down and the replacement back up. Those bytes count against pooled bandwidth.
Store your first record
Create a Vault, unseal it for a Vault Access Token, and POST a name and a JSON object to the Vault's Structured Ingots endpoint.