14 Min. Read+ 100 Exp

Documents

Understand the lifecycle, ownership, and revision of Platform documents.

Learning objectives

By the end of this lesson, you will be able to:

  • read a document with a query and add, update, or remove one with a signed write;
  • read the base fields on any document and pick out the one that records its owner;
  • say who is allowed to change or delete a document, and how ownership moves;
  • update a document safely by advancing its revision; and
  • explain what deleting stored data returns, and why it is only part of the original cost.

A data contract declares the shape of your records; a document is one of those records, actually stored on the network. This lesson covers what a document is, how it is read and written, who owns it, how revisions work, and what happens to the storage fee when you delete it.

What a Platform document is

A document is the atomic unit of application data on Dash Platform. It behaves like a JSON document in a document-oriented database: a single record with named fields. The set of documents of one kind are what you declared as a document type when you published your .

Every document carries two kinds of fields:

  • Base fields (prefixed with $) are added by the protocol. Every document has them, regardless of the app.
  • Application fields are the ones you declared in the document type's schema in your data contract, such as a message on a note.

The base fields answer the questions the network needs answered for every record:

FieldWhat it records
$idThe document's unique ID (32 bytes)
$typeThe document type in the referenced contract
$revisionThe document's revision, 1 or higher, on mutable documents
$dataContractIdThe data contract this document belongs to
$ownerIdThe that owns the document

The document also has optional $createdAt, $updatedAt, $transferredAt, and their block-height companions, but those appear only when the document type's schema lists them as required properties.

Here is a note document the way a query returns it:

{
  "$id": "6NsbpUBZUnyArsmWozxhuGdXTBNVE5BMyRh6hsowg8HY",
  "$type": "note",
  "$dataContractId": "2cJrFFWZNB1QBP2U9pzAwxLqbdnD2ZiA4j9ByyaVQPmB",
  "$ownerId": "6YfP6tT9AK8HPVXMK7CQrhpc8VMg7frjEnXinSPvUmZC",
  "$revision": 1,
  "message": "Ship the first draft"
}

The $ fields are Platform's; message is the app's, declared in the contract.

Where a document ID comes from

You do not choose the $id by hand. The protocol derives it by double-SHA256 hashing the document's dataContractId, ownerId, type name, and a 32-byte random value called entropy. Entropy makes two otherwise-identical documents unique; the same owner creating two copies of the same type gets two different IDs for free.

Read and write lifecycle

A document's life splits into two paths that work differently.

Reading

Reading is a query against committed state. You ask for documents of a given contract and type, and you get back the documents the network has already validated and stored. The SDK reads with something like:

const results = await sdk.documents.query({
  dataContractId: CONTRACT_ID,
  documentTypeName: "note",
  where: [["$id", "==", DOCUMENT_ID]],
  limit: 2,
});

The result is a map keyed by each document's $id. A read does not sign anything and does not change state; you are looking at what already exists.

Writing

Writing changes state, so it works through signed operations that the network validates. The core actions are the three you already know from any data store:

  • Create adds a new document. It carries the entropy that seeds its $id.
  • Replace overwrites an existing document's data, keeping the same $id but advancing its revision.
  • Delete removes an existing document.

Two more actions change who owns a document rather than its data: transfer moves ownership to another identity, and purchase lets a buyer buy a document the owner has listed for sale. A final action, update price, lets the owner set or change the listing price. Transfer and purchase are the subject of their own later module, so here it is enough to know they are how ownership moves.

Every one of these writes is wrapped in a signed — specifically a Batch transition that can bundle one or more document actions — and submitted through DAPI by the owning identity. Before anything changes, Platform validates the transition against both the protocol and your data contract. Only a validated write becomes part of the state that later reads see.

A useful mental model

Reads are lookups of what the network already agreed to. Writes are proposals the network checks before committing. That check — not a database administrator — is what enforces every rule in this lesson.

Ownership

Ownership is recorded in the $ownerId base field: the identity that submitted a document owns it. That single field drives what you are allowed to do with a record.

  • Replace and delete are permitted only on a document the submitting identity owns. The write is signed with a key bound to that identity, so no one else can mutate or remove the record.
  • Transfer changes ownership directly by naming a recipient identity. Only a document whose type the contract marks transferable can be transferred.
  • Purchase changes ownership when a buyer matches a price the current owner listed. Only types whose trade mode permits sale can be bought.
  • Update price can be set only by the current owner.

A contract can also tighten who may create a document type in the first place, independently of who owns each document once it exists.

The pattern to remember: the owner — the identity in $ownerId — holds the write permissions, and ownership moves only through the transfer or purchase actions, never through an ordinary edit.

Revisions

$revision is how Dash Platform stops two writers from silently overwriting each other. It is a 64-bit number that starts at 1 when a document is created and must sit on your mind every time you update.

Here is the rule: a replace must submit a $revision strictly greater than the one currently stored. The network rejects any replace built from a stale revision — a guard called optimistic concurrency. If you and another client both fetched revision 3, the first replace to land accepts 4; the second one fails because its 3 is no longer current, telling that client to re-fetch instead of clobbering the winner.

The SDK makes the safe path the obvious one: fetch the current document, add one, then replace.

const current = await fetchCurrentNote();            // e.g. $revision 3
const replacement = new Document({
  properties: { message: "Revised draft" },
  documentTypeName: "note",
  dataContractId: CONTRACT_ID,
  ownerId: current.ownerId,
  id: current.id,
  revision: current.revision + 1n,                   // 4
});
await sdk.documents.replace({ document: replacement, identityKey, signer });

Revision also marks mutability. A document type whose contract sets documentsMutable: false produces documents with no $revision at all — they are immutable, created once and only ever read. The default is documentsMutable: true.

Delete refunds

Deleting a document is not just cleanup — it can return money, which is why Dash Platform nudges apps to remove data they no longer need.

When you write data, you pay a storage fee. That fee is not handed out all at once: it is paid to gradually, over the storage's 50-year lifetime. If you delete the data before those 50 years are up, the portion that has not been distributed yet comes back to you as a storage refund.

Two limits keep that honest:

  • You are refunded only the undistributed storage fee, not the full amount you originally paid — the longer the data has lived, the less remains to refund.
  • Processing fees are never refunded. The network already did the work of validating and applying your write, and that cost is not returned.

So deleting early recovers the storage value that would otherwise keep trickling out to masternodes, but it is a partial return, not a full one.

Checkpoint

Pass the quiz to complete the lesson.

Knowledge check

Restoring your progress…

4 correct to pass

What you accomplished

You can now read a document with a query and write one with a signed, validated action; parse a document's base fields and identify its owner; explain who may change or delete a document and how transfer and purchase move ownership; update a document safely by advancing its revision; and say what an early delete refunds, and why it is partial rather than full. These are the rules every later hands-on module — submitting, querying, transferring, and deleting documents for real — will ask you to apply.