Reference
← Relifold documentation

Python API

Authenticate once and use the same product operations as the browser.

Account authentication

import os
from scratchpad.api import ScratchpadClient

account = ScratchpadClient(
    "https://api.relifold.com",
    os.environ["RELIFOLD_API_KEY"],
)

Select a workspace from the account page, then open API keys in workspace administration. The secret is shown once, inherits the account's current permissions, and can be revoked without modifying pipelines. The key remains user-owned rather than workspace-owned: it can reach only the organizations and workspaces the user can currently access. It is a Relifold credential, not a model-provider credential.

Workspace scope

workspace = account.select_workspace(
    organization="your-organization",
    workspace="main",
)

print(workspace.pipelines())
print([
    (
        pipeline["pipeline_id"],
        pipeline["version_count"],
        pipeline["session_statuses"],
    )
    for pipeline in workspace.pipeline_catalog()
])
print([
    (
        version["version"],
        version["state"],
        version["node_count"],
        version["review_count"],
        version["stage_count"],
        version["max_parallel_width"],
    )
    for version in workspace.versions("news-events")
])
definition = workspace.version("news-events", "v2")
print(definition["nodes"])
print(workspace.sessions(pipeline_id="news-events", version_id="v2"))
print(workspace.metrics(pipeline_id="news-events", version_id="v2"))

Either selector accepts an ID, slug, or display name. Omit a selector only when that level has exactly one result.

Ambiguous accounts fail closed rather than choosing an arbitrary workspace. Unattended scripts should supply the same selectors from RELIFOLD_ORGANIZATION and RELIFOLD_WORKSPACE.

pipeline_catalog() is the bounded workspace overview. It returns version counts, session-status counts, semantic operator families, and maximum DAG shape for every pipeline in one collection read. It does not embed full declarations, prompts, session evidence, or review quality.

versions() is a bounded catalog call: it returns lifecycle, count, semantic-family, and execution-shape summaries, not every DAG declaration. After choosing a version, use version() for its complete nodes, reviews, parameters, and readable callable source.

metrics() returns totals, task-level observations, and an operators rollup with calls, tokens, cost, reuse, failures, task runs, and wall time attributed through each session's immutable version. Historical observations that cannot be attributed are counted separately rather than guessed from a reused task name.

Edit a draft and act on suggestions

workspace.add_node(
    "news-events",
    "draft",
    '''Select(
    input_spaces=("headlines",),
    output_space="headline-fields",
    name="select-headline-fields",
    fields=("article_id", "headline"),
)''',
)

workspace.add_nodes(
    "news-events",
    "draft",
    [
        '''Select(
        input_spaces=("headline-fields",),
        output_space="recent-headlines",
        name="select-recent",
        fields=("article_id", "headline"),
        )''',
        "Barrier()",
    ],
)

pending = workspace.advice("news-events", "v1")
suggestion = pending["parameter_advice"][0]
workspace.accept_parameter_advice(
    "news-events",
    "v1",
    task=suggestion["task"],
    params=suggestion["params"],
    target_version="v2",
    owner_pipeline_id=suggestion["owner_pipeline_id"],
    owner_version_id=suggestion["owner_version_id"],
)

rejected = pending["prompt_advice"][0]
workspace.dismiss_advice(
    "news-events",
    "v1",
    kind="prompt",
    prompt_id=rejected["prompt_id"],
    proposal_version=rejected["proposal_version"],
    owner_pipeline_id=rejected["owner_pipeline_id"],
    owner_version_id=rejected["owner_version_id"],
)

add_node, add_nodes, replace_node, and delete_node edit the same draft DAG shown in the browser. add_nodes validates every ordered constructor and task name before atomically changing the draft. Prompt and parameter advice may be accepted into an editable successor or dismissed. Dismissal changes no version, prompt, session, or output.

Pipeline and version pages offer Delete with confirmation. Deletion requires edit permission for that pipeline, granted directly or through an access group. The corresponding client methods are workspace.delete_pipeline(pipeline_id) and workspace.delete_version(pipeline_id, version_id). Both draft and declared versions can be deleted once active runs, planning, and deployments no longer use them. Workspace datasets and run history are retained. A deleted version name cannot be reused.

Inspect version prompts and output rows

bindings = workspace.prompts("news-events", "v2")
for binding in bindings:
    revision = workspace.prompt(
        "news-events", binding["prompt_id"], binding["version"]
    )
    print(revision["text"])

page = workspace.space_rows(
    "scored-headlines", session_id="session-id", limit=100
)
for row in page["rows"]:
    print(row["data"])

Export an editable runner

artifact = workspace.export_version(
    "news-events",
    "v2",
    language="python",  # python, typescript, or cpp
)
with open(artifact["filename"], "w", encoding="utf-8") as target:
    target.write(artifact["source"])

The exported runner reconstructs the declared DAG through the public API. It contains prompt bindings and non-secret connector configuration, but never embeds external data credentials.

Main operation groups

Stable import boundary

Import user-facing declarations from scratchpad.api. Modules beneath that boundary are not part of the public contract.

Error handling. Hosted client failures raise AccountApiError with an HTTP status and a user-facing message. Treat 401 as expired or revoked authentication, 403 as insufficient permission, 404 as a missing resource, 409 as conflicting state, 422 as an invalid declaration, and 429 as a request-rate limit. A service error uses a stable public message rather than exposing an upstream response body.