# Latitude 10 docs Push one OpenAPI document and Latitude 10 keeps every version of it in a registry, then makes it a hosted reference with an API client, a docs site, TypeScript and Python SDKs, and an MCP server for AI agents. These pages say how each one works, what it refuses and where its limits are. Start with the [quickstart](quickstart), or read [Concepts](get-started/concepts) first. ## Registry Every push is kept as a version, scored from 0 to 100 by the [readiness rules](registry/readiness-rules) and compared with the version before it for [breaking changes](registry/breaking-changes). Your CI pushes with a project key, through the GitHub Action or one `curl` line. [More about the registry](registry/index). ## Reference An owner or admin publishes a version as an interactive reference at `/r//`, made from your document with no third-party script on the page. You can embed it on your own site, or keep it on ours. [More about the reference](api-reference/index). ## API client Every hosted reference has Try it: requests go from the reader's browser straight to your API. On Pro and up, a proxy reaches APIs without CORS on the hosts you verify, and your team can save requests in shared collections. [More about the API client](api-client/index). ## Docs Write your guides in Markdown in your repository and push them from CI. They're built once, at push, and served beside your reference, with `llms.txt`, Markdown for every page and a docs MCP server for agents. [More about docs hosting](docs-hosting/index). ## SDKs On Pro and up, your CI asks for a TypeScript or Python package made from a registry version and your `latitude10.sdk.json`. Its version follows the breaking-change diff, and the generated code is yours, under the MIT licence. [More about SDKs](sdks/index). ## MCP Every operation in your document becomes an MCP tool at `/mcp//`. Each tool call is one request to your API, and agents use a key you hand them or, on Pro and up, sign in through your own identity provider. [More about hosted MCP](hosted-mcp/index). ## For agents These docs are built for models too. [llms.txt](https://docs.latitude10.tech/llms.txt) lists every page, every page is also served as Markdown, `skill.md` is an agent skill that points at the rest, and the docs' MCP server at `/mcp` searches them with no key. For help adopting the platform, see our [professional services](https://latitude10.tech/services). ## Where this comes from - `app/platform/_lib/modules.ts` - `app/docs/_lib/build.ts` - `app/registry/_lib/ci.ts` --- # Quickstart From sign-in to a published reference, with your own OpenAPI document. You need a document, YAML or JSON, and a terminal. ### 1. Sign in Go to the [sign-in page](https://latitude10.tech/workspace/sign-in) and continue with GitHub, or ask for an emailed link. The link works once, for 15 minutes. Your first sign-in creates your workspace, named after you. ### 2. Create a project On your workspace's page, name a project. A project holds one OpenAPI document and every version of it. Owners, admins and editors can create projects. ### 3. Create a CI key On the project's page, create a key under **CI keys**. It's shown once: copy it into your environment, never into a file you commit. ```sh export LATITUDE10_KEY=... # paste it from the project page BASE=https://latitude10.tech/api/registry/v1 ``` ### 4. Push your document Send the document as the request body: ```sh curl -sS -X POST "$BASE/versions?label=first" -H "Authorization: Bearer $LATITUDE10_KEY" --data-binary @openapi.yaml ``` The answer is the new version, with `201`: its number (`seq`), its readiness `score` out of 100, and `url`, its page in your workspace. Push the same bytes again and you get the same version back with `200`; no second version is made. ### 5. Read the score The latest version, and the report that explains its score: ```sh curl -sS "$BASE/versions/latest" -H "Authorization: Bearer $LATITUDE10_KEY" ``` ```sh curl -sS "$BASE/versions/1/report" -H "Authorization: Bearer $LATITUDE10_KEY" ``` Each rule in the report lists its findings and how to fix them. The [readiness rules](registry/readiness-rules) explain the score. ### 6. Publish the reference On the project's page, choose **Publish** under Reference. Until then it's private: only members see it. Owners and admins can publish. ### 7. See the outputs Once it's published, the project's page links each output: - the reference, with Try it, at `https://latitude10.tech/r//`; - the docs site, once you push a docs folder and publish it, at `https://latitude10.tech/docs//`; - the MCP server, at `https://latitude10.tech/mcp//` once you set it up on the project's MCP page. ## When something goes wrong Every error is JSON with an `error` that says what to do. A `401` means the key is missing or revoked, a `422` that the body isn't an OpenAPI 3.0 or 3.1 document in one file, and a `429` that a quota is reached until `resetsAt`. [Errors](registry-api/errors) lists them all. ## Where this comes from - `openapi/registry-v1.yaml` - `app/api/workspace/auth/route.ts` - `app/workspace/_lib/users.ts` - `app/workspace/_lib/workspaces.ts` - `app/workspace/_lib/projects.ts` - `app/workspace/_lib/onboarding.ts` - `app/workspace/_lib/keys.ts` - `app/reference/_lib/access.ts` - `app/api/registry/v1/versions/route.ts` - `app/api/registry/v1/versions/latest/route.ts` --- # Concepts ## Account You sign in with GitHub or with a link we email you. Your first sign-in creates a workspace for you, named after you. ## Workspace A workspace holds your projects, its members and its plan. Its slug is made from its name: lowercase letters, digits and dashes, with `-2`, `-3` and so on added when the slug is taken. The slug is in every URL the workspace serves, such as `/r//`. Renaming a workspace changes its name, not its slug. ## Members and seats Each member has a role: owner, admin, editor or viewer. [Roles](../enterprise/roles) says what each can do. Members and open invitations both take a seat, and the number of seats depends on the plan: see [Plans and limits](plans-and-limits#workspace). ## Invitations Owners and admins invite people by link, with the role they'll get. A link works once, within 7 days, and only while a seat is free. Revoking an invitation frees its seat. ## Project A project is one API: one OpenAPI document and every version of it. Its slug is made the same way as a workspace's. The reference, the API client, the docs, the SDKs and the MCP server all belong to a project. How many projects a workspace may have depends on its plan. ## Versions Every push that changes the document makes a new version, numbered `seq` from 1 in the order they were pushed. Pushing the same bytes as the latest version returns it instead of making a new one. Each version keeps its score, its report and its diff against the version before it. How many versions are kept depends on the plan: see [Plans and limits](plans-and-limits#registry). ## The sample A new project can start from our sample document, an Orders API, so you can see every output before your own document is at hand. A version made from it is marked `source: "sample"`. Its server is a placeholder, so Try it and the MCP server can't call it, and no SDK is published from it. Push your own document any time to replace it. ## Where this comes from - `app/workspace/_lib/users.ts` - `app/workspace/_lib/workspaces.ts` - `app/workspace/_lib/slugs.ts` - `app/workspace/_lib/projects.ts` - `app/workspace/_lib/permissions.ts` - `app/workspace/_lib/sample.ts` - `app/registry/_lib/versions.ts` --- # Keys and tokens Every key and token the platform issues starts with a prefix that says what it is. A secret scanner can match them, and so can you. | Prefix | What it is | Who makes it | Where it goes | How it's stored | How to revoke it | | --- | --- | --- | --- | --- | --- | | `l10p_` | A project key, for CI | An owner or admin, on the project's page under **CI keys** | Your CI's secrets, sent as `Authorization: Bearer` to the registry API | SHA-256 hash only | **Revoke** on the project's page | | `l10m_` | An MCP key, for agents | An owner or admin, on the project's MCP page | The agent's MCP client, sent as `Authorization: Bearer` to the hosted MCP server | SHA-256 hash only | **Revoke** on the project's MCP page | | `l10a_` | An MCP access token | The MCP server's sign-in, when a person signs in through your identity provider | Sent by the MCP client to that one server | SHA-256 hash only | The client revokes it, or an owner or admin signs the person out on the MCP page | | `l10r_` | An MCP refresh token | The same sign-in, beside the access token | Sent by the MCP client to that server's token endpoint | SHA-256 hash only | As for `l10a_`. It's replaced on every use | | `l10c_` | An MCP OAuth client id | The MCP server, when a client registers itself | The client's own settings | As is: it isn't a secret | An owner or admin revokes the client on the MCP page | | `l10v_` | A host-verification token | Latitude 10, for the project's MCP server and for its API client proxy | A file or a DNS TXT record on your API's host | As is: it isn't a secret | Nothing to revoke: it proves only that you control the host | `l10_`, with no letter after it, is the seller dashboard's key for kits and payments, not a platform key. ## How secrets are kept CI keys and MCP keys are stored only as SHA-256 hashes, and shown once. Your API credential for hosted MCP is sealed with AES-GCM 256 under a Worker secret, with a fresh IV each time, and one module decrypts it. So a lost key can't be shown again: revoke it and create another. Access and refresh tokens are kept the same way, as hashes. ## Where this comes from - `app/_lib/auth/keys.ts` - `app/_lib/auth/tokens.ts` - `app/workspace/_lib/keys.ts` - `app/hosted-mcp/_lib/keys.ts` - `app/hosted-mcp/_lib/tokens.ts` - `app/hosted-mcp/_lib/oauth.ts` - `app/hosted-mcp/_lib/server.ts` - `app/hosted-mcp/_lib/credential.ts` - `app/reference/_lib/playground/hosts.ts` --- # Plans and limits Each limit applies per the unit its row names, such as a project, a workspace, a server or a site. A request past a limit is refused, with an error that says so. ## Prices | Plan | Price | Billed annually | | --- | --- | --- | | Free | $0 | $0 | | Pro | $150 a month | $125 a month, billed annually | | Business | $600 a month | $500 a month, billed annually | | Enterprise | By contract | By contract | ## Workspace | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | Seats | 1 | 5 | 10 | By contract | ## Registry | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | APIs (projects) | 1 | 15 | 25 | By contract | | Versions kept | 10 | 200 | 1,000 | By contract | | Pushes per project a day | 20 | 200 | 500 | By contract | | Fix runs per workspace a month | Not included | 100 | 500 | By contract | | Largest spec | 2 MB | 2 MB | 2 MB | By contract | ## Reference | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | Uncached renders per project a day | 2,000 | 50,000 | 200,000 | By contract | ## API client | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | Proxy hosts per project | Not included | 3 | 10 | By contract | | Proxy calls per project a day | Not included | 1,000 | 5,000 | By contract | | Shared collections per project | Not included | 20 | 100 | By contract | | Requests per collection | Not included | 100 | 500 | By contract | | Proxy calls per IP a minute | Not included | 20 | 20 | By contract | | Collection saves per project a day | Not included | 500 | 2,000 | By contract | | Collection storage per project | Not included | 10 MB | 25 MB | By contract | ## Docs | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | Pages per build | 25 | 500 | 2,000 | By contract | | Docs versions per project | Not included | 5 | 20 | By contract | | Branch previews per project | Not included | 5 | 20 | By contract | | Custom domains per workspace | Not included | 3 | 10 | By contract | | Page reads per site a day | 5,000 | 100,000 | 400,000 | By contract | | Docs MCP calls per site a day | 1,000 | 20,000 | 100,000 | By contract | | Bundle size, unpacked | 5 MB | 25 MB | 100 MB | By contract | | Docs pushes per project a day | 10 | 100 | 300 | By contract | ## SDKs | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | Endpoints in an SDK | Not included | 100 | 250 | By contract | | SDK builds per project a day | Not included | 50 | 200 | By contract | ## MCP | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | Tool calls per workspace a month | 1,000 | 50,000 | 250,000 | By contract | | Tool calls per key a minute | 30 | 120 | 300 | By contract | | Keys per server | 2 | 20 | 100 | By contract | | People signing in per server | Not included | 1,000 | 10,000 | By contract | | OAuth clients per server | Not included | 200 | 1,000 | By contract | | Sign-ins per server a day | Not included | 1,000 | 10,000 | By contract | | Claim rules per server | Not included | 20 | 20 | By contract | ## Enterprise | Limit | Free | Pro | Business | Enterprise | | --- | ---: | ---: | ---: | ---: | | SSO connections per workspace | Not included | Not included | 1 | By contract | | SSO email domains per workspace | Not included | Not included | 5 | By contract | | SSO sign-ins per workspace a day | Not included | Not included | 2,000 | By contract | | Audit log retention in days | Not included | Not included | 90 | By contract | | Audit events per workspace a day | Not included | Not included | 5,000 | By contract | | Rows per audit export | Not included | Not included | 50,000 | By contract | ## Where this comes from - `app/pricing/_lib/plans.ts` - `app/workspace/_lib/quotas.ts` - `app/platform/_lib/modules.ts` --- # Registry The registry is where your OpenAPI document lives. Each push from your CI, or an upload on the project's page, becomes a version. ## A version A version is one copy of your document, numbered `seq` in push order, with an optional label and the Git commit it came from. The registry keeps the document exactly as you sent it, so you can download the original of any version it keeps. ## Its score Each version is scored from 0 to 100 by the [readiness rules](readiness-rules): how well an AI agent will understand and call your API. The version's report lists every finding and how to fix it. ## Its diff Each version is compared with the one before it. The diff marks each change [breaking, warning or information](breaking-changes), and the version records how many breaking changes and warnings it has. ## In this section - [Push a version](push): the request, its parameters and its errors. - [The GitHub Action](github-action): score, gate and push from a workflow. - [Readiness rules](readiness-rules): what the score is made of. - [Breaking changes](breaking-changes): every kind of change the diff finds. - [Fixes](fixes): rules-only changes that raise the score, as JSON Patch. - [Versions](versions): how many are kept, and how to read them. ## Where this comes from - `app/registry/_lib/versions.ts` - `app/registry/_lib/diff.ts` - `app/api/readiness/_lib/report.ts` - `openapi/registry-v1.yaml` --- # Push a version ### 1. Send the document `POST /versions` takes the document itself as the request body, YAML or JSON, with a project key: ```sh curl -sS -X POST "$BASE/versions?label=v1.4.0&git_sha=$GITHUB_SHA&git_ref=$GITHUB_REF" -H "Authorization: Bearer $LATITUDE10_KEY" --data-binary @openapi.yaml ``` ### 2. Read the answer A new version answers `201` with its `seq`, `score`, `breaking` and `warnings` counts and `url`, its page in your workspace. If the bytes are the same as the latest version's, you get that version back with `200`, and nothing new is made. ## Parameters All three are optional query parameters. | Parameter | What it's for | | --- | --- | | `label` | The version's name. Without one, the document's `info.version` is used. | | `git_sha` | The commit the document came from. | | `git_ref` | The branch or tag, such as `refs/heads/main`. | ## What the registry accepts - One OpenAPI 3.0 or 3.1 document, in YAML or JSON. - One file: a `$ref` inside the document works, a `$ref` to another file or a URL is refused. The GitHub Action bundles local files into one before it pushes. - Up to 2 MB, on every plan. The registry keeps the newest versions up to your plan's number, and removes the oldest after each push: see [Plans and limits](../get-started/plans-and-limits#registry). ## Errors | Status | When | The `error` | | --- | --- | --- | | `401` | No project key, or a revoked one. | `Send a project key: Authorization: Bearer l10p_…` | | `403` | The workspace has more projects than its plan includes. | `This project is read-only: the workspace has more projects than its plan includes.` | | `409` | Another push landed at the same moment. | `Another version was pushed at the same moment. Push again.` | | `413` | The body is larger than the registry keeps. | The size sent and the most that's kept. | | `422` | It isn't OpenAPI 3.0 or 3.1, it doesn't parse, or it has an external `$ref`. | What's wrong. For a `$ref`: `External $ref isn't supported here: …` and how to bundle it. | | `429` | The project's pushes for today are used. | `Quota reached for this period. It resets at …`, with `resetsAt`. | A push counts against the day's quota before its body is read, so a refused push still counts. Daily quotas reset at midnight UTC. ## Where this comes from - `app/api/registry/v1/versions/route.ts` - `app/api/registry/v1/_lib/route.ts` - `app/registry/_lib/versions.ts` - `app/registry/_lib/bundle.ts` - `app/registry/_lib/usage.ts` - `app/workspace/_lib/quotas.ts` --- # The GitHub Action Our [Action for GitHub workflows](https://github.com/jorgeortega/latitude10-action) scores your document in the workflow, can fail the job on a low score or a breaking change, and can push the version to the registry. It's public, under MIT. ### 1. Add the key Add your project key to the repository's secrets as `LATITUDE10_KEY`. The Action scores and gates without it; pushing and fixes need it. ### 2. Add the step ```yaml - uses: jorgeortega/latitude10-action@v1 with: spec: openapi.yaml min-score: 70 # fail below this; default: report only max-tools: 40 # fail above this many operations; default 40 fail-on-breaking: true # default false push: ${{ github.ref == 'refs/heads/main' }} suggest-fixes: true # paid plans; opens or updates one PR env: LATITUDE10_KEY: ${{ secrets.LATITUDE10_KEY }} # optional ``` ## Inputs | Input | What it does | Default | | --- | --- | --- | | `spec` | The path to your OpenAPI document, YAML or JSON. Local `$ref`s are bundled. Required. | None | | `min-score` | Fail when the readiness score is below this, from 0 to 100. | Empty: report only | | `max-tools` | Fail when the document has more operations than this, since each one becomes an agent tool. | `40` | | `fail-on-breaking` | Fail when the document has breaking changes against its base. | `false` | | `push` | With `LATITUDE10_KEY`, push this version to the registry. | `false` | | `suggest-fixes` | With `LATITUDE10_KEY` on a paid plan, open or update one pull request with rules-only fixes. | `false` | | `label` | The version's label in the registry. | Empty: `info.version` | | `github-token` | The token for the fixes pull request. It needs contents and pull-requests write. | The workflow's token | | `api-url` | The Latitude 10 API. | `https://latitude10.tech` | ## Outputs | Output | What it holds | | --- | --- | | `score` | The readiness score, from 0 to 100. | | `operations` | The number of operations. | | `breaking` | The breaking changes against the base. | | `version-url` | With `push`, the version's page in the registry. | The Action has no input for docs yet. Push a docs folder with `curl` from a step of its own. ## Without the Action One `curl` step pushes the document on every merge to `main`: ```yaml - name: Push the spec to Latitude 10 if: github.ref == 'refs/heads/main' run: > curl --fail-with-body -X POST "https://latitude10.tech/api/registry/v1/versions?git_sha=$GITHUB_SHA&git_ref=$GITHUB_REF" -H "Authorization: Bearer $LATITUDE10_KEY" --data-binary @openapi.yaml env: LATITUDE10_KEY: ${{ secrets.LATITUDE10_KEY }} ``` [Push a version](push) lists what it answers. ## Where this comes from - `app/registry/_lib/ci.ts` - `app/api/registry/v1/versions/route.ts` - `app/registry/_lib/versions.ts` - `app/registry/_lib/bundle.ts` - `app/registry/_lib/usage.ts` --- # Readiness rules Every version you push is scored from 0 to 100 by these rules, version 1.0.3. The version's report lists each rule's findings. ## The score Each rule applies to some of your operations or parameters, and its share is the part of those that pass. A rule with nothing to apply to passes. The score is the sum of each rule's weight times its share, divided by the total weight (88), times 100, rounded to a whole number. ## The rules | Rule | What it checks | Weight | How to fix it | | --- | --- | ---: | --- | | `operation-ids` | Every operation has a clear operationId | 10 | Give each operation an operationId that says what it does (listOrders, refundOrder). It becomes the tool name. | | `descriptions` | Descriptions say what the operation does, when to use it, and what it returns | 10 | Write a description of at least 40 characters per operation, different from the others: models pick tools by it. | | `summaries` | Every operation has a summary | 8 | Add a short summary (under 80 characters): clients show it as the tool's title. | | `parameter-descriptions` | Parameters are described | 8 | Describe each parameter: its meaning, format and allowed values. | | `response-schemas` | Success responses have a JSON schema | 8 | Describe what a 2xx response contains with a JSON schema, so agents know what they'll get back. | | `security` | How to authenticate is described | 8 | Describe your auth in components.securitySchemes and apply it with security. | | `examples` | Operations have an example | 6 | Add an example for each operation (a parameter, request or response example): models copy examples. | | `error-responses` | Errors are described | 6 | Document the errors an operation returns (400, 404, 409…) so agents can recover instead of retrying blindly. | | `pagination` | List endpoints are paginated | 6 | Give list operations a limit and a cursor (or page) parameter: an agent can't read ten thousand rows. | | `json-bodies` | Request bodies are JSON | 5 | Accept application/json for request bodies agents send (form and multipart bodies can't be tool calls). | | `idempotency` | Writes have an idempotency story | 5 | Accept an Idempotency-Key header on POST/PATCH (Agentify honours it for agents), so a retry doesn't do the work twice. | | `enums` | Parameters with a fixed set of values list them | 4 | Give status/sort/type-like parameters an enum (or list the values in the description). | | `tool-count` | A manageable number of tools, with distinct names | 4 | Keep enabled tools to about 40 per server (models choose worse from long lists), and give operations distinct operationIds. | ## Run them yourself The same rules are public as [openapi-agent-check](https://www.npmjs.com/package/openapi-agent-check) (MIT), so you can score a document on your machine or in CI before you push it. ## Where this comes from - `app/api/readiness/_lib/agentify/rules.ts` - `app/api/readiness/_lib/report.ts` - `app/registry/_lib/store.ts` - `app/_lib/entity.ts` --- # Breaking changes Each version you push is compared with the version before it. Every change found has a kind and a level: breaking, warning or information. The version's diff lists them, breaking changes first. ## Breaking | Kind | What changed | | --- | --- | | `operation-removed` | An operation (a method and a path) is gone, and no new operation has its operationId. | | `operation-moved` | An operation’s method or path changed. It’s matched to the old one by its operationId. | | `parameter-removed` | A parameter an operation took is gone. | | `parameter-became-required` | An optional parameter is now required. | | `required-parameter-added` | An operation has a new parameter, and it’s required. | | `request-body-became-required` | An operation’s request body is now required. | | `response-property-removed` | A property is gone from a JSON success response. | | `response-property-type-changed` | A JSON success response, or a property in it, has a different type. | | `response-enum-value-added` | An enum in a JSON success response has a new value, which clients may not handle. | | `request-enum-value-removed` | An enum in a parameter or a JSON request body lost a value clients may still send. | | `success-response-removed` | A 2xx response an operation had is gone. | | `security-requirement-added` | An operation’s security asks for a scheme that a client meeting the old requirement doesn’t have. A new alternative breaks nobody. | | `security-scheme-changed` | A security scheme an operation uses changed its type, location, name, scheme, bearer format or flows. | | `server-url-removed` | A URL in `servers` is gone. | ## Warnings | Kind | What changed | | --- | --- | | `operation-id-changed` | An operation’s operationId changed, so agents see a new tool name. | | `description-removed` | An operation or a parameter lost its description. | | `operation-deprecated` | An operation is now marked deprecated. | ## Information | Kind | What changed | | --- | --- | | `operation-added` | A new operation. | | `optional-parameter-added` | An operation has a new optional parameter. | | `response-property-added` | A JSON success response has a new property. | ## In CI The GitHub Action's `fail-on-breaking` input, off by default, fails the job when the diff has a breaking change. ## Where this comes from - `app/registry/_lib/diff.ts` - `tests/fixtures/registry/diff/` - `app/registry/_lib/ci.ts` --- # Fixes On the paid plans, the registry API answers a document with the changes that raise its readiness score, as a JSON Patch against the document exactly as you sent it. Fixes to your spec are rules-only JSON Patch: no workspace feature sends your spec to an AI model. The paid readiness report on our public site does, outside the workspace. ### 1. Ask for the fixes Send the document as the body, as you would to push it. Nothing is stored and no version is made. ```sh curl -sS -X POST "$BASE/fixes" -H "Authorization: Bearer $LATITUDE10_KEY" --data-binary @openapi.yaml ``` ### 2. Read the patch | Field | What it holds | | --- | --- | | `rulesVersion` | The version of the readiness rules used. | | `scoreBefore` | The document's score as sent. | | `scoreAfter` | Its score with the patch applied. | | `operations` | How many operations the patch improves. | | `patch` | The JSON Patch operations, in order. | The fixes fill in what the rules look for, such as operationIds, summaries, descriptions, parameter descriptions, examples and an `Idempotency-Key` header on writes. Read them before you apply them. ## From the GitHub Action With `suggest-fixes: true` and `LATITUDE10_KEY` on a paid plan, the [Action](github-action) opens or updates one pull request that applies the fixes to your file. ## Limits and errors Each request counts as one fix run against your workspace's monthly runs, before the body is read: see [Plans and limits](../get-started/plans-and-limits#registry). Monthly quotas reset on the first of the month, UTC. | Status | When | | --- | --- | | `403` | The plan has no fixes: `Suggested fixes are part of the paid plans.` | | `413` | The body is larger than the registry reads. | | `422` | The body isn't an OpenAPI 3.0 or 3.1 document in one file. | | `429` | The month's fix runs are used, until `resetsAt`. | ## Where this comes from - `app/api/registry/v1/fixes/route.ts` - `app/registry/_lib/fixes.ts` - `app/registry/_lib/json-patch.ts` - `app/registry/_lib/usage.ts` - `app/registry/_lib/ci.ts` --- # Versions ## How many are kept Each project keeps its newest versions up to your plan's number: see [Plans and limits](../get-started/plans-and-limits#registry). After each push, the oldest beyond that number are deleted, with their source, report and diff. After a downgrade, the old plan's number still holds for 30 days, so nothing is deleted the day you change plans. After that, the next push trims the list to the new plan's number. ## Reading them Every call takes your project key. ### 1. List the versions Newest first: ```sh curl -sS "$BASE/versions" -H "Authorization: Bearer $LATITUDE10_KEY" ``` ### 2. Read one version's report The score's findings, rule by rule: ```sh curl -sS "$BASE/versions/3/report" -H "Authorization: Bearer $LATITUDE10_KEY" ``` ### 3. Download the original The document exactly as it was pushed, as YAML or JSON: ```sh curl -sS "$BASE/versions/3/source" -H "Authorization: Bearer $LATITUDE10_KEY" -o openapi.yaml ``` ### 4. Compare any two versions ```sh curl -sS "$BASE/diff?from=1&to=3" -H "Authorization: Bearer $LATITUDE10_KEY" ``` Each change has a `kind`, a `level` (breaking, warning or info), a JSON `pointer` into the document and a `message`. The kinds are listed in [Breaking changes](breaking-changes). A version number that isn't a number answers `400`, and one that doesn't exist, or was deleted, answers `404`. ## Where this comes from - `app/workspace/_lib/quotas.ts` - `app/registry/_lib/versions.ts` - `app/api/registry/v1/versions/route.ts` - `app/api/registry/v1/versions/[seq]/source/route.ts` - `app/api/registry/v1/versions/[seq]/report/route.ts` - `app/api/registry/v1/diff/route.ts` - `app/api/registry/v1/_lib/route.ts` --- # Hosted API reference A project's reference is made from its latest registry version: every operation, its parameters, request bodies and responses, with Try it to send real requests. It's private until an owner or admin publishes it, and every push after that updates it. Hosted references and docs load no third-party script or font, and each response sends its own content security policy. Our own pages report errors to Sentry, with identifiers removed first. ## Who sees it - Members see the reference in the workspace, published or not. - Once published, anyone with the link reads it at `https://latitude10.tech/r//`. - An unpublished project answers the same `404` as one that doesn't exist, so a private project's name never shows. ## In this section - [Publishing](publishing): publish, unpublish, downloads, search engines and older versions. - [Embedding](embed): the reference inside your own site. - [Markdown in descriptions](markdown): what your document's descriptions may use. - [Caching and security](caching-and-security): the cache, the render cap and the headers. ## Where this comes from - `app/reference/_lib/access.ts` - `app/reference/_lib/page.ts` - `app/r/_lib/respond.ts` - `app/r/[ws]/[project]/route.ts` --- # Publishing the reference Owners and admins publish from the Reference panel on the project's page. The project needs at least one version first. ## The switches | Switch | What it does | | --- | --- | | **Publish** | Anyone with the link can read the reference, and you can embed it. | | **Unpublish** | The public link and every embed stop working at once. | | **Let readers download the OpenAPI file** | Readers get a link to the file exactly as you pushed it. | | **Hide from search engines** | Every page of the reference asks search engines not to index it. **Show to search engines** undoes it. | A reference made from the sample document stays hidden from search engines until you push your own. ## Its addresses | Path | What it serves | | --- | --- | | `/r//` | The latest version. | | `/r///v/` | A version the registry still keeps. Only the latest is indexed by search engines. | | `/r///openapi.yaml` | The latest version's file, if you pushed YAML and downloads are on. | | `/r///openapi.json` | The same, if you pushed JSON. | | `/r///embed` | The frameable page: see [Embedding](embed). | The file is served only in the format you pushed: the other path answers `404`. ## On the Free plan A reference on Free carries a small "Made with Latitude 10" link in its footer. The paid plans don't. ## Where this comes from - `app/workspace/actions.ts` - `app/reference/_lib/access.ts` - `app/reference/_lib/page.ts` - `app/r/_lib/respond.ts` - `app/r/[ws]/[project]/route.ts` - `app/r/[ws]/[project]/v/[seq]/route.ts` - `app/r/[ws]/[project]/openapi.yaml/route.ts` - `app/r/[ws]/[project]/openapi.json/route.ts` --- # Embedding the reference ### 1. Publish the reference Embedding needs a published reference: see [Publishing](publishing). ### 2. Copy the snippet The Reference panel on the project's page shows the snippet for your project. It looks like this: ```html ``` ### 3. Choose a theme Add `?theme=light` or `?theme=dark` to the `src` to fix the theme. Without it, the embed follows the reader's system setting. ## What the embed allows - Only `/embed` may be framed: it sends `frame-ancestors *`. Every other page of the reference sends `frame-ancestors 'none'`. - The embed has no site bar, and otherwise shows what the public reference shows, Try it included. - If you unpublish, the embed shows that the reference isn't published, instead of an error page. ## Where this comes from - `app/workspace/[ws]/[project]/page.tsx` - `app/r/_lib/respond.ts` - `app/r/[ws]/[project]/embed/route.ts` - `app/reference/_lib/access.ts` --- # Markdown in descriptions Descriptions in your OpenAPI document, for the API, a tag, an operation, a parameter, a request body, a schema or a security scheme, are rendered as a safe subset of Markdown. Anything outside it is shown as the text you wrote, never run. ## What's rendered | You write | You get | | --- | --- | | A blank line between paragraphs | Separate paragraphs. Lines next to each other join into one. | | `*text*` or `_text_` | Emphasis. | | `**text**` | Strong text. | | Text in backticks | Inline code. | | A fence of three backticks or tildes, with an optional language | A code block, with the language as its class. | | Lines starting with `-`, `*`, `+` or `1.` | A flat list, bulleted or numbered. | | `[label](https://…)` or `[label](mailto:…)` | A link, marked `rel="nofollow ugc noopener"`. | | `![alt](https://…)` | A link to the image: images aren't loaded. | ## What's shown as text | You write | What the reader sees | | --- | --- | | Raw HTML, such as `` or `