# Quickstart

> Create an API key, install the SDK (or use curl), run your first Google search with SerpKite, read the response and check your credit balance. Takes about five minutes.

This guide takes you from zero to a working search call. Use one of the official SDKs (TypeScript, Python or Go), or any HTTP client: the API is plain JSON over HTTPS.

1. ### Create an account and a key

   Sign in at [app.serpkite.com](https://app.serpkite.com/login?signup=1) with your email, GitHub or Google. New accounts start with 1,000 free credits (2,500 once you link GitHub or Google). No card is needed.

   Open **API keys**, click **Create key**, give it a name such as `local-dev`, and copy the secret. It starts with `skt_live_` and is shown only once.

2. ### Store the key in an environment variable

   Keep the key out of source code. The SDKs and every example in these docs read it from `SERPKITE_API_KEY`:

   ```bash
   export SERPKITE_API_KEY="skt_live_..."
   ```

3. ### Install an SDK (optional)

   The SDKs handle auth, retries, timeouts and typed responses. Skip this step if you prefer curl or your own HTTP client.

   ```bash
   npm install serpkite                          # TypeScript / JavaScript (Node 18+, Bun, Deno, edge)
   pip install serpkite                          # Python 3.9+ (sync and async clients)
   go get github.com/serpkite/serpkite-go   # Go
   ```

   LangChain and CrewAI tools are available too. See [SDKs](https://serpkite.com/docs/sdks).

4. ### Run a search

   `POST /v1/search` takes a JSON object. Only `q` is required. `country` sets the country and `language` the interface language.

   cURL:

   ```bash
   curl https://api.serpkite.com/v1/search \
     -H "Authorization: Bearer $SERPKITE_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"q":"best espresso machine 2026","country":"us","language":"en"}'
   ```

   TypeScript:

   ```ts
   import { SerpKite } from "serpkite";

   const sk = new SerpKite(); // reads SERPKITE_API_KEY
   const res = await sk.search({ q: "best espresso machine 2026", country: "us", language: "en" });
   console.log(res.results[0].title, res.meta.credits_used);
   ```

   Python:

   ```python
   from serpkite import SerpKite

   sk = SerpKite()  # reads SERPKITE_API_KEY
   res = sk.search("best espresso machine 2026", country="us", language="en")
   print(res.results[0].title, res.meta.credits_used)
   ```

   Go:

   ```go
   package main

   import (
   	"context"
   	"fmt"
   	"log"

   	serpkite "github.com/serpkite/serpkite-go"
   )

   func main() {
   	ctx := context.Background()
   	c := serpkite.NewClient() // reads SERPKITE_API_KEY
   	res, err := c.Search(ctx, serpkite.SearchParams{Q: "best espresso machine 2026", Country: "us", Language: "en"})
   	if err != nil {
   		log.Fatal(err)
   	}
   	fmt.Println(res.Results[0].Title, res.Meta.CreditsUsed)
   }
   ```

5. ### Read the response

   Every endpoint returns the same envelope. `request` echoes the normalised request, `results` holds the ten blue links with resolved destination URLs and a canonical `domain`, and `meta` tells you what the call cost and whether the page parsed cleanly. All keys are snake_case.

   200 OK · illustrative:

   ```json
   {
     "request": {
       "endpoint": "search",
       "engine": "google",
       "q": "best espresso machine 2026",
       "country": "us",
       "language": "en",
       "num": 10,
       "page": 1,
       "device": "desktop",
       "autocorrect": true
     },
     "results": [
       {
         "position": 1,
         "title": "The Best Espresso Machines of 2026, Tested and Reviewed",
         "link": "https://www.example.com/best-espresso-machines",
         "domain": "example.com",
         "displayed_link": "https://www.example.com › best-espresso-machines",
         "snippet": "We pulled more than 1,200 shots on 42 machines to find the best espresso makers for every budget, from beginner-friendly to prosumer.",
         "date": "Sep 12, 2026",
         "sitelinks": [
           {
             "title": "Best budget pick",
             "link": "https://www.example.com/best-espresso-machines#budget"
           },
           {
             "title": "Best dual boiler",
             "link": "https://www.example.com/best-espresso-machines#dual-boiler"
           }
         ]
       },
       {
         "position": 2,
         "title": "Espresso Machine Buying Guide (2026)",
         "link": "https://coffee.example.org/guides/espresso",
         "domain": "coffee.example.org",
         "displayed_link": "https://coffee.example.org › guides › espresso",
         "snippet": "Single boiler, heat exchanger or dual boiler? What the specs mean and which features are worth paying for."
       },
       {
         "position": 3,
         "title": "r/espresso: What machine would you buy in 2026?",
         "link": "https://www.reddit.com/r/espresso/comments/abc123/",
         "domain": "reddit.com",
         "displayed_link": "https://www.reddit.com › r › espresso",
         "snippet": "Discussion thread with 480 comments comparing entry-level and prosumer machines."
       }
     ],
     "people_also_ask": [
       {
         "question": "What is the #1 rated espresso machine?",
         "snippet": "Reviewers most often rank dual-boiler machines with PID control at the top…",
         "link": "https://www.example.com/best-espresso-machines"
       },
       {
         "question": "Is a $500 espresso machine worth it?",
         "snippet": "For daily drinkers, a mid-range machine usually pays for itself within a year…",
         "link": "https://coffee.example.org/guides/espresso"
       }
     ],
     "related_searches": [
       {
         "query": "best espresso machine under $500"
       },
       {
         "query": "best espresso machine for beginners"
       },
       {
         "query": "dual boiler vs heat exchanger"
       }
     ],
     "meta": {
       "request_id": "req_01J8ZK4M6Q2V7",
       "credits_used": 1,
       "cached": false,
       "engine": "google",
       "latency_ms": 942,
       "parse_quality": "ok",
       "resolved_urls": true
     }
   }
   ```

## Check what it cost

Every billed response carries headers with the cost and your remaining balance, so you never need a separate call to track spend. `meta.credits_used` repeats the cost in the body:

Response headers:

```http
HTTP/2 200
content-type: application/json
x-request-id: req_01J8ZK4M6Q2V7
x-credits-used: 1
x-credits-remaining: 61499
x-cost-usd: 0.0008
x-cache: MISS
x-latency-ms: 942
x-tokens-estimate: 1184
```

A regular search costs 1 credit per page of 10 results. Failed, empty and blocked requests are refunded automatically and show `X-Credits-Used: 0`. See [Credits and billing](https://serpkite.com/docs/credits-and-billing) and [Response headers](https://serpkite.com/docs/response-headers).

You can also ask for the balance directly. `GET /v1/account` is free:

cURL:

```bash
curl "https://api.serpkite.com/v1/account" \
  -H "Authorization: Bearer $SERPKITE_API_KEY"
```

TypeScript:

```ts
import { SerpKite } from "serpkite";

const sk = new SerpKite();
const account = await sk.account();
console.log(account.balance, account.month.credits);
```

Python:

```python
from serpkite import SerpKite

sk = SerpKite()
account = sk.account()
print(account.balance, account.month.credits)
```

Go:

```go
c := serpkite.NewClient()
account, err := c.Account(ctx)
if err != nil {
	log.Fatal(err)
}
fmt.Println(account.Balance, account.Month.Credits)
```

## Get fewer tokens for an LLM

If the results go into a model's context, ask for Markdown. The same query drops from a large JSON document to a few hundred tokens of prose, with links kept. The SDKs return a plain string for `format: "markdown"`:

cURL:

```bash
curl https://api.serpkite.com/v1/search \
  -H "Authorization: Bearer $SERPKITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"best espresso machine 2026","country":"us","format":"markdown"}'
```

TypeScript:

```ts
import { SerpKite } from "serpkite";

const sk = new SerpKite(); // reads SERPKITE_API_KEY
const res = await sk.search({ q: "best espresso machine 2026", country: "us", format: "markdown" });
console.log(res);
```

Python:

```python
from serpkite import SerpKite

sk = SerpKite()  # reads SERPKITE_API_KEY
res = sk.search("best espresso machine 2026", country="us", format="markdown")
print(res)
```

Go:

```go
package main

import (
	"context"
	"fmt"
	"log"

	serpkite "github.com/serpkite/serpkite-go"
)

func main() {
	ctx := context.Background()
	c := serpkite.NewClient() // reads SERPKITE_API_KEY
	res, err := c.SearchMarkdown(ctx, serpkite.SearchParams{Q: "best espresso machine 2026", Country: "us"})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res)
}
```

format=markdown:

```markdown
# best espresso machine 2026

## Results
1. **The Best Espresso Machines of 2026, Tested and Reviewed** — example.com
   https://www.example.com/best-espresso-machines
   We pulled more than 1,200 shots on 42 machines to find the best espresso makers for every budget.
2. **Espresso Machine Buying Guide (2026)** — coffee.example.org
   https://coffee.example.org/guides/espresso
   Single boiler, heat exchanger or dual boiler? What the specs mean.
3. **r/espresso: What machine would you buy in 2026?** — reddit.com
   https://www.reddit.com/r/espresso/comments/abc123/

## People also ask
- **What is the #1 rated espresso machine?** Reviewers most often rank dual-boiler machines with PID control at the top…
- **Is a $500 espresso machine worth it?** For daily drinkers, a mid-range machine usually pays for itself within a year…

## Related searches
best espresso machine under $500 · best espresso machine for beginners · dual boiler vs heat exchanger
```

`format: "compact"` returns lean JSON instead, and `fields` projects only the parts you need (for example `results.title,results.link,knowledge_graph`). The `X-Tokens-Estimate` header tells you how big the body is. See [Output formats](https://serpkite.com/docs/output-formats).

## Handle errors

Errors always have the same shape and are never billed:

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Your balance is 0 credits. Buy a pack at https://app.serpkite.com/billing.",
    "request_id": "req_01J8ZK7T2RX4B"
  }
}
```

The SDKs raise it as a typed error (`SerpKiteError` in TypeScript and Python, `*serpkite.Error` in Go) with `status`, `code`, `message` and the request ID, and retry `429` and `5xx` for you.

Retry `429` and `503` with backoff (honour `Retry-After`). Fix the request for `400`, the key for `401`, and your balance or limits for `402` and `403`. The full list is in [Errors](https://serpkite.com/docs/errors).

Parameters are validated strictly: an unknown or misspelled parameter returns `400 invalid_request` and names the right one, instead of being ignored.

400 Bad Request:

```json
{
  "error": {
    "code": "invalid_request",
    "message": "unknown parameter \"gl\": use country",
    "request_id": "req_01J8ZK9W3HC2D"
  }
}
```

See [Strict validation](https://serpkite.com/docs/parameters#strict-validation).

## Next steps

- [Common parameters](https://serpkite.com/docs/parameters): Country, language, location, device, time range and more.
- [Search reference](https://serpkite.com/docs/endpoints/search): Every request parameter and response field of /v1/search.
- [Official SDKs](https://serpkite.com/docs/sdks): TypeScript, Python and Go clients, LangChain and CrewAI tools.
- [Use it from Claude or Cursor](https://serpkite.com/docs/mcp): Add the remote MCP server with one config snippet.
- [Give an agent web search](https://serpkite.com/docs/guides/agents-tool-calling): Tool definitions for OpenAI and Anthropic function calling.