# Quickstart (https://upapi.io/docs/quickstart)



## 1. Create an account [#1-create-an-account]

Sign up at [app.upapi.io](https://app.upapi.io) with an email and password, or
with Google or Apple. When guest access is enabled you can also explore the
marketplace and the dashboard without an account at all, and convert to a real
account later without losing what you created.

Signing up creates your organization automatically. Keys, usage and billing all
belong to that organization rather than to you personally, so inviting a
teammate later does not mean re-issuing keys.

## 2. Create an API key [#2-create-an-api-key]

Go to [Dashboard → API keys](https://app.upapi.io/dashboard/api-keys) and create
a key. It has the shape:

```
upapi_YOUR_KEY_HERE
```

That is the literal prefix `upapi_` followed by 48 hex characters — 54
characters in all.

<Callout type="warn" title="The key is shown exactly once">
  Only a SHA-256 hash of the key is stored, so nobody — including us — can show it to you again.
  Copy it when it appears. If you lose it, delete the key and create another.
</Callout>

An organization can hold up to 20 keys, and can create up to 10 keys per hour.

## 3. Make a call [#3-make-a-call]

Every operation is a `POST` to its slug on `api.upapi.io`, with the key in the
`x-api-key` header and the input as a JSON body.

<Tabs groupId="upapi-docs-lang" items="['cURL', 'Node', 'Python']">
  <Tab value="cURL">
    ```bash title="GitHub trending repositories"
    curl -X POST https://api.upapi.io/github-trending.get \
      -H 'x-api-key: upapi_YOUR_KEY' \
      -H 'content-type: application/json' \
      -d '{"language":"typescript","since":"weekly","limit":5}'
    ```
  </Tab>

  <Tab value="Node">
    ```ts title="GitHub trending repositories"
    import { UpAPI } from '@upapi/sdk';

    const upapi = new UpAPI({ apiKey: process.env.UPAPI_API_KEY });

    const repos = await upapi.call('github-trending.get', {
      language: 'typescript',
      since: 'weekly',
      limit: 5,
    });
    ```
  </Tab>

  <Tab value="Python">
    ```python title="GitHub trending repositories"
    import os, requests

    repos = requests.post(
        'https://api.upapi.io/github-trending.get',
        headers={'x-api-key': os.environ['UPAPI_API_KEY']},
        json={'language': 'typescript', 'since': 'weekly', 'limit': 5},
    ).json()
    ```
  </Tab>
</Tabs>

A successful call returns the operation's output directly — no envelope to
unwrap:

```json
{
  "language": "typescript",
  "since": "weekly",
  "totalCount": 5,
  "repos": [
    {
      "position": 1,
      "fullName": "owner/repo",
      "url": "https://github.com/owner/repo",
      "description": "…",
      "language": "TypeScript",
      "totalStars": 48213,
      "starsToday": 612,
      "forks": 2140
    }
  ],
  "fetchedAt": "2026-08-06T12:00:00.000Z"
}
```

Operations with a required input reject an empty body. `pokeapi-pokemon.get`
needs a `name`:

```bash
curl -X POST https://api.upapi.io/pokeapi-pokemon.get \
  -H 'x-api-key: upapi_YOUR_KEY' \
  -H 'content-type: application/json' \
  -d '{"name":"pikachu"}'
```

<Callout title="Slugs are not the same as manifest ids">
  An operation's internal id may contain several dots (`pokeapi.pokemon.get`), but the callable slug
  collapses everything except the trailing method segment into hyphens — so you call
  `pokeapi-pokemon.get`. The marketplace and [`/api/catalog`](https://app.upapi.io/api/catalog)
  always show the callable form; use what they show.
</Callout>

## What to read next [#what-to-read-next]

* [Authentication](https://upapi.io/docs/authentication) — how keys behave and what they scope to.
* [Errors](https://upapi.io/docs/errors) — the one error shape, and every code behind it.
* [Rate limits](https://upapi.io/docs/rate-limits) — burst limits, weighted units, response headers.
* [TypeScript SDK](https://upapi.io/docs/sdk) — if you would rather not hand-roll `fetch`.
