Skill Tracer
Skills › Scientific Agent Skills › tamarind › api_reference.md

api_reference.md

189 lines · skills/tamarind/references/api_reference.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Tamarind Bio REST API reference
2
3Reviewed 2026-09-30 against the [current OpenAPI](https://app.tamarind.bio/api/openapi.json),
4[REST guide](https://app.tamarind.bio/llms-full.txt), and
5[public catalog](https://app.tamarind.bio/tools.json). These are documentation
6checks, not authenticated endpoint tests.
7
8All paths below are relative to `https://app.tamarind.bio/api`, or the user's
9organization deployment's `/api` base. Requests use `x-api-key` except public
10catalog discovery. Do not send the key when downloading a signed storage URL.

Tamarind Bio REST API reference

Reviewed 2026-09-30 against the current OpenAPI, REST guide, and public catalog. These are documentation checks, not authenticated endpoint tests.

All paths below are relative to https://app.tamarind.bio/api, or the user's organization deployment's /api base. Requests use x-api-key except public catalog discovery. Do not send the key when downloading a signed storage URL.

Raw lines 1 to 11
12## Endpoint map
14| Method | Path | Request and response |
15|---|---|---|
16| GET | `/tools-catalog` | Public catalog; also at host-level `/tools.json`. Optional `type`/`tag` filters; `tools` contains public types and conditional required settings. |
17| GET | `/tools` | Account-scoped array with `name`, descriptions, trimmed `settings`, and optional output metadata. `custom=true` selects legacy custom tools only. |
18| GET | `/tools/{name}/schema` | JSON Schema for the settings object. Optional `version` pins a custom build. 404 covers missing, inaccessible, and mid-deploy tools. |
19| POST | `/validate-job` | `type`, object/array `settings`; optional `jobName` (single), `jobNames` (array), `version`. HTTP 200 contains a `valid` verdict. |
20| POST | `/submit-job` | `jobName`, `type`, object `settings`; optional `version`, `projectTag`. 200 is a **plain-text** confirmation. |
21| POST | `/submit-batch` | `batchName`, `type`, array `settings`; optional parallel `jobNames`, `version`, `projectTag`. 200 schema has `batchName`, `jobs`, `totalJobs`. |
22| GET | `/jobs` | Exact lookup or cursor-paginated listing; shapes below. |
23| POST | `/jobs/search` | `jobNames` (up to 1,000), optional `organization`, `includeSubjobs`, `jobEmail`. Returns `jobs`, `notFound`, `statuses`. |
24| POST | `/result` | `jobName`; optional `fileName`, `pdbsOnly`, `jobEmail`, `noAsync`. 200 JSON string URL or 202 preparing object. |
25| POST | `/stop-job` | `jobName`; stops queued/running work, including stoppable batch children. Returns `message`, `stoppedCount`. |
26| DELETE | `/delete-job` | `jobName`; soft-deletes the job/batch children from listings. Result files remain. Unknown name: 400. |
27| PUT | `/upload/{filename}` | Binary body; optional `folder`. This route redirects to the upload service; follow redirects. |
28| GET | `/files` | Optional `folder`, `includeFolders=true`; complete array of name strings for that folder, no pagination. |
29| DELETE | `/delete-file` | Query `filePath` **or** `folder`. A folder request removes its files. |
30| GET | `/usage-statistics` | `statistic=hours\|weighted_hours\|jobs`, `scope=user\|organization`; details below. |
31| POST | `/submit-pipeline` | Legacy inline execution: `jobName`, `stages`, conditional `initialInputs`, optional `projectTag`. |
32| POST | `/run-pipeline` | Legacy saved execution: `jobName`, `pipelineName`, nonempty `initialInputs` array, optional `version`. |

Endpoint map

MethodPathRequest and response
GET/tools-catalogPublic catalog; also at host-level /tools.json. Optional type/tag filters; tools contains public types and conditional required settings.
GET/toolsAccount-scoped array with name, descriptions, trimmed settings, and optional output metadata. custom=true selects legacy custom tools only.
GET/tools/{name}/schemaJSON Schema for the settings object. Optional version pins a custom build. 404 covers missing, inaccessible, and mid-deploy tools.
POST/validate-jobtype, object/array settings; optional jobName (single), jobNames (array), version. HTTP 200 contains a valid verdict.
POST/submit-jobjobName, type, object settings; optional version, projectTag. 200 is a plain-text confirmation.
POST/submit-batchbatchName, type, array settings; optional parallel jobNames, version, projectTag. 200 schema has batchName, jobs, totalJobs.
GET/jobsExact lookup or cursor-paginated listing; shapes below.
POST/jobs/searchjobNames (up to 1,000), optional organization, includeSubjobs, jobEmail. Returns jobs, notFound, statuses.
POST/resultjobName; optional fileName, pdbsOnly, jobEmail, noAsync. 200 JSON string URL or 202 preparing object.
POST/stop-jobjobName; stops queued/running work, including stoppable batch children. Returns message, stoppedCount.
DELETE/delete-jobjobName; soft-deletes the job/batch children from listings. Result files remain. Unknown name: 400.
PUT/upload/{filename}Binary body; optional folder. This route redirects to the upload service; follow redirects.
GET/filesOptional folder, includeFolders=true; complete array of name strings for that folder, no pagination.
DELETE/delete-fileQuery filePath or folder. A folder request removes its files.
GET/usage-statistics`statistic=hours\weighted_hours\jobs, scope=user\organization`; details below.
POST/submit-pipelineLegacy inline execution: jobName, stages, conditional initialInputs, optional projectTag.
POST/run-pipelineLegacy saved execution: jobName, pipelineName, nonempty initialInputs array, optional version.
Raw lines 12 to 33
34## Discovery and validation
36`/tools` is an array, not `{"tools": [...]}`. Each trimmed parameter has `name`
37and `required`; optional metadata includes `type`, `description`, `default`,
38`options`, `extension`, and `list`. Filter built-ins client-side; arbitrary search
39query parameters are not documented. `/tools?custom=true` does not discover
40current custom deployments: use the deployed name and `/tools/{name}/schema`.
42The latter is a **JSON Schema document**, not the trimmed parameter array and not
43an MCP `parameters` envelope. Domain strings may carry `x-tamarind-type`. Numeric
44strings and sequence normalization are not fully checked by JSON Schema bounds;
45use `/validate-job` for domain validation and file existence. Keep `version`
46consistent across schema, validate, and submit for a pinned custom build.
48For valid credentials, `/validate-job` returns 200 whether valid or invalid:
50- Single success: `{"valid": true, "normalized": {...}}`. Current `normalized`
51 contains cleaned settings and defaults intended for submission. Inspect these
52 defaults for model/sample-count changes, then submit that settings object.
53- Single failure: `valid: false`, `error`, possibly `missing_fields` and `code`.
54 `missing_fields` may be empty despite failure. Do not interpret quota/policy
55 codes as sequence-format errors.
56- `job_name` reflects name normalization when `jobName` was supplied;
57 `job_name_changed` indicates a change. Persist this stored name.
58- The guide additionally documents `unrecognized_settings`: correct every typo,
59 even if `valid` is true. Unknown settings sent directly to submit are carried
60 through and may silently leave the intended optional field at its default.
61- For array input, inspect **presence of `results`**, not just `valid`.
62 `results` holds one verdict per row, with its `index`, and top-level `valid`
63 aggregates all rows. If `results` is absent, the whole request was rejected and
64 top-level `error` explains why. Array validation supports at most 1,000 rows
65 per call and approximately 4.5 MB; large normalized responses can also require
66 smaller chunks. Validate all rows, not a representative sample.
68Field validation does not reserve compute or re-check every organization policy,
69queue constraint, or custom-tool deployment state. A valid verdict can still be
70rejected at submission. Do not manually add internal routing settings.

Discovery and validation

/tools is an array, not {"tools": [...]}. Each trimmed parameter has name and required; optional metadata includes type, description, default, options, extension, and list. Filter built-ins client-side; arbitrary search query parameters are not documented. /tools?custom=true does not discover current custom deployments: use the deployed name and /tools/{name}/schema.

The latter is a JSON Schema document, not the trimmed parameter array and not an MCP parameters envelope. Domain strings may carry x-tamarind-type. Numeric strings and sequence normalization are not fully checked by JSON Schema bounds; use /validate-job for domain validation and file existence. Keep version consistent across schema, validate, and submit for a pinned custom build.

For valid credentials, /validate-job returns 200 whether valid or invalid:

  • Single success: {"valid": true, "normalized": {...}}. Current normalized contains cleaned settings and defaults intended for submission. Inspect these defaults for model/sample-count changes, then submit that settings object.
  • Single failure: valid: false, error, possibly missing_fields and code. missing_fields may be empty despite failure. Do not interpret quota/policy codes as sequence-format errors.
  • job_name reflects name normalization when jobName was supplied; job_name_changed indicates a change. Persist this stored name.
  • The guide additionally documents unrecognized_settings: correct every typo, even if valid is true. Unknown settings sent directly to submit are carried through and may silently leave the intended optional field at its default.
  • For array input, inspect **presence of results**, not just valid. results holds one verdict per row, with its index, and top-level valid aggregates all rows. If results is absent, the whole request was rejected and top-level error explains why. Array validation supports at most 1,000 rows per call and approximately 4.5 MB; large normalized responses can also require smaller chunks. Validate all rows, not a representative sample.

Field validation does not reserve compute or re-check every organization policy, queue constraint, or custom-tool deployment state. A valid verdict can still be rejected at submission. Do not manually add internal routing settings.

Raw lines 34 to 71
Uses an outside tool MCP :43
72## Names, projects, and batches
74Names are sanitized: whitespace becomes `_` and characters outside
75`[A-Za-z0-9_.-]` are removed. Send an already-clean, nonempty name of at most 200
76characters so exact job lookup works; this is a compatibility limit, not a
77100-character submit validator. Parse the actual name from the successful
78`<stored-name> submitted to queue.` response. On a lost response, check that
79persisted clean name before retrying.
81`projectTag` accepts an organization project ID or name. It is normally optional
82but required under an organization's project policy. A refusal may include
83`availableProjects`; absence does not establish that no projects exist.
85Batch `settings` must be a nonempty array. If `jobNames` is supplied it must have
86the same length, with no duplicates or child name equal to the parent. Stored
87child names may be prefixed/rewritten; enumerate `/jobs?batch=...` rather than
88assuming names. The batch cap is **30,000 jobs after design fan-out**, plus a
89separate approximately **4.5 MB** request cap. The older `{tool, jobs:[...]}`
90alternative is not the current documented contract. Do not rely on undocumented
91`weightedHoursBudget`, `maxRuntimeSeconds`, or `gpuType` keys for limits.

Names, projects, and batches

Names are sanitized: whitespace becomes _ and characters outside [A-Za-z0-9_.-] are removed. Send an already-clean, nonempty name of at most 200 characters so exact job lookup works; this is a compatibility limit, not a 100-character submit validator. Parse the actual name from the successful <stored-name> submitted to queue. response. On a lost response, check that persisted clean name before retrying.

projectTag accepts an organization project ID or name. It is normally optional but required under an organization's project policy. A refusal may include availableProjects; absence does not establish that no projects exist.

Batch settings must be a nonempty array. If jobNames is supplied it must have the same length, with no duplicates or child name equal to the parent. Stored child names may be prefixed/rewritten; enumerate /jobs?batch=... rather than assuming names. The batch cap is 30,000 jobs after design fan-out, plus a separate approximately 4.5 MB request cap. The older {tool, jobs:[...]} alternative is not the current documented contract. Do not rely on undocumented weightedHoursBudget, maxRuntimeSeconds, or gpuType keys for limits.

Raw lines 72 to 92
93## Jobs, status, and pagination
95`GET /jobs` query fields: `jobName`, `batch`, `limit` (1–1,000; default 1,000),
96`startKey`, `batchOnly`, `includeSubjobs`, `includeSequences`, `organization`, and
97`jobEmail`. Use lowercase string `true` for boolean query values.
99- Own-account exact `jobName`: row directly, without a `jobs` wrapper.
100- Listing or `batch`: `{"jobs": [...], "statuses": {...}, "startKey": ...}`.
101 Follow nonempty `startKey` even when a page is short. Batch children paginate.
102- `organization=true` exact-name collisions have a legacy exceptional response
103 shape; prefer a known owner with `jobEmail`. `/jobs/search` instead selects the
104 newest visible match for each requested name, not every member's match.
105- `includeSubjobs=true` includes children in ordinary listings. `batchOnly=true`
106 selects parents. `includeSequences` is retained for compatibility; do not
107 assume it controls `Settings` presence.
108- Page `statuses` is generally page-local, but organization queries may return a
109 collection-wide tally. Do not sum those tallies to infer batch completion.
111Rows require `JobName`, `JobStatus`, `Created`. Other fields are optional:
112`Type`, `Started`, `Completed`, `Batch`, `WeightedHours`, `Settings`, `Score`,
113`User`, `batchStatus`, `AggregationError`, and result/aggregation metadata.
114`Settings` can be JSON text or a structured value; `Score` may be a string,
115number, or null. Do not assume every successful tool emits pLDDT or any score.
116`/jobs/search` omits large settings/scores/errors and result URLs; fetch individual
117details only when needed.
119Single-job terminal states are `Complete`, `Stopped`, `Failed`. Handle legacy
120`Deleted` and lookup errors; a deleted/missing job need not remain pollable.
121A batch parent uses `batchStatus`: `Running`, `Aggregating`, `Complete`, `Stopped`,
122`AggregationFailed`. Discriminate by `Type == "batch"`/`batchStatus`, not
123`statuses`, which also appears for a single job.
125The guide and schema disagree about whether compatibility rows expose a signed
126`resultUrl`; the schema makes it optional. Use `/result` for all downloads.

Jobs, status, and pagination

GET /jobs query fields: jobName, batch, limit (1–1,000; default 1,000), startKey, batchOnly, includeSubjobs, includeSequences, organization, and jobEmail. Use lowercase string true for boolean query values.

  • Own-account exact jobName: row directly, without a jobs wrapper.
  • Listing or batch: {"jobs": [...], "statuses": {...}, "startKey": ...}. Follow nonempty startKey even when a page is short. Batch children paginate.
  • organization=true exact-name collisions have a legacy exceptional response shape; prefer a known owner with jobEmail. /jobs/search instead selects the newest visible match for each requested name, not every member's match.
  • includeSubjobs=true includes children in ordinary listings. batchOnly=true selects parents. includeSequences is retained for compatibility; do not assume it controls Settings presence.
  • Page statuses is generally page-local, but organization queries may return a collection-wide tally. Do not sum those tallies to infer batch completion.

Rows require JobName, JobStatus, Created. Other fields are optional: Type, Started, Completed, Batch, WeightedHours, Settings, Score, User, batchStatus, AggregationError, and result/aggregation metadata. Settings can be JSON text or a structured value; Score may be a string, number, or null. Do not assume every successful tool emits pLDDT or any score. /jobs/search omits large settings/scores/errors and result URLs; fetch individual details only when needed.

Single-job terminal states are Complete, Stopped, Failed. Handle legacy Deleted and lookup errors; a deleted/missing job need not remain pollable. A batch parent uses batchStatus: Running, Aggregating, Complete, Stopped, AggregationFailed. Discriminate by Type == "batch"/batchStatus, not statuses, which also appears for a single job.

The guide and schema disagree about whether compatibility rows expose a signed resultUrl; the schema makes it optional. Use /result for all downloads.

Raw lines 93 to 127
128## Results and uploads
130Check HTTP status **before** decoding `/result`:
132- **200:** `response.json()` is the signed URL string; download with a separate
133 GET, no API key. File requests return that file instead of an archive.
134- **202:** object with `status: "preparing"`, `jobName`, and `message`; wait and
135 repeat the same result call. Do not resubmit compute.
136- `noAsync: true` changes a not-yet-built archive to a 400 instead of 202.
137- A result request can wait up to approximately 290 seconds for archive assembly;
138 use an adequate read timeout and persist the job name to resume later.
139- `fileName: "output.log"` is permitted for failed/stopped jobs before completion.
141Upload uses `Content-Type: application/octet-stream`; `curl -L --data-binary`
142follows the documented upload redirect. The schema describes success fields
143`message`, `fileUrl`, `signedUrl`, but verify registered names with `/files` and
144pass the **relative stored path** (`target.pdb` or `inputs/target.pdb`) to a tool.
145The current guide says a redundant account-email prefix is stripped. Prefer the
146relative path; do not construct internal storage keys. Prior results use
147`JobName/path/to/file.ext`. Inline text can cause side effects/large bodies during
148validation; prefer uploaded paths.

Results and uploads

Check HTTP status before decoding /result:

  • 200: response.json() is the signed URL string; download with a separate GET, no API key. File requests return that file instead of an archive.
  • 202: object with status: "preparing", jobName, and message; wait and repeat the same result call. Do not resubmit compute.
  • noAsync: true changes a not-yet-built archive to a 400 instead of 202.
  • A result request can wait up to approximately 290 seconds for archive assembly; use an adequate read timeout and persist the job name to resume later.
  • fileName: "output.log" is permitted for failed/stopped jobs before completion.

Upload uses Content-Type: application/octet-stream; curl -L --data-binary follows the documented upload redirect. The schema describes success fields message, fileUrl, signedUrl, but verify registered names with /files and pass the relative stored path (target.pdb or inputs/target.pdb) to a tool. The current guide says a redundant account-email prefix is stripped. Prefer the relative path; do not construct internal storage keys. Prior results use JobName/path/to/file.ext. Inline text can cause side effects/large bodies during validation; prefer uploaded paths.

Raw lines 128 to 149
150## Usage and pipeline boundaries
152Usage defaults to `statistic=hours`, `scope=organization`. The response has
153`users` (each with `email`, `total`, per-tool `tools`), `lastUpdated`, and
154`metadata.statistic`/`metadata.scope`. Unauthorized organization scope can narrow
155to the user: read the applied scope. Weighted hours depend on compute resources;
156inspect the current account report rather than assuming a per-job price.
158Legacy `/submit-pipeline` requires `jobName` and `stages`; every stage requires
159`task` and nonempty `toolSettings` keyed by tool name. `initialInputs` is required
160when the first stage uses the `"pipe"` placeholder; file/sequence inputs must
161match that stage. Filter names must be in the tool's published `filterMetrics`.
162`/run-pipeline` requires `jobName`, `pipelineName`, and `initialInputs` (array of
163uploaded PDB filenames or raw sequences with unique basenames), not an `inputs`
164alias. Both return plain-text submission confirmations.
166For new integrations, consult the [pipeline guide](https://docs.tamarind.bio/tamarind/pipelines.md):
167`POST /pipelines/templates` creates a template; `POST /pipelines/validate` checks
168the same run body accepted by `POST /pipelines/submit`: required `name`,
169`bindings`, and exactly one of `templateId` or inline `pipeline`, plus optional
170version and permitted per-node overrides. `idempotencyKey` enables safe retries
171on this newer submit surface. Poll
172`GET /pipelines/runs/{run_id}` with its lowercase statuses:
173`queued`, `running`, `finished`, `partial`, `stopped`, `failed`. Terminal partial
174runs need per-step inspection. Pipeline runs are not visible through `/jobs`.
175Check the live spec for graph/binding shapes and account feature availability.

Usage and pipeline boundaries

Usage defaults to statistic=hours, scope=organization. The response has users (each with email, total, per-tool tools), lastUpdated, and metadata.statistic/metadata.scope. Unauthorized organization scope can narrow to the user: read the applied scope. Weighted hours depend on compute resources; inspect the current account report rather than assuming a per-job price.

Legacy /submit-pipeline requires jobName and stages; every stage requires task and nonempty toolSettings keyed by tool name. initialInputs is required when the first stage uses the "pipe" placeholder; file/sequence inputs must match that stage. Filter names must be in the tool's published filterMetrics. /run-pipeline requires jobName, pipelineName, and initialInputs (array of uploaded PDB filenames or raw sequences with unique basenames), not an inputs alias. Both return plain-text submission confirmations.

For new integrations, consult the pipeline guide: POST /pipelines/templates creates a template; POST /pipelines/validate checks the same run body accepted by POST /pipelines/submit: required name, bindings, and exactly one of templateId or inline pipeline, plus optional version and permitted per-node overrides. idempotencyKey enables safe retries on this newer submit surface. Poll GET /pipelines/runs/{run_id} with its lowercase statuses: queued, running, finished, partial, stopped, failed. Terminal partial runs need per-step inspection. Pipeline runs are not visible through /jobs. Check the live spec for graph/binding shapes and account feature availability.

Raw lines 150 to 176
177## Errors and safe retries
179Classic auth rejection is often 400 recovery JSON; jobs use 401 problem JSON or
180an earlier gateway 403; usage can return 401. A 403 can also mean policy, quota,
181or tool access. Parse the actual error; do not treat every 403 as a budget cap.
182Exact unknown job lookup is 400, not a guaranteed 404.
184Submit 400 errors may be JSON or plain text, independent of Content-Type.
185Ordinary duplicate-name checks return 400; concurrent locks can return 409.
186A 413 means the request was rejected before jobs were created (body shape varies
187by deployment); split it or upload files. For timeout/5xx ambiguity, inspect the
188stored name before retrying a submit. Back off on rate limits, and use batched
189status/validation requests instead of flooding per-job calls.

Errors and safe retries

Classic auth rejection is often 400 recovery JSON; jobs use 401 problem JSON or an earlier gateway 403; usage can return 401. A 403 can also mean policy, quota, or tool access. Parse the actual error; do not treat every 403 as a budget cap. Exact unknown job lookup is 400, not a guaranteed 404.

Submit 400 errors may be JSON or plain text, independent of Content-Type. Ordinary duplicate-name checks return 400; concurrent locks can return 409. A 413 means the request was rejected before jobs were created (body shape varies by deployment); split it or upload files. For timeout/5xx ambiguity, inspect the stored name before retrying a submit. Back off on rate limits, and use batched status/validation requests instead of flooding per-job calls.

Raw lines 177 to 189