# Xynthera AI — prepaid HTTP integration kit

This kit supports exactly three available prepaid operations. It creates no orders, initiates no payments, uses no subscription API and has no automatic recharge or retries. It is separate from the older Workbench/MCP integrations for previously accepted subscriptions.

## Prepare the client files

Download [the prepaid integration ZIP](https://xynthera-ai.toasty-seal-8877.chatgpt.site/downloads/xynthera-ai-integration-kit.zip), extract it into a private working directory and open your terminal in that extracted directory. `client.py`, `client.mjs` and the `fixtures/` folder must be beside the commands below. Python 3.10+ or Node.js 20+ is required; no package installation is needed for these HTTP clients. Store the private budget code in the server environment variable `XYNTHERA_BUDGET_CODE`, not inside these files.

Individual JSON examples are available from [the three-service guide](https://xynthera-ai.toasty-seal-8877.chatgpt.site/prepaid-api.html). Downloading or reading an example does not consume API credit.

## First successful call

1. Try the browser examples, without an account or card: `/invoice-check.html`, `/contract-check.html`, `/events-check.html` on https://xynthera-ai.toasty-seal-8877.chatgpt.site.
2. Open https://xynthera-ai.toasty-seal-8877.chatgpt.site/payg.html. Select your eligible billing country and exact budget from €10 to €10,000 **including applicable taxes**. Review the operation prices and conditions. Save the private budget code before manually confirming the Stripe payment. Returning from checkout alone does not activate access.
3. Store the code in a private server environment variable `XYNTHERA_BUDGET_CODE`. Never place it in a URL, source repository, shared workflow export, screenshot or client-side application. It is itself the API bearer capability; no separate API key generation is needed.
4. Read status without consuming credit:

```sh
python3 client.py status --output budget-status.json
```

Proceed only when `state` is `active`. `remaining` is shared **micro-EUR excluding taxes**: 1,000,000 means €1. Taxes reduce the usable amount. Maximum invoice/contract/event capacities are alternatives, not additive quotas.

5. Review the synthetic fixture and explicitly opt into one paid call:

```sh
python3 client.py invoice --input fixtures/invoice.json --allow-charge --output invoice-result.json
python3 client.py contract --input fixtures/contract.json --allow-charge --output contract-result.json
python3 client.py events --input fixtures/events.json --allow-charge --output events-result.json
```

Each command consumes its own operation price if this is a new valid request. Files are created with restrictive permissions and existing output files are refused. Save the complete result, including `receipt.report` and `receipt.signature`, yourself. Reports and submitted documents are not stored by this budget service. Standard-library Python 3.10+ and Node.js 20+ examples require no external SDK dependencies.

|Operation|POST route|Cost excluding tax|
|---|---|---|
|Structured invoice reconciliation|`/v1/invoices/reconcile`|€0.005 = 5,000 micro-EUR|
|Supplied OpenAPI contract check|`/v1/contracts/check`|€0.010 = 10,000 micro-EUR|
|Supplied event batch, 1–200 events|`/v1/events/check`|€0.002 = 2,000 micro-EUR|

Base: `https://pfxxzsnboehxsefyajml.supabase.co/functions/v1/xynthera-ai-payg`. Public configuration: `GET /v1/config`. Server-side `Authorization: Bearer <private budget code>` is required for status and paid operations. Calls from other website origins are rejected; run these integrations on your server. `x-api-key` belongs to the older subscription service and does not authenticate prepaid calls.

## Idempotency and failed calls

Use a unique `request_id` for each new control. After a timeout, keep the **identical body and identifier** when retrying manually; do not create a new identifier merely because the response was lost. Within 30 days, identical repeats are reconstructed without another debit; the returned `replayed` flag identifies this. A replay may omit `remaining`: read status for the current balance. Same identifier with changed input or operation is HTTP 409. After metadata expiry, the original identifier remains protected against another debit and a replay can be refused. This is not report archival.

HTTP 200 means a calculation was delivered, not that the underlying business evidence passed: inspect `receipt.report.analysis` and its findings. A valid result reporting a discrepancy is charged. Invalid inputs and failed signing are not charged. Invoice input is structured data, not a PDF/OCR upload; the contract is an OpenAPI document, not a legal contract; event checks do not attest external delivery. Signatures bind our calculation to supplied data and do not independently certify a payment or regulatory compliance. The clients preserve signatures but do not cryptographically verify them; follow the published JWKS/signature guidance before relying on provenance.

|HTTP/code|Action|
|---|---|
|401 `authentication_required`|Use the complete correct private budget code; never send it to support.|
|402 `paid_access_required`|Check actual activation/revocation with status and support.|
|402 `credits_exhausted`|Read shared balance. A new manually confirmed purchase creates a separate code/balance.|
|400 `invalid_input`, `invalid_json`, `request_id_required`|Fix the payload before another call.|
|409 `request_id_conflict`|Restore the exact original payload for retry; new business request requires a new ID.|
|409 `idempotency_metadata_expired`, `report_policy_changed`|Use your saved report; contact support with a redacted reference.|
|413 input/body/report limit|Reduce the supplied data; default body maximum is 64 KiB.|
|429 / 503|No automatic retry in this kit. Check status and retry the same request manually when appropriate.|

No production timing SLA is claimed. Time to first paid call depends on manual checkout and payment confirmation. Local fixture validation is separate from payment/signature/live ledger verification. Tests in this kit use local mocks and synthetic data, never a paid customer account.

```sh
python3 -m unittest -v test_client.py
node --test client.test.mjs
```

## JavaScript, server-side

```js
import {readFileSync,writeFileSync} from 'node:fs';
import {XyntheraPaygClient} from './client.mjs';
const client = new XyntheraPaygClient({recoveryCode: process.env.XYNTHERA_BUDGET_CODE});
const status = await client.status(); // free read
if (status.state !== 'active') throw new Error('Budget inactive');
const input = JSON.parse(readFileSync('fixtures/invoice.json','utf8'));
// Explicit paid operation below: review input and cost before running.
const result = await client.run('invoices/reconcile',input);
writeFileSync('invoice-result.json',JSON.stringify(result,null,2),{flag:'wx',mode:0o600});
```

Create/check the private output location before a production call. An output-file error after the server response does not reverse a debit; retry the exact same ID/body to reconstruct a receipt.

## curl, server-side

The code is supplied through curl stdin configuration so it is not included in command-line arguments. Never enable shell tracing or verbose HTTP logs. This is a **paid call**; review the price and input first. For status, omit data/request and use `/v1/status`.

```sh
printf 'header = "Authorization: Bearer %s"\n' "$XYNTHERA_BUDGET_CODE" |
  curl --config - --silent --show-error --fail-with-body --max-time 20 \
    --header 'Content-Type: application/json' \
    --data-binary @fixtures/invoice.json \
    --output invoice-result.json \
    https://pfxxzsnboehxsefyajml.supabase.co/functions/v1/xynthera-ai-payg/v1/invoices/reconcile
```

Protect the output directory and do not follow redirects. Save successful result files immediately. An HTTP error is not a successful signed report; inspect the HTTP status and error code.

## n8n / Make / Postman

Use an ordinary HTTP request step on your server: method POST, the exact allowlisted operation URL, JSON body from the corresponding fixture, and an Authorization Bearer credential stored privately by your platform. Do not export a credential value into a shared workflow. Status is a separate GET step. Disable automatic retries until you have explicitly preserved the original request ID and entire payload. An agent may run checks against already paid credit, but it cannot purchase or recharge autonomously through this kit. This is HTTP integration guidance, not a deployed MCP, n8n or Make adapter.

Postman: import `postman.json`, set `private_budget_code` locally as a secret, then send only the reviewed request. Do not export that value or use an unattended collection runner. n8n: import one `n8n-invoice.json`, `n8n-contract.json` or `n8n-events.json`; the paid HTTP node is disabled and the workflow inactive. Configure a private Header Auth credential (`Authorization`, value `Bearer <your private code>`), review the synthetic body and cost, and explicitly enable only that node before manual execution. These templates are structurally checked but were not imported/executed in a live n8n instance. Persist the complete response yourself; check automation-platform execution-log retention before supplying production data.

## Local AI / MCP connection

The dependency-free Node.js 20+ `mcp/server.mjs` adapter bridges a local stdio MCP client to the three existing prepaid cloud HTTP APIs. See `mcp-onboarding.md`, `claude-desktop.example.json` and `mcp/README.md`. Paid calls are blocked with the default zero session cap; set a positive consumption cap only after explicit authorization. There is no remote OAuth connector, order creation, purchase or recharge. Nine local MCP tests use mocks/synthetic credentials; client-specific live onboarding still requires qualification.
