# Preflight Checks (`josedrobles/preflight-checks`) Actor

Verify before the irreversible step: package existence in npm/PyPI, Bitcoin transaction decoding, EU-law citation check, CVE record lookup, and EU AI Act obligation retrieval. Deterministic answers with official sources. Pay per check.

- **URL**: https://apify.com/josedrobles/preflight-checks.md
- **Developed by:** [Jose D Robles](https://apify.com/josedrobles) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event + usage

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Preflight Checks

> Cheap, deterministic checks an agent runs **before** the irreversible step.

Before an agent installs a package, signs a transaction, or publishes a claim
that cites EU law, it can ask one question: *is this real, and what exactly is
it?* Preflight answers with facts and an official link — never with a verdict.

***

### Checks

| Endpoint | Price | Call it before… |
|---|---:|---|
| `POST /v1/deps/check` | **$0.05** | installing packages a model suggested, to catch names it invented |
| `POST /v1/btc/tx-inspect` | **$0.10** | signing or broadcasting a Bitcoin transaction |
| `POST /v1/btc/tx-context` | **$0.10** | needing chain context for a Bitcoin transaction's inputs before signing |
| `POST /v1/legal/cite-check` | **$0.10** | publishing a claim that cites EU law |
| `POST /v1/cve/check` | **$0.05** | acting on a CVE identifier produced by a model |
| `POST /v1/ai-act/obligations` | **$0.10** | you need the AI Act articles that mention an obligation for a role |

Free routes: `GET /v1/coverage` (this catalogue) and
`GET /v1/<endpoint>/schema` (JSON Schema of each input).

***

### How it works

This Actor runs in **Standby mode**: it is a plain HTTP server, always warm.
You call an endpoint and get the result in the response body — there is no
dataset or key-value store to read afterwards.

Authenticate with your Apify token, as with any Standby Actor:

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/deps/check" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ecosystem":"npm","packages":["left-pad"]}'
```

***

### Endpoints

#### `POST /v1/deps/check` — $0.05

Call before installing packages suggested by a language model. Returns, for each npm or PyPI package name, whether it actually exists in the registry, whether it is deprecated or yanked, and — when the name is not found — the closest real package names. Catches hallucinated dependencies (slopsquatting) before an agent installs them. Never inspects package contents and never returns a safety verdict.

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/deps/check" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ecosystem":"npm","packages":["left-pad"]}'
```

Returns:

```json
{
  "ecosystem": "npm",
  "checked_at": "2026-09-02T21:40:00Z",
  "results": [
    {
      "name": "jscodeshift-react",
      "exists": false,
      "verdict": "not_found",
      "official_url": "https://www.npmjs.com/package/jscodeshift-react"
    }
  ]
}
```

#### `POST /v1/btc/tx-inspect` — $0.10

Call before signing or broadcasting a Bitcoin transaction. Decodes a raw transaction hex or a PSBT and returns inputs, outputs, script types, addresses, vsize, fee rate when derivable, and objective signals such as RBF, dust outputs, non-standard sighash flags and unsigned inputs. Parses only the bytes you send: no network access. Describes the transaction; never advises whether to sign it.

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/btc/tx-inspect" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"raw":"0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000"}'
```

Returns:

```json
{
  "kind": "psbt",
  "txid": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
  "version": 2,
  "locktime": 0,
  "vsize": 141,
  "weight": 561,
  "fee_sats": 1410,
  "fee_rate_sat_vb": 10,
  "inputs": [
    {
      "prev_txid": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "prev_vout": 1,
      "sequence": 4294967293,
      "script_sig": "",
      "witness": [],
      "witness_utxo_value_sats": 50000,
      "address": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
      "partial_sigs": 0,
      "has_final_script": false
    }
  ],
  "outputs": [
    {
      "value_sats": 12000,
      "script_pubkey": "0014751e76e8199196d454941c45d1b3a323f1433bd6",
      "script_type": "p2wpkh",
      "address": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"
    },
    {
      "value_sats": 330,
      "script_pubkey": "5120cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
      "script_type": "p2tr"
    }
  ],
  "signals": [
    "rbf_enabled",
    "dust_output",
    "unsigned_inputs"
  ],
  "thresholds": {
    "dust_output_sat": 546,
    "high_fee_rate_sat_vb": 100
  }
}
```

#### `POST /v1/btc/tx-context` — $0.10

Call before signing a Bitcoin transaction when you need chain context for its inputs: whether each prevout exists, whether it is already spent, its value in sats and its confirmations. Resolves up to 10 inputs against a public explorer at about one request per second, so a full batch can take over 20 seconds; figures reflect chain state at checked\_at. Describes on-chain facts with source links; never advises whether to sign.

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/btc/tx-context" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"inputs":[{"txid":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b","vout":0}]}'
```

Returns:

```json
{
  "network": "mainnet",
  "checked_at": "2026-09-11T12:00:00Z",
  "source": "blockstream.info",
  "inputs": [
    {
      "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
      "vout": 0,
      "exists": true,
      "spent": false,
      "value_sats": 5000000000,
      "script_pubkey": "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac",
      "confirmations": 912345,
      "official_url": "https://blockstream.info/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b?output:0"
    }
  ],
  "total_input_sats": 5000000000,
  "disclaimer": "Chain state at checked_at, from a third-party explorer. Not a recommendation to sign."
}
```

#### `POST /v1/legal/cite-check` — $0.10

Call before publishing a claim that cites EU law. Checks that the cited instrument exists in our pinned corpus, that the cited article exists within it, and whether your quoted text actually appears in that article. Covers the AI Act, GDPR, NIS2, DORA and the Cyber Resilience Act. Returns the official article text with a EUR-Lex link. Citation verification only: it never gives legal advice or classifies systems.

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/legal/cite-check" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"instrument":"CELEX:32024R1689","article":"Article 11"}'
```

Returns:

```json
{
  "instrument_exists": true,
  "article_exists": true,
  "quote_match": "not_found",
  "official_url": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
  "corpus_version": "eurlex-2026-09-05",
  "attribution": "© European Union, https://eur-lex.europa.eu, CC BY 4.0",
  "disclaimer": "Citation verification, not legal advice."
}
```

#### `POST /v1/cve/check` — $0.05

Call before acting on CVE identifiers produced by a model. Returns whether each CVE record exists and its state (published or rejected), with severity and the official CVE record link. Catches fabricated advisory references. Does not tell you whether to patch.

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/cve/check" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ids":["CVE-2021-44228"]}'
```

Returns:

```json
{
  "checked_at": "2026-09-02T21:40:00Z",
  "results": [
    {
      "id": "CVE-2026-12345",
      "exists": true,
      "state": "published",
      "cvss_v3": 7.5,
      "official_url": "https://www.cve.org/CVERecord?id=CVE-2026-12345"
    }
  ]
}
```

#### `POST /v1/ai-act/obligations` — $0.10

Call when you need to know which articles of the EU AI Act mention a given obligation for a given role (provider, deployer, importer, distributor, authorised representative). Returns the matching articles with headings, excerpts and EUR-Lex links from a pinned corpus version. Retrieval over the official text: it does not classify your system or assess compliance.

```bash
curl -X POST "https://josedrobles--preflight-checks.apify.actor/v1/ai-act/obligations" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role":"provider","topic":"technical_documentation"}'
```

Returns:

```json
{
  "corpus_version": "eurlex-2026-07-01",
  "articles": [
    {
      "article": "Article 11",
      "heading": "Technical documentation"
    }
  ],
  "disclaimer": "Retrieval over the official text, not legal advice."
}
```

***

### Billing

One event is charged **only when a check succeeds** (HTTP 200). A malformed
body (400), an input that cannot be processed (422), a body over the limit
(413) or an unreachable upstream registry (502) are **not charged**.

***

### What this Actor does not do

- **No verdicts.** It never answers `safe`, `eligible` or `compliant`, and
  never tells you whether to install, sign, patch or publish. It reports what
  the registry or the official text says, with a link, and you decide.
- **No legal advice.** The EU-law checks verify citations and retrieve article
  text. They do not classify your system or assess compliance.
- **No language model in the critical path.** Every check is deterministic:
  parsing, a public-registry lookup, or a search over a pinned corpus.
- **No stored input.** Request bodies are not persisted; logs keep a hash.

***

### Sources

| Source | Licence / policy |
|---|---|
| npm registry | API publica sin clave; no se redistribuye corpus |
| PyPI JSON API | API publica documentada |
| blockstream.info API | blockstream.com/terms v1.0 (2018): no prohibe uso comercial, sin clave ni atribucion; Esplora MIT |
| mempool.space API | Sin ToS restrictivo; software AGPL-3.0; no prohibe uso comercial ni exige clave |
| EUR-Lex textos consolidados | CC BY 4.0 (Decision 2011/833/UE) - reutilizacion comercial expresa |
| CVE Services API (cve.org) | Dominio público |

EU legal texts are reproduced from EUR-Lex unmodified except for splitting by
article, under CC BY 4.0 (Decision 2011/833/EU). Every response that quotes
them carries the attribution
`© European Union, https://eur-lex.europa.eu, CC BY 4.0` and the pinned
`corpus_version`.

`/v1/btc/tx-inspect` parse **only the bytes you send**: no network call to any node or explorer.

`/v1/btc/tx-context` **do query public block explorers** (blockstream.info API and mempool.space API) to resolve on-chain state, so their answers reflect what those explorers reported at `checked_at`.

# Actor input Schema

## Actor input object example

```json
{}
```

# Actor output Schema

## `serverUrl` (type: `string`):

Base URL of the running server. POST to /v1/deps/check, /v1/btc/tx-inspect, /v1/btc/tx-context, /v1/legal/cite-check, /v1/cve/check, /v1/ai-act/obligations. GET /v1/coverage lists every check for free.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("josedrobles/preflight-checks").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("josedrobles/preflight-checks").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call josedrobles/preflight-checks --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,josedrobles/preflight-checks"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/O1guMK9eBOWN5JTF6/builds/TiHgoNTWoyV0VcA3g/openapi.json
