---
title: "Offer a paid service · intentic API"
description: "Wire a service into intentic: one JSON endpoint, the Stripe-style signature to verify, what is paid versus refunded, pricing in credits, and how onboarding works today."
url: "https://intentic.dev/developers/services/"
updated: "2026-08-13"
---

Ship

# Offer a paid service

A service is not an extension: no manifest, bundle or repo pointer. It is one HTTPS endpoint that receives metered, signed calls from the platform. The technical bar is verifying a webhook; the catalog itself is curated.

**On this page (7 sections)**

- [What a service is for](#what-a-service-is-for)
- [The shape of a run](#the-shape-of-a-run)
- [Verify the signature](#verify-the-signature)
- [What's paid, what refunds](#whats-paid-what-refunds)
- [Pricing & the split](#pricing-the-split)
- [Admission & the watch](#admission-the-watch)
- [Getting onboarded, honestly](#getting-onboarded-honestly)

## What a service is for

Most tools should be free extensions. Reach for a **service** only when every run costs *you* real money — a paid data API, heavy compute, a licensed corpus — so giving it away per run would mean paying to be used. This page is the provider's side; what a run looks like from the member's seat is on [Earn](https://intentic.dev/earn/).

| | Extension | Service |
| --- | --- | --- |
| **What it is** | Code of yours, run in someone's sandbox | One HTTPS endpoint, run by you |
| **Every run** | Free, forever | Costs credits, priced by you |
| **What ships** | A repo pointer, pinned to a commit | Nothing — a signed call reaches your endpoint |
| **You're paid** | Donations from the monthly pool | A share of every paid run |

## The shape of a run

The platform is the intermediary: it charges the member's credits atomically, forwards their JSON to you with a signature, and relays what you send back **as you send it**. Your answer is a stream — NDJSON, one event per line:`status` lines while you work (each replaces the last, a progress label rather than a log) and exactly one`result` whose `data` is the answer, which ends the run. The status lines appear live on the run's card in the member's chat; the result goes to their agent. A run has five minutes and 2 MB of stream to finish in, and richer event kinds will join the vocabulary as chat learns to render them — a service written today streams the two above.

*The platform is the only party that holds the money or learns who is asking. You get a signed call and stream events back — the stream is your whole side of it, never the member's identity or their wallet.*

1. 1

 The **member** clicks approve on the run's card — their agent cannot spend without that click.
2. 2

 The **platform** charges the credits and forwards one **signed** call to your endpoint.
3. 3

 You **stream events back**: `status` lines while you work, then one `result` that ends the run — up to five minutes.
4. 4

 The platform **relays each event live** — status onto the member's card, the result to their agent.
5. 5

 The **ledger settles** with a receipt: paid. No result — a 5xx, a timeout, a dead stream — and the **charge is reversed**, costing the member nothing.

One run, on the wire

```http
POST /your-endpoint HTTP/1.1
content-type: application/json
x-intentic-timestamp: 1791234567
x-intentic-signature: 3f1a9c… # HMAC-SHA256 over "{timestamp}.{body}"

{ "query": "which subreddits fit a self-hosted agent workspace?" }

HTTP/1.1 200 OK
content-type: application/x-ndjson

{ "event": "status", "text": "Searching 240 communities…" }
{ "event": "status", "text": "Ranking the 12 that fit…" }
{ "event": "result", "data": { "communities": [ … ], "confidence": 0.82 } }
```

## Verify the signature

What you get instead of issuing API keys: every forwarded call carries `x-intentic-timestamp` and `x-intentic-signature`, an HMAC over `{timestamp}.{body}` with the secret you were issued at onboarding, using the same scheme as Stripe webhooks. Verify it and drop everything else, and nobody but the platform can run up your upstream bill. The timestamp check makes a replayed capture die of old age.

The whole verification

```typescript
import { createHmac, timingSafeEqual } from "node:crypto";

// x-intentic-signature = HMAC-SHA256(secret, "{timestamp}.{body}"); reject anything older than a few minutes.
export function verifyIntenticSignature(body: string, timestamp: string, signature: string, secret: string): boolean {
 if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
 const expected = createHmac("sha256", secret).update(`${timestamp}.${body}`).digest("hex");
 const a = Buffer.from(signature, "utf8");
 const b = Buffer.from(expected, "utf8");
 return a.length === b.length && timingSafeEqual(a, b);
}
```

## What's paid, what refunds

The line is **whether a `result` arrived**, not whether the caller liked it. A 4xx refusal is still an answer — "your query was malformed" is the service serving exactly what was asked — and it's paid.

| Your response | The member | You |
| --- | --- | --- |
| `2xx` — a stream ending in its `result` | pays | paid |
| `4xx` — "your query was malformed" | pays | paid |
| `2xx` — a stream that dies before its `result`, or isn't the event format | refunded | not paid |
| `5xx` — your endpoint failed | refunded | not paid |
| Timeout (5 min) or dead socket | refunded | not paid |

Credits are spent atomically before the call, so a refund is immediate — the receipt on the member's card says the run cost nothing. Validate loudly: a clear `4xx` is a real answer, and the paid, honest thing to serve.

## Pricing & the split

You publish one number — **credits per run** — shown on every surface before the run. Price your real cost plus margin, not a teaser; a refusal for lack of credits tells the member what's left and when it resets.

| You set | **Credits per run**: one number, shown before every run. |
| --- | --- |
| You keep | **90%** of every spent credit's dollar value. |
| Public | Your run counts, credits and earnings — per service, month by month, for anyone to read. |

[Earn](https://intentic.dev/earn/) explains what a credit is worth and why the model is unfarmable.

## Admission & the watch

A service has no code to audit — none of yours ships to anyone — so the gate is human, not a pipeline. **Admission is curated**: every listing is created by the platform after a review of who you are, what it claims, and whether the price fits. No form puts an endpoint in front of members' agents unreviewed.

After that, the watch is behavioral — with a service, behavior is the artifact:

| What's watched | How it works |
| --- | --- |
| **Every run** | Public on the ledger, month by month — a track record neither of us can dress up. |
| **Disputes** | Almost none to have: "no answer, no charge" is the platform's code, not a support queue. |
| **Quality** | A service that keeps disappointing is delisted, its run history kept — the way a bad extension listing is blocked. |

Throughout, the member keeps their guard: the agent only *discovers* and offers, and nothing is spent until the owner clicks approve on the run's card — a gate the member's own sandbox enforces, not an etiquette the model is trusted with. Discovery is the agent's job, admission is the platform's, spending stays the member's.

## Getting onboarded, honestly

There's no self-serve signup yet: the first services are onboarded by hand, which buys each one a real conversation about price and shape.

1. 1

 Bring an endpoint that answers the exchange above.
2. 2

 [Say hello on Discord](https://discord.gg/3veuzYp32T) — that's where onboarding starts.
3. 3

 We review it together: who you are, what the listing claims, and whether the price fits.
4. 4

 You leave with a secret and a listing.

The catalog's own `demo-research` service is the living reference: its upstream is run by the platform and verifies exactly the signature on this page, so what this page documents is what the forward actually sends.

## Related pages

- [Earn](https://intentic.dev/earn/): the economy your price plugs into, and the chat flow your service is offered in.
- [Publish & registries](https://intentic.dev/developers/publish/): shipping a free, unmetered extension instead.

More in Ship

[Previous ← Maintain & grow](https://intentic.dev/developers/maintain/)
