Recoup

Get started with Recoup.

API REFERENCE

Get file contents

On this page
GET/api/sandboxes/file

Read a file from the authenticated account's Git-backed repository, or an explicitly authorized target account's repository, including resolved submodule paths, on main. The repository comes from the account's snapshot. Authenticate with x-api-key or an Authorization Bearer token.

Omit account_id to read the authenticated account. An explicit UUID must pass the existing account-access policy: the caller itself, an organization the caller belongs to, a shared-organization account, or existing Recoup administrative access. Invalid UUIDs return 400; denied targets return 403 before snapshot or repository lookup. A target read never falls back to the caller's repository. Successful explicit-target reads echo account_id; omitted-target responses do not add that field. This delegates reads only, not upload, replacement or deletion rights.

Clients selecting an account must send the same account_id on the list and file reads and require a matching response echo before using the result. Key cached data by authentication identity, target account and API origin. When that scope changes, reject stale in-flight results and invalidate writable revisions. Retain any unsaved replacement under its original account for manual recovery; never reuse that draft or its revision for a different account. An explicit override is a read-only view, even when it names the authenticated account. A SHA from a target read does not grant permission to write there.

To update an existing file without silently replacing a newer edit, set include_revision=true. The response pairs content with its blob sha from the same repository read. Keep that SHA with the opened draft and send it as files[].expected_sha when saving to the same account, resolved repository and path. Omitting the flag, or setting it to false, retains the legacy raw read without a SHA.

Text files are returned verbatim. Recognized binary extensions (.mp3, .png, .jpg, .mp4, .pdf, etc.) return base64 content with encoding: base64; decode those bytes before use.

Versioned reads support existing regular files whose content is returned inline by the repository service (normally up to 1 MB). Unknown binary content that is not valid UTF-8 is rejected by the versioned read rather than converted into damaged text. Missing/unsupported content, directories and symlinks return an error.

The SHA identifies the file content; it is not an editing history.

Authentication

See the authentication guide for API key and account access requirements.

Request

cURL
curl --request GET \
  --url 'https://api.recoupable.dev/api/sandboxes/file?path=drafts%2Fnotes.txt' \
  --header 'x-api-key: YOUR_API_KEY'

Replace the YOUR_ placeholders with your values. Required query parameters are included; optional parameters are listed below.

Try it

Fill in the fields, send the request from your browser, and read the live response. The curl below updates as you type.

Kept in this browser tab only and cleared when it closes.

cURL for this request
curl --request GET \
  --url 'https://api.recoupable.dev/api/sandboxes/file'

Parameters

Query parameters

pathstringrequired

File path within the resolved repository. Use a canonical relative path. Dot/traversal segments, backslashes, control characters, malformed Unicode and leading/trailing/doubled slashes return 400. These checks also apply to legacy requests.

include_revisionboolean

Return content and blob sha together for a guarded update of an existing file. Only the literal query values true and false are accepted.

Default: false

account_idstring

Optional target account UUID authorized by the existing account-access policy. Omit for the authenticated account. Successful explicit-target reads echo this value as account_id; this does not grant file-write access.

Responses

200File content. Versioned reads also return sha; recognized binary extensions also return encoding: base64. Explicit authorized account_id requests also echo that account_id; omitted-target requests do not.

application/json

statusstring · enumrequired

Status of the operation

Values: "success"

contentstringrequired

Text content, or base64 bytes for recognized binary extensions. Decode when encoding is base64. Versioned reads reject unknown non-UTF-8 binary content.

encodingstring · enum

Present for recognized binary extensions, on both legacy and versioned reads. When absent, content is text.

Values: "base64"

shastring

Present when include_revision=true; use this reader-observed blob SHA as files[].expected_sha. Absent from legacy reads. It identifies the returned bytes, not an accepted Context source version.

Example: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

pattern: ^[a-f0-9]{40}$

account_idstring

On successful GET reads only: the explicitly requested, authorized target account UUID. Present even for an explicit self target; absent when account_id was omitted. This is read scope, not write authorization.

Example: "11111111-1111-4111-8111-111111111111"

format: uuid

Legacy text read

legacyText
{
  "status": "success",
  "content": "Release notes"
}

Text and its observed revision

versionedText
{
  "status": "success",
  "content": "Release notes",
  "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Recognized binary bytes and revision

versionedBinary
{
  "status": "success",
  "content": "aGVsbG8=",
  "encoding": "base64",
  "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Authorized target read (account_id supplied; no revision requested)

targetText
{
  "status": "success",
  "content": "Release notes",
  "account_id": "11111111-1111-4111-8111-111111111111"
}

Authorized target bytes and revision (read access only)

targetVersionedText
{
  "status": "success",
  "content": "Release notes",
  "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "account_id": "11111111-1111-4111-8111-111111111111"
}

400Invalid account_id UUID, missing/noncanonical path or include_revision other than true/false. Use a canonical relative path. Dot/traversal segments, backslashes, control characters, malformed Unicode and leading/trailing/doubled slashes return 400. These checks also apply to legacy requests.

application/json

errorstringrequired

Error message describing what went wrong

Example: "Failed to create sandbox"

401Missing or invalid API-key/Bearer authentication.

application/json

errorstringrequired

Error message describing what went wrong

Example: "Failed to create sandbox"

403Access denied to the explicit account_id. No target snapshot/repository lookup or fallback to the caller's repository occurs.

application/json

errorstringrequired

Error message describing what went wrong

Example: "Failed to create sandbox"

404No usable account snapshot/repository, missing file, or unsupported/failed versioned read. Guarded reads do not fall back to another branch or separately fetched bytes. An explicit target with no usable repository or file does not fall back to the caller's repository.

application/json

errorstringrequired

Error message describing what went wrong

Example: "Failed to create sandbox"

Full specification

Download the OpenAPI file for complete schemas, constraints, and examples.

Download content.json
View operation source
json
{
  "operationId": "getSandboxesFile",
  "description": "Read a file from the authenticated account's Git-backed repository, or an explicitly authorized target account's repository, including resolved submodule paths, on `main`. The repository comes from the [account's snapshot](/api-reference/sandboxes/list). Authenticate with `x-api-key` or an Authorization Bearer token.\n\nOmit `account_id` to read the authenticated account. An explicit UUID must pass the existing account-access policy: the caller itself, an organization the caller belongs to, a shared-organization account, or existing Recoup administrative access. Invalid UUIDs return 400; denied targets return 403 before snapshot or repository lookup. A target read never falls back to the caller's repository. Successful explicit-target reads echo `account_id`; omitted-target responses do not add that field. This delegates reads only, not upload, replacement or deletion rights.\n\nClients selecting an account must send the same `account_id` on the list and file reads and require a matching response echo before using the result. Key cached data by authentication identity, target account and API origin. When that scope changes, reject stale in-flight results and invalidate writable revisions. Retain any unsaved replacement under its original account for manual recovery; never reuse that draft or its revision for a different account. An explicit override is a read-only view, even when it names the authenticated account. A SHA from a target read does not grant permission to write there.\n\nTo update an existing file without silently replacing a newer edit, set `include_revision=true`. The response pairs `content` with its blob `sha` from the same repository read. Keep that SHA with the opened draft and send it as `files[].expected_sha` when saving to the same account, resolved repository and path. Omitting the flag, or setting it to `false`, retains the legacy raw read without a SHA.\n\n**Text files are returned verbatim. Recognized binary extensions (`.mp3`, `.png`, `.jpg`, `.mp4`, `.pdf`, etc.) return base64 content with `encoding: base64`; decode those bytes before use.**\n\nVersioned reads support existing regular files whose content is returned inline by the repository service (normally up to 1 MB). Unknown binary content that is not valid UTF-8 is rejected by the versioned read rather than converted into damaged text. Missing/unsupported content, directories and symlinks return an error.\n\nThe SHA identifies the file content; it is not an editing history.",
  "parameters": [
    {
      "name": "path",
      "in": "query",
      "required": true,
      "description": "File path within the resolved repository. Use a canonical relative path. Dot/traversal segments, backslashes, control characters, malformed Unicode and leading/trailing/doubled slashes return 400. These checks also apply to legacy requests.",
      "schema": {
        "type": "string",
        "example": "drafts/notes.txt",
        "minLength": 1
      }
    },
    {
      "name": "include_revision",
      "in": "query",
      "required": false,
      "description": "Return content and blob sha together for a guarded update of an existing file. Only the literal query values true and false are accepted.",
      "schema": {
        "type": "boolean",
        "default": false
      },
      "example": true
    },
    {
      "name": "account_id",
      "in": "query",
      "description": "Optional target account UUID authorized by the existing account-access policy. Omit for the authenticated account. Successful explicit-target reads echo this value as account_id; this does not grant file-write access.",
      "required": false,
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "example": "11111111-1111-4111-8111-111111111111"
    }
  ],
  "responses": {
    "200": {
      "description": "File content. Versioned reads also return sha; recognized binary extensions also return encoding: base64. Explicit authorized account_id requests also echo that account_id; omitted-target requests do not.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SandboxFileResponse"
          },
          "examples": {
            "legacyText": {
              "summary": "Legacy text read",
              "value": {
                "status": "success",
                "content": "Release notes"
              }
            },
            "versionedText": {
              "summary": "Text and its observed revision",
              "value": {
                "status": "success",
                "content": "Release notes",
                "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
              }
            },
            "versionedBinary": {
              "summary": "Recognized binary bytes and revision",
              "value": {
                "status": "success",
                "content": "aGVsbG8=",
                "encoding": "base64",
                "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
              }
            },
            "targetText": {
              "summary": "Authorized target read (account_id supplied; no revision requested)",
              "value": {
                "status": "success",
                "content": "Release notes",
                "account_id": "11111111-1111-4111-8111-111111111111"
              }
            },
            "targetVersionedText": {
              "summary": "Authorized target bytes and revision (read access only)",
              "value": {
                "status": "success",
                "content": "Release notes",
                "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                "account_id": "11111111-1111-4111-8111-111111111111"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid account_id UUID, missing/noncanonical path or include_revision other than true/false. Use a canonical relative path. Dot/traversal segments, backslashes, control characters, malformed Unicode and leading/trailing/doubled slashes return 400. These checks also apply to legacy requests.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SandboxErrorResponse"
          }
        }
      }
    },
    "401": {
      "description": "Missing or invalid API-key/Bearer authentication.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SandboxErrorResponse"
          }
        }
      }
    },
    "403": {
      "description": "Access denied to the explicit account_id. No target snapshot/repository lookup or fallback to the caller's repository occurs.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SandboxErrorResponse"
          }
        }
      }
    },
    "404": {
      "description": "No usable account snapshot/repository, missing file, or unsupported/failed versioned read. Guarded reads do not fall back to another branch or separately fetched bytes. An explicit target with no usable repository or file does not fall back to the caller's repository.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SandboxErrorResponse"
          }
        }
      }
    }
  }
}