Shell City API

Web data extraction built for AI agents. One API key, pay-per-request pricing, no subscriptions. Scrape URLs, extract structured data, and monitor your usage with a simple REST API.

New API keys receive 100 free credits ($0.10) to get started. No credit card required.
Base URL
All Requests https://shellcity.polsia.app

Authentication

All authenticated endpoints require a Bearer token in the Authorization header. API keys start with the prefix sc_live_.

Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

You can create an API key programmatically using the Create API Key endpoint (no authentication required), or from the Dashboard.

Endpoints

POST Create API Key

/v1/keys
No authentication required

Create a new API key. Every new key receives 100 free credits ($0.10) to start. You can optionally provide a name to identify the key.

Request Body
Parameter Type Description
nameoptional string A human-readable name for the key (e.g., "My App", "Production Agent")
Examples
curl -X POST https://shellcity.polsia.app/v1/keys \
  -H "Content-Type: application/json" \
  -d '{"name": "My App"}'
const response = await fetch('https://shellcity.polsia.app/v1/keys', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'My App' })
});

const data = await response.json();
console.log(data.api_key.key); // sc_live_xxxxxxxx...
Response
201 Created
{
  "success": true,
  "api_key": {
    "key": "sc_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "id": "key_8f3a9b2c",
    "prefix": "sc_live_a1b2",
    "name": "My App",
    "balance_credits": 100
  },
  "message": "API key created. You have 100 free credits ($0.10)."
}
🔒
The full API key is only returned once at creation time. Store it securely. You will not be able to retrieve it again.

GET Get Key Info

/v1/keys/me
Authentication required

Retrieve information about the currently authenticated API key, including credit balance, usage statistics, and account details.

Examples
curl https://shellcity.polsia.app/v1/keys/me \
  -H "Authorization: Bearer sc_live_your_key_here"
const response = await fetch('https://shellcity.polsia.app/v1/keys/me', {
  headers: {
    'Authorization': `Bearer ${SHELL_CITY_KEY}`
  }
});

const data = await response.json();
console.log(data);
Response
200 OK
{
  "success": true,
  "api_key": {
    "id": "key_8f3a9b2c",
    "prefix": "sc_live_a1b2",
    "name": "My App",
    "balance_credits": 95,
    "balance_usd": 0.095,
    "total_requests": 5,
    "created_at": "2026-03-15T10:30:00Z",
    "last_used_at": "2026-03-17T08:22:14Z",
    "status": "active"
  }
}

POST Scrape URL 1 credit ($0.001)

/v1/scrape
Authentication required

Scrape a URL and return the page content as clean markdown. Handles JavaScript rendering, anti-bot bypasses, and proxies automatically. The response includes metadata about credits used and remaining balance.

Request Body
Parameter Type Description
urlrequired string The URL to scrape. Must be a valid HTTP or HTTPS URL.
formatsoptional string[] Output formats. Supported: "markdown", "html", "text". Default: ["markdown"]
Examples
curl -X POST https://shellcity.polsia.app/v1/scrape \
  -H "Authorization: Bearer sc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "formats": ["markdown"]
  }'
const response = await fetch('https://shellcity.polsia.app/v1/scrape', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${SHELL_CITY_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com',
    formats: ['markdown']
  })
});

const data = await response.json();
console.log(data.data.markdown);
Response
200 OK
{
  "success": true,
  "data": {
    "markdown": "# Example Domain\n\nThis domain is for use in illustrative examples..."
  },
  "metadata": {
    "credits_used": 1,
    "credits_remaining": 94,
    "provider": "firecrawl",
    "response_time_ms": 1240
  }
}

POST Extract Structured Data 5 credits ($0.005)

/v1/extract
Authentication required

Extract structured data from a URL using AI. Provide a natural language prompt describing what to extract, and optionally a JSON schema for the output. The LLM reads the page content and returns clean, structured data matching your requirements.

Request Body
Parameter Type Description
urlrequired string The URL to extract data from.
promptrequired string Natural language description of what to extract (e.g., "Extract all product names and prices").
schemaoptional object A JSON schema defining the expected output structure. Helps the LLM return consistently formatted data.
Examples
curl -X POST https://shellcity.polsia.app/v1/extract \
  -H "Authorization: Bearer sc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/products",
    "prompt": "Extract all product names and prices",
    "schema": {
      "type": "object",
      "properties": {
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "price": { "type": "number" },
              "currency": { "type": "string" }
            }
          }
        }
      }
    }
  }'
const response = await fetch('https://shellcity.polsia.app/v1/extract', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${SHELL_CITY_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com/products',
    prompt: 'Extract all product names and prices',
    schema: {
      type: 'object',
      properties: {
        products: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              name: { type: 'string' },
              price: { type: 'number' },
              currency: { type: 'string' }
            }
          }
        }
      }
    }
  })
});

const data = await response.json();
console.log(data.data);
Response
200 OK
{
  "success": true,
  "data": {
    "products": [
      {
        "name": "Wireless Keyboard Pro",
        "price": 79.99,
        "currency": "USD"
      },
      {
        "name": "Ergonomic Mouse X1",
        "price": 49.99,
        "currency": "USD"
      }
    ]
  },
  "metadata": {
    "credits_used": 5,
    "credits_remaining": 89,
    "provider": "firecrawl",
    "response_time_ms": 3420
  }
}

GET Usage Statistics

/v1/usage
Authentication required

Retrieve usage statistics for your API key, including total requests, credits used, daily breakdown, and breakdown by provider.

Examples
curl https://shellcity.polsia.app/v1/usage \
  -H "Authorization: Bearer sc_live_your_key_here"
const response = await fetch('https://shellcity.polsia.app/v1/usage', {
  headers: {
    'Authorization': `Bearer ${SHELL_CITY_KEY}`
  }
});

const data = await response.json();
console.log(data);
Response
200 OK
{
  "success": true,
  "usage": {
    "total_requests": 142,
    "credits_used": 312,
    "daily": [
      {
        "date": "2026-03-17",
        "requests": 23,
        "credits": 48
      },
      {
        "date": "2026-03-16",
        "requests": 45,
        "credits": 110
      }
    ],
    "by_provider": {
      "firecrawl": { "requests": 120, "credits": 250 },
      "scrapingbee": { "requests": 22, "credits": 62 }
    }
  }
}

GET Request History

/v1/usage/history
Authentication required

Retrieve a paginated list of individual API requests made with your key. Useful for debugging, auditing, and understanding usage patterns.

Query Parameters
Parameter Type Description
limitoptional integer Number of records to return. Default: 50. Max: 200.
offsetoptional integer Number of records to skip for pagination. Default: 0.
Examples
curl "https://shellcity.polsia.app/v1/usage/history?limit=10&offset=0" \
  -H "Authorization: Bearer sc_live_your_key_here"
const params = new URLSearchParams({ limit: 10, offset: 0 });

const response = await fetch(
  `https://shellcity.polsia.app/v1/usage/history?${params}`,
  {
    headers: {
      'Authorization': `Bearer ${SHELL_CITY_KEY}`
    }
  }
);

const data = await response.json();
console.log(data.requests);
Response
200 OK
{
  "success": true,
  "requests": [
    {
      "id": "req_9f8e7d6c",
      "endpoint": "/v1/scrape",
      "method": "POST",
      "url": "https://example.com",
      "status": 200,
      "credits_used": 1,
      "provider": "firecrawl",
      "response_time_ms": 1180,
      "created_at": "2026-03-17T08:22:14Z"
    },
    {
      "id": "req_5a4b3c2d",
      "endpoint": "/v1/extract",
      "method": "POST",
      "url": "https://example.com/products",
      "status": 200,
      "credits_used": 5,
      "provider": "firecrawl",
      "response_time_ms": 3210,
      "created_at": "2026-03-17T08:15:03Z"
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "total": 142,
    "has_more": true
  }
}

GET Credits

/v1/credits
Authentication required

Retrieve your current credit balance and recent transaction history. Use this endpoint to monitor your spending and track credit purchases.

Examples
curl https://shellcity.polsia.app/v1/credits \
  -H "Authorization: Bearer sc_live_your_key_here"
const response = await fetch('https://shellcity.polsia.app/v1/credits', {
  headers: {
    'Authorization': `Bearer ${SHELL_CITY_KEY}`
  }
});

const data = await response.json();
console.log(`Balance: ${data.balance.credits} credits ($${data.balance.usd})`);
Response
200 OK
{
  "success": true,
  "balance": {
    "credits": 4850,
    "usd": 4.85
  },
  "transactions": [
    {
      "id": "txn_a1b2c3d4",
      "type": "purchase",
      "credits": 5000,
      "amount_usd": 5.00,
      "description": "Credit purchase via Stripe",
      "created_at": "2026-03-15T10:30:00Z"
    },
    {
      "id": "txn_e5f6g7h8",
      "type": "usage",
      "credits": -150,
      "amount_usd": -0.15,
      "description": "API usage (150 requests)",
      "created_at": "2026-03-16T23:59:59Z"
    },
    {
      "id": "txn_i9j0k1l2",
      "type": "bonus",
      "credits": 100,
      "amount_usd": 0.10,
      "description": "Welcome bonus - 100 free credits",
      "created_at": "2026-03-15T10:30:00Z"
    }
  ]
}

Pricing

Shell City uses a simple credit-based pricing model. Buy credits, spend them on API calls. No subscriptions, no monthly minimums, no surprise bills.

Exchange Rate 1 credit = $0.001
Scrape
$0.001
per request
1 credit
Extract
$0.005
per request
5 credits
Free Tier
100
credits on signup
$0.10 value
No subscriptions. No monthly fees. Credits never expire. Pay only for what your agent uses.

Error Codes

All error responses follow a consistent format with a success: false flag and a human-readable message field. Your integration should handle these status codes gracefully.

Status Code Description
401 Unauthorized Invalid or missing API key. Verify your Authorization header contains a valid Bearer token.
402 Insufficient Credits Your credit balance is too low for this request. Purchase additional credits to continue.
403 Forbidden API key has been revoked or lacks permission for the requested operation.
422 Provider Error The upstream scraping provider returned an error. This may be a temporary issue with the target URL or provider. Retry after a brief delay.
502 Provider Unavailable The upstream provider is temporarily unavailable. Shell City will attempt automatic failover. If the error persists, retry after 30 seconds.
Error Response Format
402 Insufficient Credits
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Insufficient credits. Required: 5, available: 2. Purchase more credits to continue.",
    "credits_required": 5,
    "credits_available": 2
  }
}

Rate Limits

Shell City applies rate limits per API key to ensure fair usage and platform stability. Rate limit information is included in response headers.

Tier Limit Window
Default 60 requests Per minute
Burst 10 requests Per second
Rate Limit Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1710662400

When rate limited, you will receive a 429 Too Many Requests response. Wait for the time indicated in the X-RateLimit-Reset header before retrying.