Portal for developers and agents
Everything this website publishes about me is also available as JSON, as OpenAPI and as markdown. No keys, no sign-up and with open CORS.
Quickstart
Three calls and you have the whole map. Check that the API responds, read it from its specification and ask for the profile.
curl -s https://sgomez.dev/api/v1/health?lang=en
curl -s https://sgomez.dev/openapi.json
curl -s https://sgomez.dev/api/v1/profile?lang=enThere is no separate sandbox or test keys, because the API is read-only and all of its content is already public, so the production environment IS the test environment. There is nothing you can break with a GET. The API answers in Spanish by default and accepts ?lang=en or Accept-Language: en for English.
Endpoints
| Method and path | operationId | What it returns |
|---|---|---|
| GET /api/v1/health | getHealth | Service status and entry links. |
| GET /api/v1/profile | getProfile | Identity, role, location, contact and availability. |
| GET /api/v1/about | getAbout | Long biography and year-by-year timeline. |
| GET /api/v1/projects | listProjects | Published projects, with stack and link. |
| GET /api/v1/projects/{slug} | getProject | A single project by its slug. |
| GET /api/v1/experience | listExperience | Positions, organizations and periods. |
| GET /api/v1/skills | listSkills | Technologies by category, with years of use. |
| GET /api/v1/certifications | listCertifications | Certifications with a link to the credential. |
| GET /api/v1/education | listEducation | Formal education. |
| GET /api/v1/recommendations | listRecommendations | Recommendations written by colleagues and clients. |
| GET /api/v1/search?q= | searchContent | Keyword search over all of the above. |
Collections accept limit (1-100) and offset (0-1000). search accepts q (required) and limit (1-50). Every successful response is wrapped in { "data": …, "meta": … }, and meta includes count, total, self and documentation_url.
Errors
Errors are JSON too, always in the same envelope. code is stable and can be used in a switch; hint says what to do to fix it, which is what an agent lacks when it gets an empty 404.
{
"error": {
"status": 404,
"code": "not_found",
"message": "No project with slug \"nope\".",
"hint": "Known slugs: nudaui, sortlab, … List them with GET /api/v1/projects.",
"documentation_url": "https://sgomez.dev/developers"
}
}400 invalid_parameter: a parameter is missing or out of range.404 not_found: the resource or the endpoint does not exist. Any unknown route under /api responds with JSON, never HTML.405 method_not_allowed: the API is read-only; the response includes theAllowheader.
Authentication and limits
There is no authentication or API keys because there is no private data behind it, so a key would only be red tape. There is no per-client rate limit either, beyond the CDN's ordinary protection. In exchange, responses are served cached (Cache-Control: public, max-age=300, s-maxage=3600). If you need the whole catalog, one call per collection is enough, and repeating the same call in a loop won't give you fresher data.
CORS is open to any origin (Access-Control-Allow-Origin: *) for GET, HEAD and OPTIONS, so the API can be called from the browser. The data is published under the CC BY 4.0 license, so you can use it with attribution.
OpenAPI specification
The specification is OpenAPI 3.1 and is generated from the same code that serves the endpoints, so it cannot describe a route that no longer exists. Each operation has a unique operationId, a summary, a description, typed parameters and a response schema per status code, which is exactly what a function-calling client needs to turn it into tools.
- /openapi.json: Canonical location.
- /api/openapi.json: The same document under /api.
- /api/openapi.yaml: The same document as YAML.
Markdown for agents
Content pages are served as markdown when the request asks for it, following the acceptmarkdown.com convention. The canonical URL does not change and the response carries Vary: Accept, so a CDN does not hand an agent the HTML variant it cached for a browser.
curl -s -H "Accept: text/markdown" https://sgomez.dev/en/about
# or, if you prefer an explicit URL:
curl -s https://sgomez.dev/en/about.mdIt works on /, /about, /contact, /privacy and /developers, and on their English twins under /en/…. Routes that are already markdown (/llms.txt, /agents.md) are served as they are. A route that does not exist returns 404 with a markdown body that says where to go, instead of an error page an agent can't read.
Files for agents
- /llms.txt: Factual summary of the site, with the “when to use this” section.
- /agents.md: Usage instructions covering what this site is for and how to call it.
- /sitemap.xml: All published URLs.
- /robots.txt: AI crawlers explicitly allowed.
- /manifest.webmanifest: Web app manifest.
Versioning
The version is in the path (/api/v1). Within v1 only fields and endpoints are added, because removing a field or renaming an operationId would be a breaking change and would ship as /api/v2. Error code values are part of the contract and are not renamed.