Driftstone Docs
Back to landing

Reference

API Overview

POST/v1/reposCreate a repository for the authenticated organization.GET/v1/reposList repositories for the authenticated organization.GET/v1/repos/{repo}Return repository metadata for the authenticated organization.DELETE/v1/repos/{repo}Delete a repository and its stored files.GET/v1/repos/{repo}/main-diffsList recorded main-branch diff metadata.POST/v1/repos/{repo}/main-diffs/rangeResolve and combine a linear main diff range.POST/v1/repos/{repo}/uploadsCreate signed upload URLs for main or branch files.GET/v1/repos/{repo}/uploads/{uploadId}Read upload status, including async validation status.POST/v1/repos/{repo}/downloadsCreate signed download URLs for specific main or branch files.POST/v1/repos/{repo}/downloads/directoryCreate signed download URLs for every file under a live directory.POST/v1/repos/{repo}/uploads/{uploadId}/completeComplete a pending main or branch upload.POST/v1/repos/{repo}/copiesCopy a directory between repository namespaces.GET/v1/repos/{repo}/copies/{runId}Poll a directory copy job.POST/v1/repos/{repo}/syncMerge a main storage directory into branch storage directories.GET/v1/repos/{repo}/sync/{runId}Poll a repository sync job.POST/v1/repos/{repo}/validatorsCreate a repo validation gate.GET/v1/repos/{repo}/validatorsList repo validation gates.PATCH/v1/repos/{repo}/validators/{validatorId}Update a repo validation gate.DELETE/v1/repos/{repo}/validators/{validatorId}Soft-delete a repo validation gate.GET/v1/repos/{repo}/validations/{validationRunId}Fetch a validation run report.GET/v1/repos/{repo}/branchesList repository branches.GET/v1/repos/{repo}/branches/{branch}Return metadata for one branch.POST/v1/repos/{repo}/branchesCreate a branch, optionally from the repository main head.DELETE/v1/repos/{repo}/branches/{branch}Delete a branch and its stored files.GET/v1/repos/{repo}/commitsList commit history for a repository branch.POST/v1/repos/{repo}/branches/{branch}/rollbackMove a branch head to an existing commit or storage snapshot.POST/v1/extensions/createCreate a private agent extension for the authenticated organization.POST/v1/extensions/updateUpdate an extension name, description, status, prompt, or presets.POST/v1/extensions/deleteDelete an extension owned by the authenticated organization.POST/v1/extensions/runRun an extension against a Driftstone storage path.GET/v1/extensions/poll/{runId}Poll a background extension run.

API Reference

Repositories

Repository endpoints create and retrieve Driftstone repositories within the authenticated organization.

POST/v1/repos

Create a repository

Creates a new repository for the authenticated organization. Repository names cannot include path separators.

FieldLocationRequiredDescription
namebodyyesRepository name. Must be non-empty and cannot contain / or \.
pagequerynoList page number. Defaults to 1.
pageSizequerynoList page size. Defaults to 10.
curl -X POST "https://api.driftstone.ai/v1/repos" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "hello-world"
  }'
GET/v1/repos

List repositories

Returns repositories for the authenticated organization. Supports page and pageSize query parameters.

GET/v1/repos/{repo}

Get a repository

Returns one repository resolved under the authenticated organization.

DELETE/v1/repos/{repo}

Delete a repository

Marks a repository as deleting and starts background deletion for repository files, uploads, branches, and the repository record.

API Reference

Uploads + Downloads

Upload and download endpoints create signed URLs for main or branch files. Directory downloads return every live file under the requested directory without waiting for an archive job.

POST/v1/repos/{repo}/uploads

Create upload URLs

Returns signed upload URLs for files under the target branch storage directory. Upload each file to its URL with Content-Type: application/octet-stream. Pass message to record a commit message when the upload is completed.

FieldLocationRequiredDescription
repopathyesRepository identifier.
branchbodynoTarget branch name. Defaults to main.
storageDirbodyyesUpload storage directory.
messagebodynoOptional commit message stored when the upload is completed.
filesbodyyesNon-empty array of objects with name and hash.
uploadIdpathyes for completeUpload id returned by the create upload endpoint.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/uploads" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "branch": "main",
    "storageDir": "ver-1234abcd",
    "message": "Update README copy",
    "files": [
      {
        "name": "README.md",
        "hash": "64-character-sha256-or-client-hash"
      }
    ]
  }'
POST/v1/repos/{repo}/downloads

Create download URLs

Returns signed download URLs for specific files under the selected main or branch namespace. File paths are relative to that namespace.

FieldLocationRequiredDescription
repopathyesRepository identifier.
typebodyyesStorage namespace. Must be main or branch.
filesbodyyes for file downloadsNon-empty array of objects with path fields.
directorybodyyes for directory downloadsDirectory under the selected namespace.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/downloads" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "main",
    "files": [
      {
        "path": "ver-1234abcd/README.md"
      }
    ]
  }'
POST/v1/repos/{repo}/downloads/directory

Create directory download URLs

Returns signed download URLs for every file under a live directory. Response paths are relative to the requested directory.

FieldLocationRequiredDescription
repopathyesRepository identifier.
typebodyyesStorage namespace. Must be main or branch.
filesbodyyes for file downloadsNon-empty array of objects with path fields.
directorybodyyes for directory downloadsDirectory under the selected namespace.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/downloads/directory" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "branch",
    "directory": "profile-123/state-456"
  }'
POST/v1/repos/{repo}/uploads/{uploadId}/complete

Complete an upload

Marks a pending upload as complete. Main uploads can create a main diff record. Custom branch uploads update the branch immediately unless matching pre_promote_upload validators require an async validation run first.

FieldLocationRequiredDescription
repopathyesRepository identifier.
branchbodynoTarget branch name. Defaults to main.
storageDirbodyyesUpload storage directory.
messagebodynoOptional commit message stored when the upload is completed.
filesbodyyesNon-empty array of objects with name and hash.
uploadIdpathyes for completeUpload id returned by the create upload endpoint.
GET/v1/repos/{repo}/uploads/{uploadId}

Get upload status

Polls an upload. This is useful when completion returns validating because branch promotion is waiting on validators.

FieldLocationRequiredDescription
repopathyesRepository identifier.
uploadIdpathyesUpload id returned by create upload.
curl -X GET "https://api.driftstone.ai/v1/repos/hello-world/uploads/upload-..." \
  -H "Authorization: Bearer dk-..."

API Reference

Branches

Branch endpoints keep agent work isolated and reviewable after a repository main upload has established a head identifier.

GET/v1/repos/{repo}/branches

List branches

Returns branches available in a repository. Supports page and pageSize query parameters.

GET/v1/repos/{repo}/branches/{branch}

Get a branch

Returns metadata for a single branch.

POST/v1/repos/{repo}/branches

Create a branch

Creates a branch. By default, Driftstone copies the repository main head and optional transforms can patch files after the copy. Set deriveFromMain to false to create only the branch record before uploading its first directory.

FieldLocationRequiredDescription
repopathyesRepository identifier.
namebodyyesNew branch name.
storageDirbodyconditionalBranch storage directory. Required when deriveFromMain is true.
deriveFromMainbodynoWhether to copy from the repository main head. Defaults to true. Set false to create only the branch record.
messagebodynoOptional branch creation message.
transformsbodynoOptional file transforms applied after copying the repository main head.
archivebodynoWhether to archive the copied branch directory. Defaults to true.
pagequerynoList page number. Defaults to 1.
pageSizequerynoList page size. Defaults to 10.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/branches" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "feature-readme",
    "storageDir": "state-123",
    "deriveFromMain": true,
    "transforms": {
      "README.md": "# Branch-specific README\n"
    }
  }'
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/branches" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "profile-123",
    "deriveFromMain": false
  }'
DELETE/v1/repos/{repo}/branches/{branch}

Delete a branch

Marks a branch as deleting and starts background deletion for the stored branch files and branch record.

API Reference

Commits + Rollback

Driftstone records a commit whenever a branch head moves through branch creation, upload completion, sync promotion, or rollback. headIdentifier is the current file snapshot for a branch, while headCommitId identifies the history event that currently owns that head. Multiple commits can point to the same storageDir after rollback, but only one commit should match headCommitId. Existing repositories that predate commit rows expose completed uploads as isLegacyUpload history entries, and those entries can be rollback targets too.

GET/v1/repos/{repo}/commits

List branch commits

Returns commit history for a branch with headIdentifier, headCommitId, and per-commit isCurrent. Use storageDir to inspect the files for a commit and message for the human-readable commit message.

FieldLocationRequiredDescription
repopathyesRepository identifier.
branchquerynoBranch name to list history for. Defaults to main.
pagequerynoList page number. Defaults to 1.
pageSizequerynoList page size. Defaults to 50 and is capped at 250.
curl -X GET "https://api.driftstone.ai/v1/repos/hello-world/commits?branch=feature-readme" \
  -H "Authorization: Bearer dk-..."
POST/v1/repos/{repo}/branches/{branch}/rollback

Rollback a branch

Moves a branch head to an existing commit or storage snapshot and records a new rollback commit. The files served by the branch change only when the selected commit points to a different storageDir than the current headIdentifier. Use expectedHead to guard against stale UI or concurrent updates.

FieldLocationRequiredDescription
repopathyesRepository identifier.
branchpathyesBranch name to move.
commitIdbodyconditionalCommit id to restore. Provide commitId or storageDir.
storageDirbodyconditionalStorage snapshot to restore. Provide commitId or storageDir.
expectedHeadbodynoOptional current headIdentifier guard to prevent stale rollback.
messagebodynoOptional rollback commit message.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/branches/feature-readme/rollback" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "commitId": "commit-...",
    "expectedHead": "state-456",
    "message": "Rollback feature-readme to stable README"
  }'

API Reference

Copies

Copy endpoints duplicate a stored directory from one repository namespace to another and optionally apply JSON or Markdown transforms before archiving the destination.

POST/v1/repos/{repo}/copies

Copy a directory

Starts a background copy from sourceDir to destDir. Source and destination branches default to main.

FieldLocationRequiredDescription
repopathyesRepository identifier.
sourceDirbodyyesSource storage directory name.
destDirbodyyesDestination storage directory name.
sourceBranchbodynoSource branch name. Defaults to main.
destBranchbodynoDestination branch name. Defaults to main.
transformsbodynoOptional JSON or Markdown transforms applied after copy.
archivebodynoWhether to archive the destination directory. Defaults to true.
runIdpathyes for pollingCopy run id returned by the create copy endpoint.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/copies" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "sourceDir": "ver-1234abcd",
    "destDir": "state-456",
    "sourceBranch": "main",
    "destBranch": "profile-123",
    "archive": true
  }'
GET/v1/repos/{repo}/copies/{runId}

Poll copy status

Returns running, completed, or failed for a directory copy run.

FieldLocationRequiredDescription
repopathyesRepository identifier.
sourceDirbodyyesSource storage directory name.
destDirbodyyesDestination storage directory name.
sourceBranchbodynoSource branch name. Defaults to main.
destBranchbodynoDestination branch name. Defaults to main.
transformsbodynoOptional JSON or Markdown transforms applied after copy.
archivebodynoWhether to archive the destination directory. Defaults to true.
runIdpathyes for pollingCopy run id returned by the create copy endpoint.

API Reference

Sync

Sync has two modes. Classic sync merges one main storage directory into one or more branch storage directories. Agent-diff sync applies recorded main diffs into one custom branch through Driftstone's sync extension flow.

POST/v1/repos/{repo}/sync

Classic sync

Starts a background sync from incomingStorageDir into each target branch. The strategy field is typed as manual, current, incoming, or smart.

FieldLocationRequiredDescription
repopathyesRepository identifier.
incomingStorageDirbodyyesMain storage directory to merge into each target branch.
strategybodynoMerge strategy. One of manual, current, incoming, or smart. Defaults to manual.
targetsbodyyesNon-empty array of branch sync targets.
targets[].branchbodyyesTarget branch name.
targets[].baseStorageDirbodyyesMain storage directory that the current branch state is based on.
targets[].currentStorageDirbodyyesCurrent branch storage directory to preserve user changes from.
targets[].outputStorageDirbodyyesBranch storage directory where the merged output is written.
runIdpathyes for pollingSync run id returned by the create sync endpoint.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/sync" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "incomingStorageDir": "ver-456",
    "strategy": "smart",
    "targets": [
      {
        "branch": "profile-123",
        "baseStorageDir": "ver-123",
        "currentStorageDir": "state-123",
        "outputStorageDir": "state-456"
      }
    ]
  }'
POST/v1/repos/{repo}/sync

Agent-diff sync

Starts the new main-diff sync flow. Driftstone resolves missing main diffs, creates a workspace with main/, custom/, work/, MAIN_DIFF.json, MAIN_DIFF.patch, and SYNC_TASK.md, then promotes work/ only after validators pass.

FieldLocationRequiredDescription
repopathyesRepository identifier.
modebodyyesMust be agent-diff.
branchbodyyesCustom branch to sync with main.
extensionIdbodynoOptional override for the sync extension. Defaults to the platform sync extension.
fromMainStorageDirbodynoOverride the branch lastSyncedMainStorageDir.
targetMainStorageDirbodynoMain storage dir to sync to. Defaults to current repo main head.
outputStorageDirbodynoCandidate output storage dir. Defaults to generated sync-* id.
promptbodynoExtra guidance appended to the sync task.
runIdpathyes for pollingSync run id returned by sync.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/sync" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "agent-diff",
    "branch": "profile-123"
  }'
GET/v1/repos/{repo}/sync/{runId}

Poll sync status

Returns running, completed, or failed for a repository sync run.

FieldLocationRequiredDescription
repopathyesRepository identifier.
incomingStorageDirbodyyesMain storage directory to merge into each target branch.
strategybodynoMerge strategy. One of manual, current, incoming, or smart. Defaults to manual.
targetsbodyyesNon-empty array of branch sync targets.
targets[].branchbodyyesTarget branch name.
targets[].baseStorageDirbodyyesMain storage directory that the current branch state is based on.
targets[].currentStorageDirbodyyesCurrent branch storage directory to preserve user changes from.
targets[].outputStorageDirbodyyesBranch storage directory where the merged output is written.
runIdpathyes for pollingSync run id returned by the create sync endpoint.

API Reference

Main diffs

Main diffs are created automatically when a completed main upload advances from one main storage dir to another. They are stored as metadata plus larger JSON and patch artifacts. Agent-diff sync uses these records to find exactly what a custom branch is missing.

GET/v1/repos/{repo}/main-diffs

List main diffs

Lists recorded main diffs in creation order. Each record includes the source main storage dir, target main storage dir, changed paths, stats, summary, and artifact paths.

curl -X GET "https://api.driftstone.ai/v1/repos/hello-world/main-diffs" \
  -H "Authorization: Bearer dk-..."
POST/v1/repos/{repo}/main-diffs/range

Resolve a main diff range

Combines the linear diff chain between two main storage dirs. If both storage dirs are the same, the response is up_to_date.

FieldLocationRequiredDescription
repopathyesRepository identifier.
fromStorageDirbodyyesMain storage dir where the branch last synced.
toStorageDirbodyyesTarget main storage dir.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/main-diffs/range" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "fromStorageDir": "ver-123",
    "toStorageDir": "ver-456"
  }'

API Reference

Validators

Validators are promotion gates. Driftstone runs all active validators matching the repo, event, and branch pattern. All matching required validators must pass before the branch head moves.

pre_promote_sync

Before agent-diff sync promotes

pre_promote_upload

Before custom upload promotes

required

Failure blocks branch promotion

Validator config by type

type: "extension"

Runs a Driftstone extension against the candidate workspace.

{
  "extensionId": "ext-..."
}
type: "command"

Runs shell commands in order against a temporary copy of candidate work.

{
  "command": "npm test",
  "commands": ["npm test", "npm run lint"],
  "workingDirectory": ".",
  "timeoutSeconds": 600,
  "env": {
    "CI": "true"
  }
}

For command validators, use either command or commands. workingDirectory must stay inside work/. timeoutSeconds is per command and must be between 1 and 3600.

POST/v1/repos/{repo}/validators

Create an extension validator

Extension validators run a Driftstone extension against /workspace/repo/work. The extension must write VALIDATION_RESULT.json with status set to passed or failed.

FieldLocationRequiredDescription
repopathyesRepository identifier.
namebodyyesHuman-readable validator name.
typebodyyesextension or command.
branchPatternbodynoGlob-style branch match. Defaults to *.
eventsbodynoEvents to run on. Defaults to pre_promote_sync.
requiredbodynoWhether failure blocks promotion. Defaults to true.
statusbodynoactive or disabled. Defaults to active.
configbodyyesType-specific validator config.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/validators" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "semantic validation",
    "type": "extension",
    "branchPattern": "*",
    "events": ["pre_promote_sync", "pre_promote_upload"],
    "required": true,
    "config": {
      "extensionId": "ext-..."
    }
  }'
POST/v1/repos/{repo}/validators

Create a command validator

Command validators run shell commands against a temporary copy of candidate work/. Any non-zero exit code or timeout fails the validator.

FieldLocationRequiredDescription
repopathyesRepository identifier.
namebodyyesHuman-readable validator name.
typebodyyesextension or command.
branchPatternbodynoGlob-style branch match. Defaults to *.
eventsbodynoEvents to run on. Defaults to pre_promote_sync.
requiredbodynoWhether failure blocks promotion. Defaults to true.
statusbodynoactive or disabled. Defaults to active.
configbodyyesType-specific validator config.
curl -X POST "https://api.driftstone.ai/v1/repos/hello-world/validators" \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "test check",
    "type": "command",
    "branchPattern": "*",
    "events": ["pre_promote_sync", "pre_promote_upload"],
    "required": true,
    "config": {
      "commands": ["npm test"],
      "workingDirectory": ".",
      "timeoutSeconds": 600,
      "env": {
        "CI": "true"
      }
    }
  }'
GET/v1/repos/{repo}/validators

List validators

Returns active validator definitions for the repo.

curl -X GET "https://api.driftstone.ai/v1/repos/hello-world/validators" \
  -H "Authorization: Bearer dk-..."
PATCH/v1/repos/{repo}/validators/{validatorId}

Update a validator

Updates validator name, branch pattern, events, required flag, status, or config.

FieldLocationRequiredDescription
repopathyesRepository identifier.
namebodyyesHuman-readable validator name.
typebodyyesextension or command.
branchPatternbodynoGlob-style branch match. Defaults to *.
eventsbodynoEvents to run on. Defaults to pre_promote_sync.
requiredbodynoWhether failure blocks promotion. Defaults to true.
statusbodynoactive or disabled. Defaults to active.
configbodyyesType-specific validator config.
curl -X PATCH "https://api.driftstone.ai/v1/repos/hello-world/validators/validator-..." \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "status": "disabled"
  }'
DELETE/v1/repos/{repo}/validators/{validatorId}

Delete a validator

Soft-deletes a validator definition.

curl -X DELETE "https://api.driftstone.ai/v1/repos/hello-world/validators/validator-..." \
  -H "Authorization: Bearer dk-..."
GET/v1/repos/{repo}/validations/{validationRunId}

Get a validation run

Returns the checks, summary, candidate storage dir, previous storage dir, and sync or upload id for one validation run.

FieldLocationRequiredDescription
repopathyesRepository identifier.
validationRunIdpathyesValidation run id returned in a validation report.
curl -X GET "https://api.driftstone.ai/v1/repos/hello-world/validations/valrun-..." \
  -H "Authorization: Bearer dk-..."