Skip to content

Finish a chunked replacement

POST
/drives/{drive}/nodes/{node}/chunk/contents/{content}/finish
curl --request POST \
--url https://work.optidata.cloud/api/drives/1/nodes/300754/chunk/contents/613488/finish \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "fileHash": "example", "base_content_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" }'

Assembles the chunks into the new content version and makes it the file’s current content. The previous version remains in the node history. Requires permission to update the node’s content.

This is the commit point, so this is where base_content_hash is enforced: a version committed by someone else since prepare is caught here. When the finish sends no base, the one prepare stored is checked; a base sent here replaces it. On a stale base the answer is 409 and the waiting version is never committed; it is cleaned up like any unfinished upload.

Every finish, with or without a base, runs under the node’s lock, so it can answer 423 Locked (see ContentBaseLocked). Once the lock is held, a repeated finish of content already committed is answered first, by the replay rule below (200, or 409 ContentAlreadyCommitted), before any base check: its base, no longer current once the first finish committed, is not checked again.

Retrying the call after a lost response is safe once the first call has returned or been refused with 423. If the first call stored a fileHash, a retry with that same fileHash answers 200 with the node’s current state and writes nothing; a different or missing fileHash answers 409. A first call sent without fileHash stores none, so its retry always answers 409.

drive
required
integer format: int64

Numeric id of the drive. Read it from GET /drives/config.json.

node
required
integer format: int64

Numeric id of the node (file or folder).

content
required
integer format: int64

Numeric id of a stored content version of the file. Version ids come from the node history or from the chunked-update prepare step.

Media typeapplication/json
object
fileHash

SHA-256 of the whole file, for verification.

string | null
base_content_hash

The hash_sha256 of the content the caller edited, as the server returned it. Optional. When sent, the write is accepted only if it is equal to the hash stored on the node’s current content, and is stored on the new version as base_content_hash; otherwise the answer is 409 and nothing is written. A node with no stored hash matches no base. Omit it for an unconditional write; on a chunked replacement, omit it at both prepare and finish, since a base sent at prepare is checked at finish.

string | null
<= 128 characters

The updated node.

Media typeapplication/json
object
key
additional properties
any
Examplegenerated
{}

Missing, malformed or expired authentication key.

Media typeapplication/json

Authentication failures use an error key rather than message.

object
error
required
string
Examples
Examplemissing

No bearer token sent

{
"error": "JWT passport exception: Missing bearer token in request"
}

The caller lacks the permission level the operation requires.

Media typeapplication/json

Generic error envelope used by policy, binding and framework failures.

object
message
required

Human-readable description of the failure.

string
Examples
Exampledenied
{
"message": "This action is unauthorized."
}

The resource does not exist, or does not belong to the given drive.

Media typeapplication/json

Generic error envelope used by policy, binding and framework failures.

object
message
required

Human-readable description of the failure.

string
Examples
Examplemissing
{
"message": "No query results for model [App\\Models\\Node] 99999999"
}

Nothing was written. Two cases share this status; tell them apart by state, not by the message, which is in the caller’s language:

  • The content was already committed by an earlier finish, and the fileHash sent is different from the committed one or missing, or the earlier finish stored no fileHash (see ContentAlreadyCommitted). This is checked first.
  • The content is still waiting and base_content_hash — the one sent here, or else the one prepare stored — is not the hash_sha256 stored on the node’s current content (see ContentBaseConflict). Read the node again and keep your version as a copy.
Media typeapplication/json

Envelope of the domain errors the Drive services raise.

object
error
required

Human-readable description of the failure, in the caller’s language.

string
status
required

The HTTP status, repeated in the body.

integer
help
required

Extra detail, often empty.

string
Examples

Repeat of a finish already committed, different or missing fileHash

{
"error": "This content was already committed with different data.",
"status": 409,
"help": ""
}

The request body or query string failed validation.

Media typeapplication/json
object
message
required

The first validation message.

string
errors
required

Validation messages keyed by field name.

object
key
additional properties
Array<string>
Examples
Exampleinvalid
{
"message": "The name field is required.",
"errors": {
"name": [
"The name field is required."
]
}
}

Another write of the same file held it for longer than this write waits (30 seconds by default), or the write could not keep its turn (the server lost its hold on the file before writing). Writes that wait for a turn are the ones carrying a base_content_hash and every chunk finish. The base, if any, was not checked and nothing was written: retry the same request after the number of seconds in Retry-After; read the header rather than assume a fixed delay.

Media typeapplication/json

Envelope of the domain errors the Drive services raise.

object
error
required

Human-readable description of the failure, in the caller’s language.

string
status
required

The HTTP status, repeated in the body.

integer
help
required

Extra detail, often empty.

string
Examples
ExamplesaveInProgress
{
"error": "Another save of this file is in progress. Try again in a moment.",
"status": 423,
"help": ""
}
Retry-After
integer
Example
5

Seconds to wait before retrying the request (configurable on the server).

Rate limit exceeded. Retry after the window resets.

Media typeapplication/json

Generic error envelope used by policy, binding and framework failures.

object
message
required

Human-readable description of the failure.

string
Examples
Examplethrottled
{
"message": "Too Many Attempts."
}