---
title: Developers
description: API, MCP and WebMCP docs for daniilkutsyna.com: read-only profile data for agents. No key, no sign-up.
canonical: https://daniilkutsyna.com/developers
last-updated: 2026-11-13
---

# Developers

Read-only access to Daniil Kutsyna's profile for agents and scripts. No API key, no sign-up, no sandbox needed: every endpoint is safe to call against production because nothing here writes.

Four ways in, same data:

| Surface | Where | Use it when |
| --- | --- | --- |
| REST API | `https://daniilkutsyna.com/api/v1` | You want JSON over plain HTTPS |
| MCP server | `https://daniilkutsyna.com/mcp` | Your agent speaks MCP |
| Docs MCP server | `https://daniilkutsyna.com/mcp/docs` | Your agent wants to search or read the documents |
| WebMCP | the [homepage](https://daniilkutsyna.com/) | Your agent runs in a browser |

Static files, if you would rather fetch a document: [llms.txt](https://daniilkutsyna.com/llms.txt), [cv.md](https://daniilkutsyna.com/cv.md), [resume.json](https://daniilkutsyna.com/resume.json), [openapi.json](https://daniilkutsyna.com/openapi.json).

## Quickstart

```
curl https://daniilkutsyna.com/api/v1/profile
curl "https://daniilkutsyna.com/api/v1/roles?q=fintech&limit=3"
curl https://daniilkutsyna.com/api/v1/roles/nettle-founding-engineer
curl https://daniilkutsyna.com/api/v1/contact
```

## Authentication

None. Do not send a key. Requests with an `Authorization` header are accepted and the header is ignored.

## REST API

Base URL: `https://daniilkutsyna.com/api/v1`. All endpoints are `GET` and return `application/json`. Machine-readable description: [openapi.json](https://daniilkutsyna.com/openapi.json).

| Endpoint | Returns |
| --- | --- |
| `GET /api/v1` | Index of endpoints |
| `GET /api/v1/profile` | Pitch, roles he is open to, great-match list, proof, focus, current role, education, skills |
| `GET /api/v1/roles` | Work history, newest first. Paginated. `q` filters by keyword |
| `GET /api/v1/roles/{slug}` | One role |
| `GET /api/v1/contact` | Email, LinkedIn, GitHub |

### Pagination

`GET /api/v1/roles` is cursor-paginated. Parameters: `limit` (1 to 50, default 5), `cursor`, `q`.

```
{
  "data": [ ... ],
  "pagination": { "limit": 5, "has_more": true, "next_cursor": "bzo1", "total": 13 }
}
```

Pass `next_cursor` back as `cursor` to get the next page. A `Link: <...>; rel="next"` header carries the same URL. Cursors are opaque; do not build them yourself.

### Errors

Errors are [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem details, `application/problem+json`:

```
{
  "type": "https://daniilkutsyna.com/developers#error-role_not_found",
  "title": "Role not found",
  "status": 404,
  "code": "role_not_found",
  "detail": "No role with slug \"acme\".",
  "hint": "List valid slugs with GET https://daniilkutsyna.com/api/v1/roles.",
  "instance": "/api/v1/roles/acme"
}
```

| Status | `code` | Meaning | What to do |
| --- | --- | --- | --- |
| 400 | `invalid_parameter` | `limit` out of range | Use 1 to 50 |
| 400 | `invalid_cursor` | Cursor was not issued by this API | Start again without `cursor` |
| 404 | `not_found` | No such endpoint | Check the table above |
| 404 | `role_not_found` | No role with that slug | List slugs with `/api/v1/roles` |
| 405 | `method_not_allowed` | Not a GET | The API is read-only |
| 429 | `rate_limited` | Too many requests | Wait `Retry-After` seconds |

### Rate limits

120 requests per minute per IP address, counted separately for the API and for MCP. Every response carries the IETF `RateLimit` and `RateLimit-Policy` headers, plus `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`. A 429 adds `Retry-After`.

### Versioning and deprecation

The version is in the path: `/api/v1`. Within v1, fields are only added, never removed or renamed. A breaking change ships as `/api/v2`, and v1 then keeps running for at least 90 days while sending `Deprecation` and `Sunset` headers ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745), [RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)). Every response names its version in the `API-Version` header.

## MCP server

`https://daniilkutsyna.com/mcp`, Streamable HTTP, JSON responses, no authentication, no session. Server card: [https://daniilkutsyna.com/mcp/server-card](https://daniilkutsyna.com/mcp/server-card).

```
{
  "mcpServers": {
    "daniil-kutsyna": { "type": "http", "url": "https://daniilkutsyna.com/mcp" }
  }
}
```

| Tool | What it does |
| --- | --- |
| `get_profile` | Start here: pitch, great-match roles, proof, focus, current role |
| `search_experience` | Check a requirement against the track record. `query`, `limit` |
| `get_contact_details` | Email, LinkedIn, GitHub |
| `get_cv` | The whole CV: `markdown`, `json` or `links` |
| `draft_message` | Prepare an email to Daniil. Returns a mailto link. Sends nothing |

The documents are also exposed as MCP resources.

## Docs MCP server

`https://daniilkutsyna.com/mcp/docs`, same transport. Server card: [https://daniilkutsyna.com/mcp/docs/server-card](https://daniilkutsyna.com/mcp/docs/server-card).

| Tool | What it does |
| --- | --- |
| `search_docs` | Find a phrase across the CV, homepage, site index and these docs |
| `read_doc` | Read one document: `llms.txt`, `cv`, `homepage`, `developers` |

## WebMCP

The [homepage](https://daniilkutsyna.com/) registers five tools with `document.modelContext.registerTool`: `get_profile`, `search_experience`, `get_contact_details`, `get_cv` and `get_in_touch`. `get_in_touch` opens a pre-filled email draft in the visitor's own mail app.

## Discovery files

- [Personal Agent Protocol](https://daniilkutsyna.com/.well-known/poppy.json): `poppy.json`
- [Agentic Resource Discovery](https://daniilkutsyna.com/.well-known/ard.json): `ard.json`
- [Sitemap](https://daniilkutsyna.com/sitemap.xml)

## Changelog

- 2026-11-13: v1 of the API, both MCP servers, WebMCP tools.

## Contact

Something broken or missing: [daniil.kutsyna@gmail.com](mailto:daniil.kutsyna@gmail.com).
