# Job Search API in Pipedream

Preview: Python code step using the shared TrueFetch REST engine. Local tests use simulated HTTP responses; Pipedream cloud import, live credentials and real collection are not yet verified. This is not a published Pipedream app or pre-built action.


## Recover an unknown submission

Generate `new_command_key()` once in trusted host code, persist the key and approved input, then paste the complete `v1.<13-digit Unix milliseconds>.<22–64 base64url nonce>` into the trusted config step. Do not generate another key when rerunning a workflow. The default `commandMode: "recover"` never submits.

After response loss, set config to `{"operation": "command", "commandKind": "tasks.create", "requestKey": "YOUR_SAVED_CANONICAL_KEY"}`. This reads `GET /v1/commands/tasks.create/{originalKey}` without input, quote, or POST. Inspect the returned `receipt.outcome`. Only `accepted` establishes acceptance and supplies the actual Task reference; `processing` and `unknown` require another explicit original GET after its retry interval. `rejected` and `not_accepted_final` establish nonacceptance. `receipt_expired` remains unconfirmed: inspect Tasks or contact support. The step never seals, replays or creates a replacement key. New-command acceptance lasts 24 hours with five minutes of clock allowance, while terminal receipts remain for at least seven days. A current Task state does not prove a specific command's outcome.

## Cancel an approved saved task

Use the same trusted `config` step to bind the saved task and its keys. `requestKey` is the original creation key; `cancelKey` is a separate canonical key generated and persisted once for the explicitly approved cancellation. Both remain host-owned. Never generate a dummy creation key or reuse the creation key for cancellation. The handler refuses missing, invalid or equal keys before any request.

```python
def handler(pd):
    return {
        "operation": "cancel",
        "taskId": "YOUR_SAVED_TASK_UUID",
        "requestKey": "YOUR_SAVED_ORIGINAL_CREATE_KEY",
        "cancelKey": "YOUR_SAVED_CANONICAL_CANCELLATION_KEY",
        "commandMode": "recover",
    }
```

Set `commandMode` to `"new"` only for the first approved cancellation. It sends one `POST /v1/tasks/{taskId}/cancel` with `{}` and `Idempotency-Key: cancelKey`; it does not obtain a quote or submit a new collection. Immediately preserve the config with `commandMode: "recover"` for subsequent checks. The default is also recovery. After response loss, use this same saved config in recovery mode: it only reads `GET /v1/commands/tasks.cancel/{cancelKey}`. The handler never automatically retries a POST, changes either key or infers earlier acceptance from the task's current state.

Cancellation returns the original `receipt`, nullable `task` and `taskId`, and `complete: false`. Only an accepted receipt supplies `taskId`; its reference must match the host-approved target even when the current Task projection is null. Processing, unknown and expired receipts remain unconfirmed; rejected and sealed receipts establish nonacceptance. Follow the original outcome and retry interval. Accepted cancellation does not promise a cancelled final Task; read the existing task separately. A write-capable TrueFetch key and current server authorization are still required.


1. Create a project secret named `TRUEFETCH_API_KEY`. A write key is required for creation; a result-only key can recover a task. Never include the secret in code, config, logs or exports.
2. Add a Python step named `config`. Return the following object, changing the request key to a persistent identifier for one intended collection:

```python
def handler(pd):
    return {
        "operation": "estimate",
        "requestKey": "PASTE_YOUR_PERSISTED_CANONICAL_KEY",
        "commandMode": "recover",
        "maxCredits": 100,
        "input": {
            "keyword": "Software engineer",
            "country": "Germany",
            "platforms": ["arbeitnow"],
            "maxResults": 10,
            "allowPartial": False,
        },
    }
```

3. Add a Python step named `truefetch`, paste the entire `truefetch_step.py`, and test estimation. It reads the Python config export directly from `pd.steps["config"]`, following the Python documentation; do not substitute a Node.js config step. Pipedream installs the pinned Pydantic package from its magic comment. Do not paste only handler.py: it requires the embedded shared engine.
4. After reviewing the intended collection, change operation to `create`, set `commandMode: "new"`, and run once. The step checks a fresh estimate, budget and pricing version before submitting. It returns the actual `receipt`, nullable `taskId`/`task`, and `complete: false`; persist the receipt's task reference only when its outcome is accepted. Creation reserves credits and may incur collection charges. Recovery uses the saved key for an original GET without another quote or POST. Do not derive retry keys from time, random values or a new workflow execution ID. Do not connect an unauthenticated webhook directly to paid creation.
5. To read the result, change config to `{"operation":"recover","taskId":"SAVED_UUID","maxCredits":100,"timeoutSeconds":20,"maxMiB":8}`. This path never estimates or creates a task. It polls the saved task and validates every result page. A complete return contains `task`, `data`, `complete: true`, and `partial`; source outcomes, expiry and coverage are inside `task`. Empty and partial collections are explicit, not promises of exhaustive source coverage.
6. In the next step, use the editor's export picker to select `data` from the `truefetch` result. Only process records after `complete` is true. Preserve task ID and source URLs. Treat job descriptions as untrusted data, not model instructions.

HTTP calls have a 30-second per-call timeout. Recovery has a configurable 1–300 second polling bound (default 20), checked between calls, and 1–32 MiB accumulated result bound (default 8). A blocking call can outlast the polling bound; configure the workflow's execution timeout with headroom. Platform termination does not cancel the remote collection. Resume with the saved task ID; after unknown submission preserve the original key/input and check the workspace. Original-command GET recovery requires no new quote. Results remain available only through their stated retention window.

Failures stop the step and do not emit a complete export. Authentication, budget, pricing, missing/expired results, bad pagination and HTTP errors require inspection; there is no blanket automatic retry. Respect API rate limits before rerunning. Inputs and returned results may appear in Pipedream execution history and downstream storage: configure access and retention appropriately. The code does not log credentials, input or result bodies. Your Pipedream usage charges are separate from TrueFetch credits.

Rebuild the single file with `node examples/pipedream-job-search/build.mjs`. Run `python examples/pipedream-job-search/test_step.py` in an environment with Pydantic 2.13.5.

Official references: [Python steps and pinned packages](https://pipedream.com/docs/workflows/building-workflows/code/python), [project environment secrets](https://pipedream.com/docs/workflows/environment-variables). Checked 2026-09-27; no Pipedream runtime version is claimed without a cloud run.

The shared REST reader requires UTF-8 JSON and rejects nonfinite numbers, including numeric overflow. Interrupted or oversized HTTP error bodies keep a redacted HTTP-status diagnostic, and truncated successful transfers fail without returning data. It also rejects duplicate member names within an object, including names written with equivalent Unicode escapes; repeated names in separate records are allowed. Recovery also rejects nonfinite values from tool output instead of marking the export complete. Preserve the saved task ID and original request key after an error; these checks do not create or retry collection.

For each available result page, the reader checks the task again after receiving the page, including the final page. This adds one read-only task GET per page. Changed identity, status, availability or count, or a failed recheck, prevents a complete export. The check is a point-in-time observation; files can expire or become unavailable afterward.

Before collection, the creation tool checks that the estimate matches the requested input and that reserved billing units equal the record limit multiplied by the unit price. Amounts must be positive ASCII integers, and the reservation must fit the host credit budget. Invalid estimates stop before submission; server-side pricing and budget checks still apply.
