Skip to content
ESEnoque SousaData · Automation · AI

For machines

Documentation for agents

How to read this portfolio programmatically: endpoints, formats, caching, bot policy and the interfaces this site deliberately does not implement.

Last build: 2026-08-02T13:31:08.710Z

Purpose

This is a personal portfolio. Everything an automated client can read here is already published as HTML on the same origin — the machine-readable interfaces exist so that an agent does not have to scrape a styled page to answer a question about this person's work.

Every representation is generated from one typed dataset in the repository. The HTML page, the Markdown twin, the JSON API, the OpenAPI description, the MCP tools and the JSON-LD all read from it, so they cannot disagree about a fact.

Formats and negotiation

HTML and Markdown use distinct URLs to keep intermediary-cache behavior unambiguous. Use `/api/v1/markdown/en` or `/api/v1/markdown/pt` for Markdown.

The explicit routes make the returned representation independent of request headers.

  • `curl https://enoquesousa.com/api/v1/markdown/en` — Markdown, `200`.
  • `curl https://enoquesousa.com/en` — HTML, `200`, byte-for-byte what a browser gets.
  • `curl https://enoquesousa.com/en` — HTML, independent of `Accept`.
  • Assets, API routes and `.well-known` documents are never negotiated into Markdown.

The REST API

Public, anonymous and read-only. Responses are `{ data, meta }`; `meta.contentRevision` is a digest of the content, so a client can tell whether a cached copy is still current without diffing payloads.

Every endpoint accepts `?locale=en|pt`, defaulting to `en`. An unrecognized locale is answered with `400` rather than a silent fallback. Unknown project slugs return `404` with the list of real slugs. Unsupported methods return `405` with an `Allow` header.

Endpoints
MethodPathMedia typePurpose
GET/robots.txttext/plainCrawl preferences and the Content-Signal policy.
GET/sitemap.xmlapplication/xmlIndexable HTML pages, with hreflang alternates.
GET/llms.txttext/plainShort index of this site for language models.
GET/llms-full.txttext/plainThe entire portfolio as Markdown.
GET/openapi.jsonapplication/jsonOpenAPI 3.1 description of the REST API.
GET/.well-known/api-catalogapplication/linkset+jsonRFC 9727 catalog pointing at the API, its description, docs and health.
GET/.well-known/agent-skills/index.jsonapplication/jsonIndex of published Agent Skills, with a digest of each artifact.
GET/.well-known/agent-skills/enoque-sousa-portfolio/SKILL.mdtext/markdownThe skill artifact itself.
GET/api/healthapplication/jsonLiveness, schema version and content revision. Never cached.
GET/api/v1application/jsonRoot of the versioned API; lists its own resources.
GET/api/v1/profileapplication/jsonName, role, headline, positioning, public links.
GET/api/v1/projectsapplication/jsonSelected work. Filters: ?featured=true, ?tech=Python.
GET/api/v1/projects/{slug}application/jsonA single project by stable slug.
GET/api/v1/skillsapplication/jsonPractice areas, stack by group, flat technology list.
GET/api/v1/experienceapplication/jsonRoles, most recent first, with ISO start and end.
GET/api/v1/certificationsapplication/jsonPublished certifications and courses.
GET/api/v1/contactapplication/jsonContact channels already printed on the page.
GET/api/v1/markdown/{locale}text/markdownThe portfolio as Markdown, addressed directly.

Versioning

The API path carries the major version (`/api/v1`). `meta.schemaVersion` carries the payload semver: a minor bump adds fields, a major bump changes or removes them. Project slugs are stable identifiers and are never reused for a different project.

`meta.updatedAt` is the build timestamp of the running deployment, not a hand-edited date.

Caching

Content only changes when a new build is deployed, so the JSON resources are `public, max-age=600, s-maxage=3600, stale-while-revalidate=86400` and the discovery documents are cached longer. `/api/health` is `no-store` — a cached health check reports the health of the cache.

HTML pages are `private, max-age=0, must-revalidate`. Explicit Markdown routes are publicly cacheable and do not vary by request headers.

Bots and content use

`robots.txt` declares a single policy — `ai-train=no, search=yes, ai-input=yes` — in the wildcard group and, identically, in a group naming the known AI crawlers, because a crawler obeys only its most specific matching group. Nothing is disallowed: this is a portfolio, and being found is the point.

Read that as: index it, quote it, use it to answer questions about this person. No permission is granted to use it as training data. `robots.txt` is a statement of preference to well-behaved clients, not an access control, and it is not treated as one here.

Authentication

There is none, and that is a decision rather than an omission. Nothing here is protected, nothing is writable, and no operation acts on anyone's behalf — so there is no resource an authorization server could protect. No OAuth or OpenID Connect discovery document is published, because publishing one would advertise a flow that does not exist.

Limits and what is absent

MCP discovery is deferred until its transport lifecycle and edge controls complete a separate production audit. The read-only GET endpoints are cacheable and not separately limited.

Deliberately not implemented: OAuth and OpenID Connect discovery, protected-resource metadata, Web Bot Auth signature directories, WebMCP, and the agent-commerce protocols. Each is either inapplicable to a site with no protected resources or dependent on a specification that is not stable enough to publish against. The repository documents the reasoning per item.

Problems with these interfaces

If an endpoint here is wrong, unreachable or describes something inaccurately, the fastest route is email — the same address published in the contact section of the portfolio.

sousa3086@outlook.com