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

# Provider conformance

> Prove your public provider follows the provider contract before anyone connects a real account to it.

Prove your provider handles identity, ordering and evidence correctly before a single real account
depends on it. A public provider is the code that lets trdrs reach a market someone else runs,
written against the published provider contract. Provider conformance runs fourteen rules
against it and tells you, rule by rule, what held and what didn't. A venue can register its manifest and save a private connection from its Providers list.
Publishing a directory profile and qualifying execution are separate steps.
See [Publish a provider integration](/providers/publishing) for discovery and review.

Use this page if you're building a provider. It's a different check from the
[integration conformance](/providers/requirements), which measures software that calls the trdrs API;
this one measures software that trdrs calls. By the end you have an evidence file listing a result
for every rule.

You can run it before you have a vendor account, a certificate or a network connection. The
reference provider in the `@trdrs/reference-provider` package follows the contract exactly and
passes every rule, so running the suite against your own provider shows you the differences, and
those are your work list.

For a real exchange's test environment, trdrs also runs a testnet provider for the exchanges
[Run a testnet provider](/guides/run-a-testnet-provider) names, and that page shows how to qualify
it.

## What it checks

Each rule exists because getting it wrong loses or duplicates someone's trade. The reason comes back
with every result, because a provider that only learns what failed tends to make the check pass
rather than make the behavior right.

| Rule | What it requires |
| - | - |
| `manifest` | The manifest parses under the contract, and doesn't claim it can take orders without session fencing. |
| `grant_echoes_authority` | A session grant repeats the connection, environment, scope and account it was asked for, so it can't be replayed against another. |
| `acquisition_idempotent` | The same request for a session returns the same grant, so a caller that retries never holds two identities for one intent. |
| `fencing_revokes_older` | A newer session generation revokes the older session. The older holder still believes its grant is valid, so the provider is the only place the truth lives. |
| `fencing_refuses_older_acquire` | A generation below the highest can't start a session. Otherwise a restarted reader quietly takes an account back. |
| `payload_hash_verified` | A command whose hash doesn't match its body is refused, because the bytes and the stated intent disagree. |
| `command_idempotent` | The same command id and body return the same receipt, so a retry after a lost answer recovers the first outcome instead of trading again. |
| `command_conflict` | The same command id with a different body is refused. Two intents can't share one name; the first one stands. |
| `absence_is_not_rejection` | A command you have no record of reads as "no evidence", not "rejected". A caller that reads absence as refusal sends the order again. |
| `events_ordered` | Event cursors and account sequence numbers always increase. |
| `events_resume` | Resuming after a cursor returns exactly the events after it, with none missing and none repeated. |
| `unknown_cursor_declared` | A cursor you don't recognize is reported as unknown, never replayed from the start. Starting over quietly is how a consumer applies a day of trading twice. |
| `coverage_only_when_complete` | A snapshot page claims to cover the account only when it's the complete account. A partial page that claims coverage makes an unfinished read look like proof the account is flat. |
| `account_isolation` | A session for one account can't read another. An account id isn't a credential. |

## Run it

Call `runProviderConformance` with a function that sends each of the suite's requests to your provider
and returns what came back, plus the identities to test with:

```ts theme={null}
import { runProviderConformance } from '@trdrs/reference-provider'

const evidence = await runProviderConformance(
  async ({ method, path, query, body }) => {
    const url = new URL(path, 'https://your-provider.example.com')
    for (const [key, value] of Object.entries(query ?? {})) url.searchParams.set(key, value)
    const response = await fetch(url, { method, headers: { 'content-type': 'application/json' }, body: body ? JSON.stringify(body) : undefined })
    const text = await response.text()
    return response.headers.get('content-type')?.includes('event-stream')
      ? { status: response.status, stream: text.split('\n\n').filter(Boolean).map(frame => JSON.parse(frame.replace(/^data: /, ''))) }
      : { status: response.status, body: text ? JSON.parse(text) : undefined }
  },
  {
    connectionId: 'your-connection',
    environment: 'sandbox',
    authorizationRef: 'your-authorization',
    tradableAccountId: 'ACCOUNT-1',
    otherAccountId: 'ACCOUNT-2',
    order: { instrumentId: 'ES-MAR26', providerSymbol: 'ESH6', quantity: '1' },
  },
)
```

`tradableAccountId` and `order` let the suite place one order to test the command rules, and
`otherAccountId` lets it test that one account can't read another. Leave them out and the rules that
need them are skipped, not passed.

## Read the evidence

`runProviderConformance` returns the evidence directly; write it to a file and keep it. It never
contains your `authorizationRef`.

```json theme={null}
{
  "suite": "provider-contract-v1",
  "providerVersion": "your-provider-v1",
  "passed": false,
  "skipped": ["coverage_only_when_complete"],
  "results": [
    { "id": "payload_hash_verified", "outcome": "fail", "detail": "a forged payload hash was accepted with 200", "why": "..." }
  ]
}
```

Each rule has one of three outcomes:

| Outcome | What it means |
| - | - |
| `pass` | The rule was seen to hold. |
| `fail` | The rule was seen to break. `detail` says what was seen. |
| `skipped` | The rule couldn't be tried, for example because no tradable account was given, or the account fit on one page so there was no partial page to check. |

`passed` is `true` only when every rule passed. A skipped rule doesn't count, because approving a
provider for behavior nobody saw is worse than reporting nothing.

The suite runs every rule even when the first one fails, and a provider it can't reach at all comes
back as failures rather than a crash. One run gives you the whole list.

## What it proves

It proves your provider follows the contract's rules on identity, ordering and evidence: the part
that, when it's wrong, loses money without anyone noticing. Test how your market fills under load,
with its own order book, slippage and latency, in your own environment.

## Next steps

<CardGroup cols={2}>
  <Card title="Run a testnet provider" icon="flask" href="/guides/run-a-testnet-provider">
    Qualify a real exchange's test environment behind the contract.
  </Card>

  <Card title="Run a venue" icon="building" href="/guides/run-a-venue">
    See how a venue plugs a provider into its routes.
  </Card>
</CardGroup>

## Data-only readiness

A feed that cannot execute orders must not claim it passed the complete execution suite. Use
`runProviderMarketConformance` from `@trdrs/reference-provider` for evidence explicitly named
`provider-market-data-v1`. It verifies a market-data-only manifest, authenticated readiness,
scoped and repeatable acquisition, connection isolation, fresh bid/ask quotes in increasing
sequence, reacquisition and fencing. It sends no command and always reports
`executionQualified: false`.

Supply a dedicated test connection, its environment, private authorization reference, an
allocated positive generation and authorized instruments. The driver returns parsed market
messages in `stream` for a bounded `/market/events` read. Empty or stale feeds fail; they are not
silently passed. Keep credentials and authorization references out of evidence files.

This check does not prove process-restart durability or vendor recovery after an uncertain
order. Retain separate restart/resubscription evidence for data feeds and the full vendor
conformance evidence before claiming execution.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.