Developers and agents

# Public interfaces for agents.

DDQ publishes a small JSON API and an MCP endpoint for current company information, service availability and contact details. One MCP tool, `submit_inquiry`, sends DDQ a project inquiry on behalf of a consenting person. Nothing on this page creates an order or changes business data.

## Quick reference

| Interface | Endpoint | Format |
| --- | --- | --- |
| Company data | [`GET /api/company.json`](https://ddq.nl/api/company.json) | JSON |
| Service status | [`GET /status.json`](https://ddq.nl/status.json) | JSON |
| MCP | [`POST /mcp/`](https://ddq.nl/mcp/) | JSON-RPC 2.0 over Streamable HTTP |
| OpenAPI | [`GET /openapi.json`](https://ddq.nl/openapi.json) | OpenAPI 3.1 JSON |
| MCP server card | [`GET /.well-known/mcp/server-card.json`](https://ddq.nl/.well-known/mcp/server-card.json) | JSON |
| Full text | [`GET /llms-full.txt`](https://ddq.nl/llms-full.txt) | Markdown: every page and note |
| Any page as Markdown | `Accept: text/markdown` | Markdown |
| AI Catalog | [`GET /.well-known/ai-catalog.json`](https://ddq.nl/.well-known/ai-catalog.json) | AI Catalog 1.0 JSON |

## Authentication

The endpoints listed above contain public information and require no API key, account, cookie or OAuth token. Do not send credentials. DDQ Cloud applications and customer systems are separate services with their own access controls; publication of these read-only interfaces does not grant access to them.

## JSON API

The company endpoint is the canonical machine-readable representation of DDQ’s public company record. Request it with an identifying user agent and cache stable data instead of polling it unnecessarily.

```
curl --fail-with-body \
  -H 'Accept: application/json' \
  -H 'User-Agent: ExampleAgent/1.0 (ops@example.org)' \
  https://ddq.nl/api/company.json
```

Successful responses use `application/json`. Failures anywhere below `/api/` use RFC 9457 problem details with `type`, `title`, `status`, `detail` and `instance`. Clients should branch on the HTTP status and `type`, not on the prose in `detail`.

```
HTTP/1.1 404 Not Found
Content-Type: application/problem+json

{
  "type": "https://ddq.nl/developers/#problem-not-found",
  "title": "Not found",
  "status": 404,
  "detail": "No API resource exists at this path.",
  "instance": "/api/missing"
}
```

## Rate limits

Requests to `/api/company.json` and `/status.json` share a limit of 100 requests per client address in each fixed one-hour window. Every API response includes the current `RateLimit-Policy` and `RateLimit` structured fields plus `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` for older clients. Reset values are seconds until the current window ends.

```
RateLimit-Policy: "hourly";q=100;w=3600
RateLimit: "hourly";r=99;t=1800
RateLimit-Limit: 100
RateLimit-Remaining: 99
RateLimit-Reset: 1800
```

After the quota is exhausted, the API returns `429` problem details and a `Retry-After` header. Respect that value before retrying. The MCP endpoint has no numerical quota for reading, but abusive or unsafe traffic may be restricted. `submit_inquiry` accepts 5 inquiries per client address per hour. Cache `tools/list` using the hints returned by the current protocol.

## MCP negotiation

The MCP server is stateless. Apart from `submit_inquiry`, every tool is read-only. It supports current MCP `2026-07-28` discovery and the legacy initialize handshake for `2024-11-05`, `2025-03-26`, `2025-06-18` and `2025-11-25`. Current requests mirror the method in `Mcp-Method`, carry the protocol version in the HTTP header and request `_meta`, and use `Mcp-Name` when a method addresses a named tool.

### Current stateless discovery

```
curl https://ddq.nl/mcp/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: server/discover' \
  --data '{
    "jsonrpc":"2.0",
    "id":"discover-1",
    "method":"server/discover",
    "params":{"_meta":{
      "io.modelcontextprotocol/protocolVersion":"2026-07-28",
      "io.modelcontextprotocol/clientInfo":{"name":"example-client","version":"1.0.0"},
      "io.modelcontextprotocol/clientCapabilities":{}
    }}
  }'
```

### List capabilities without invoking a tool

```
curl https://ddq.nl/mcp/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: tools/list' \
  --data '{
    "jsonrpc":"2.0",
    "id":"tools-1",
    "method":"tools/list",
    "params":{"_meta":{
      "io.modelcontextprotocol/protocolVersion":"2026-07-28",
      "io.modelcontextprotocol/clientInfo":{"name":"example-client","version":"1.0.0"},
      "io.modelcontextprotocol/clientCapabilities":{}
    }}
  }'
```

The deterministic list exposes `company_info`, `cloud_services`, `contact` and `submit_inquiry`. The first three take no arguments and are annotated `readOnlyHint: true`. Listing these definitions does not execute a tool.

### Resources and prompts

`resources/list` returns `llms.txt`, `company.json`, `status.json`, `AGENTS.md` and every engineering note; read one with `resources/read` and its `uri`. `prompts/get` with name `evaluate_fit` and a `task` argument returns structured instructions for judging whether DDQ fits that task.

### Sending an inquiry

Call `submit_inquiry` only when the person you act for has asked to contact DDQ and agreed to share their details. `name`, `email`, `goal` and `contact_consent: true` are required; `organisation`, `workflow`, `systems_and_data`, `data_sensitivity` and `timescale` are optional. The team receives the inquiry by email and replies to the given address. Identical inquiries are sent once and return the same reference, so retries are safe. Validation problems return a tool result with `isError: true` and an explanation.

```
curl https://ddq.nl/mcp/ \
  -H 'Content-Type: application/json' \
  --data '{
    "jsonrpc":"2.0",
    "id":2,
    "method":"tools/call",
    "params":{"name":"submit_inquiry","arguments":{
      "name":"Jane Doe",
      "email":"jane@example.org",
      "organisation":"Example Hospital",
      "goal":"Reduce the time staff spend matching referral letters to patient records.",
      "data_sensitivity":"Medical data; must stay on-premise.",
      "contact_consent":true
    }}
  }'
```

### Legacy initialize

```
curl https://ddq.nl/mcp/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"initialize",
    "params":{
      "protocolVersion":"2025-11-25",
      "capabilities":{},
      "clientInfo":{"name":"example-client","version":"1.0.0"}
    }
  }'
```

After initialization, a legacy client sends `notifications/initialized` and may request `tools/list`. The server does not issue a session identifier because none of its public tools requires connection state.

## MCP errors

MCP failures remain JSON-RPC responses. Invalid JSON uses `-32700`, invalid request envelopes use `-32600`, unknown methods use `-32601`, and invalid parameters or unknown tool and prompt names use `-32602`, and unknown resource URIs use `-32002`. Current stateless requests also use `-32020` for request/header mismatches and `-32022` for unsupported protocol versions. Clients should preserve the request `id` when correlating responses.

### API problem: not found

The request path does not identify a published API resource. The response status is `404`.

### API problem: method not allowed

The resource exists, but the request method is not supported. The response status is `405` and the `Allow` header lists supported methods.

### API problem: rate limit exceeded

The client address has exhausted its fixed hourly quota. The response status is `429`; wait for the number of seconds in `Retry-After`.

### API problem: internal error

The server could not produce the requested representation. The response status is `500`; retry cautiously or contact DDQ if the condition persists.

## Discovery and change policy

- [AGENTS.md](https://ddq.nl/AGENTS.md) gives concise guidance for automated visitors.
- [llms.txt](https://ddq.nl/llms.txt) and [index.md](https://ddq.nl/index.md) provide readable company context; [llms-full.txt](https://ddq.nl/llms-full.txt) adds every page and note.
- Every page has a Markdown version, returned for `Accept: text/markdown` and linked with `rel="alternate"`.
- [The API catalog](https://ddq.nl/.well-known/api-catalog), [AI Catalog](https://ddq.nl/.well-known/ai-catalog.json), [agent card](https://ddq.nl/.well-known/agent-card.json) and [WebMCP manifest](https://ddq.nl/.well-known/webmcp.json) link the machine interfaces.

The public interfaces are versioned conservatively, but consumers should tolerate new object properties. Material changes will be reflected in the OpenAPI document, discovery metadata and this page. Questions can be sent to [web@ddq.nl](mailto:web@ddq.nl).

---

Source: https://ddq.nl/developers/
Site index for agents: https://ddq.nl/llms.txt
