AlmondTill/G3N API

On this page

startExportJob

mutation · in the family Reading your records

What it does

Export records to a file in the background — start at one kind of record, follow its links step by step, and let the platform write every matching record as CSV or JSON Lines while you carry on; download the file when it is done.

Start ONE background export — a validated plan run AS YOU, in the background, whose LAST family's records are written to a file: the SearchPlanInput grammar VERBATIM, and the SAME PLAN GATE as searchPlanRun refuses BEFORE any read — an unknown family, a field outside its roster, a hop that is not a relationship of the current family — naming the legal words; a family you may not list refuses the whole plan (the file carries the records exactly as the list lane would answer them to you). format picks the file: csv (RFC 4180 — the header is the union of every record's leaves, nested objects as dotted columns, arrays as JSON cells) or jsonl (one JSON record per line). 📊 The optional report turns the export into a BACKGROUND REPORT: the same ReportSpecInput reportRun takes — its plan MUST equal plan (one plan, two spellings never — refused VALIDATION/INVALID otherwise); the record carries the spec (reportJson) and its words become the report's; the file then holds the report's rows — a projection's chosen columns (the header = the columns in order; the .caption of the reference families you may list rides beside the ids, the others are omitted silently) or an aggregate's groups (count · sums · smallest · largest · average per currency; more than 1000 groups FAILS the job with the words — no file of half-truths). The job records the plan (planJson) and its words, runs ONE bounded step at a time (pages of 1000; at most 50000 records examined — the estimate refuses a plan that cannot fit, with the numbers; 300 s from the start → expired WITH the rows written so far; at most 400 steps; a file past 256 MiB halts partial), writing EVERY record of the last family (the plan's limit does not bound an export), and composes THE FILE at the finish — downloadable for 7 days through exportJobDownload; an in-app notice tells you when it lands. ONE running export per signed-in session — a second start refuses CONFLICT/EXPORT_JOB_ACTIVE naming the holder: wait for it to finish or cancel it. Where no machine is wired the same steps run inline and the job comes back finished. 📊 THE PLAN NAMED ONE WAY — reportId (a saved Report) XOR plan (+ optional report): a saved definition lifts its plan AND its spec — the export becomes that report, run as YOU, the spec re-validated now; only an active definition runs (an inactive or doomed one refuses CONFLICT/REF_STATE naming its state); reportId beside plan or report, or neither of them, refuses VALIDATION/INVALID. A JSON null on an optional input field reads as absent. Requires the unrestricted capability on a USER session (an API key or a collaborator refuses AUTHZ/FORBIDDEN — the job is yours: your user, your session).

What happens

It runs as you, inside your organization, over records you may already list; a plan naming a kind you cannot list is refused before anything is read. One background export runs per sign-in at a time — a second start is refused until the first finishes or you cancel it. An export stops on its own after five minutes, fifty thousand records examined, or 256 MiB written, keeping the rows written so far in the file. Nothing else changes.

Who may call it

Capability area: Reading your records — Looking up and listing the records of your organization.

Arguments

NameTypeRequiredNotes
planSearchPlanInputnoNo further notes.
formatExportFormat ExportFormat!yesNo further notes.
reportReportSpecInputnoNo further notes.
reportIdIDnoNo further notes.

Returns

ExportJob ExportJob! — The record is the durable truth (stepsDone · examined · partCount · rowCount · bytes grow; partial says the run stopped short; problem says why). the budget rule is the SearchJob's VERBATIM — at most 50000 records examined · 300 s from the start (past it the job is expired WITH the parts written) · 400 machine steps — plus ONE bound of its own: 256 MiB on the composed file (the walk halts partial the step before it would cross). The plan's limit does NOT bound the export — every terminal record is written. ONE running export per signed-in session (the EXPORTLOCK marker — a second start refuses CONFLICT/EXPORT_JOB_ACTIVE naming the holder; a running search does not block it). Lifecycle queued → running → done | cancelled | expired | failed: cancel is the owner's (cancelExportJob) or the session's end — NO file is composed on cancel; done stays listed, the other terminals are doomed-class. The generic wire is READ-ONLY (the two reads) — the bespokes own the writes: startExportJob (THE PLAN GATE, then the per-family list-op offer AS THE CALLER — a family you may not list stops the plan before any read; the format csv | jsonl) · cancelExportJob · exportJobDownload (a query — the owner alone AND the reader's own list right over the plan's terminal family). The finish mints an in-app notice (export_finished · export_expired · export_failed), never on cancel.

Example request

mutation ExampleStartExportJob($plan: SearchPlanInput, $format: ExportFormat!) {
  startExportJob(plan: $plan, format: $format) {
    id
    sysId
    type
    caption
    status
    parentId
    rootId
    createdAt
    updatedAt
    revisionNum
    revision
    userId
    sessionId
    planJson
    words
    format
    reportJson
    stepsDone
    examined
    partCount
    rowCount
    bytes
    partial
    fileKey
    fileName
    fileTtl
    startedAt
    finishedAt
    problem
    sfExecutionArn
  }
}

Variables:

{
  "plan": {
    "start": {
      "family": "<family>",
      "filter": {
        "clauses": [
          {
            "field": "<field>",
            "op": "<op>",
            "values": [
              "<values>"
            ]
          }
        ]
      }
    },
    "hops": [
      {
        "direction": "outbound",
        "field": "<field>",
        "family": "<family>",
        "filter": {
          "clauses": [
            {
              "field": "<field>",
              "op": "<op>",
              "values": [
                "<values>"
              ]
            }
          ]
        }
      }
    ]
  },
  "format": "csv"
}

Send it with the envelope naming the version: "extensions": {"at": {"version": {"name":"genesis","number":0}}}.

Example response

{
  "data": {
    "startExportJob": {
      "id": "01900000-0000-7000-8000-37386ae00000",
      "sysId": "EX-EXMP-0000-000F",
      "type": "ExportJob",
      "caption": "Blue jeans",
      "status": "queued",
      "parentId": "01900000-0000-7000-8000-065235280000",
      "rootId": "01900000-0000-7000-8000-a093dd800000",
      "createdAt": "2027-01-31T00:00:00.000Z",
      "updatedAt": "2027-01-31T00:00:00.000Z",
      "revisionNum": 1,
      "revision": "01900000-0000-7000-8000-b7960e180000",
      "userId": "01900000-0000-7000-8000-11f967df0000",
      "sessionId": "01900000-0000-7000-8000-be25a35a0000",
      "planJson": "<plan json>",
      "words": "<words>",
      "format": "<format>",
      "reportJson": "<report json>",
      "stepsDone": 1,
      "examined": 1,
      "partCount": 1,
      "rowCount": 1,
      "bytes": 1,
      "partial": true,
      "fileKey": "<file key>",
      "fileName": "Blue jeans",
      "fileTtl": 1,
      "startedAt": "2027-01-31T00:00:00.000Z",
      "finishedAt": "2027-01-31T00:00:00.000Z",
      "problem": "<problem>",
      "sfExecutionArn": "<sf execution arn>"
    }
  },
  "extensions": {
    "at": {
      "callId": "01EXAMPLE-CALL-ID",
      "version": {
        "requested": {
          "name": "genesis",
          "number": 0
        },
        "serviced": {
          "name": "genesis",
          "number": 0
        }
      }
    }
  }
}

Errors this call can answer