> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x402layer.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Processors — Quickstart

> Deploy a function, call it, and see what it cost. Every command here was run against production.

<Note>These are real commands with real responses — you can run them now. The dashboard UI is still being finished, so everything here is the CLI.</Note>

## Install

```bash theme={null}
npm i -g @singularity-layer/cli
```

Auth is a Solana wallet signature — the CLI uses `~/.config/solana/id.json` by default, or pass `--keypair`. Your key never leaves your machine.

```bash theme={null}
singularity whoami
```

## 1. Scaffold

```bash theme={null}
mkdir my-processor && cd my-processor
singularity processors init my-processor
```

You get two files: `processor.json` (the manifest) and `processor.js` (your code).

## 2. Write the function

```js processor.js theme={null}
export default {
  async fetch(request) {
    const { input } = await request.json();
    return Response.json({ greeting: `hello ${input.name}` });
  }
}
```

### TypeScript and npm packages

If you want imports, types, or a package from npm, add `--bundle`:

```bash theme={null}
npm i zod
singularity processors deploy --bundle --entry processor.ts
```

The bundling happens **on your machine**, with esbuild, and we ship the result. We deliberately never
run `npm install` for you: a postinstall script is arbitrary code, and executing it on infrastructure
that holds platform credentials is not something scanning makes safe. Your bundle crosses the boundary;
your `node_modules` never does.

Because the target is an isolate, a dependency reaching for `fs`, `child_process` or raw sockets fails
**here, on your terminal**, naming the file that imported it — rather than inside a run a buyer already
paid for.

## 3. Declare what it needs

```json processor.json theme={null}
{
  "manifest_version": 1,
  "slug": "my-processor",
  "name": "My Processor",
  "description": "One sentence buyers and agents will read.",
  "lane": "managed",
  "price_usd": "0.01",
  "input_schema":  { "type": "object", "properties": { "name": { "type": "string" } } },
  "output_schema": { "type": "object", "properties": { "greeting": { "type": "string" } } },
  "limits": { "timeout_ms": 5000, "cpu_ms": 1000, "subrequests": 1 },
  "egress": { "allow": [] },
  "secrets": []
}
```

<Tip>**Keep `limits` tight.** The ceiling we hold before each run is derived from `timeout_ms`, so a 5-second processor reserves a fraction of what a 600-second one does. Declaring honestly is directly cheaper.</Tip>

## 4. Deploy

```bash theme={null}
singularity processors deploy
```

```
deployed  my-processor

invoke token (shown once, saved to .singularity.json):
  sk-sglproc_ECpZQbXq-1aENejIPsY0QnXyVhUvhcXRbSmurMotun0
```

The **invoke token** is shown once. It is your server-side credential — the one you put behind your own product if you resell. Rotate it with `singularity processors rotate`.

## 5. Run it

```bash theme={null}
singularity processors run '{"name":"world"}'
```

```json theme={null}
{ "greeting": "hello world" }
```

Runs typically complete in under 200ms plus your own work. Anything slower than the sync window returns `202` with a `poll_url` and a run token; send `Prefer: respond-async` to get that immediately.

## 6. See what happened

```bash theme={null}
singularity processors logs
```

```
7 runs   failure rate 0.0%   platform faults 0

2026-08-07 07:38:37  completed  186ms
2026-08-07 07:38:35  completed  199ms
```

Your **failure rate is public** — it appears on your listing, because buyers pay for runs that fail after starting. Platform faults are ours and are excluded, so a bad day on our side never counts against you.

### Your own console output

Whatever your code printed is captured per run, which is how you actually debug one:

```bash theme={null}
singularity processors logs --logs <run_id>
```

```
     0ms  log   parsing input with zod
   184ms  log   calling the model
   611ms  error rate limited, retrying
```

Every `console.log` / `warn` / `error` / `info` / `debug` call is captured, capped, stripped of terminal
escape sequences, and deleted with the run after 30 days. Anything you printed is here — including
anything a caller sent you, if you printed it.

It is best-effort observability, not an audit trail: it records what your code asked `console` to print,
so code that writes output another way is not captured.

`singularity processors logs --follow` tails new runs as they happen.

## 7. Go live

```bash theme={null}
singularity processors publish
```

Now it is in the catalogue, callable by anyone, and exposed as an MCP tool.

<Warning>
  Your Solana payout wallet must be able to receive USDC. If it has never held any, publishing is refused
  with instructions — send any amount of USDC to it once, then publish again. This is a Solana rule: you
  cannot transfer a token to an account that does not exist yet. It does not apply to Base or Robinhood.
</Warning>

<Note>
  By default buyers pay you in USDC on Solana, at the wallet you deployed with. To also accept USDC on
  Base or USDG on Robinhood Chain, add a `payout` block — see
  [which chains buyers can pay on](/cloud/processors/pricing#which-chains-buyers-can-pay-on). One
  `price_usd` covers every chain.
</Note>

## Calling a published processor

Without payment, you get the price:

```bash theme={null}
curl -X POST https://processors.x402compute.cc/processors/my-processor/run \
  -H 'content-type: application/json' -d '{"input":{"name":"world"}}'
```

```json theme={null}
{
  "x402Version": 1,
  "accepts": [{ "payTo": "<the publisher's wallet>", "maxAmountRequired": "10000", "asset": "EPjFW…Dt1v", "network": "solana" }],
  "error": "payment required"
}
```

Pay it and retry with an `X-Payment` header — any x402 client does this automatically. The money goes
straight to the publisher.

`accepts` carries **one entry per chain that publisher accepts**, so a processor with a `payout` block
returns several. Pick the one whose `network` you can sign for — `solana`, `base`, or `robinhood` — and
pay that entry. `maxAmountRequired` is the same integer on all of them, because every asset is a
6-decimal stablecoin.

## Calling your own, from your own product

Use the invoke token. No payment, because you are paying for the compute yourself:

```bash theme={null}
curl -X POST https://processors.x402compute.cc/processors/my-processor/run \
  -H "Authorization: Bearer $SGL_PROCESSOR_TOKEN" \
  -H 'content-type: application/json' -d '{"input":{"name":"world"}}'
```

## Common rejections

| Response                           | Meaning                                                        |
| ---------------------------------- | -------------------------------------------------------------- |
| `400 input_required`               | body must be `{"input": …}`                                    |
| `402`                              | it is a paid processor and you sent no payment                 |
| `404 not_found`                    | unknown, unlisted, or deleted — deliberately indistinguishable |
| `429 too_many_concurrent_runs`     | at the per-processor concurrency cap                           |
| `402 insufficient_runtime_credits` | your own balance cannot cover the run's ceiling                |
