> For the complete documentation index, see [llms.txt](https://docs.pullbay.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pullbay.com/documentation/getting-started/first-api-call.md).

# First API Call

Learn how to make your first API call to Pullbay and understand the response structure. This hands-on guide shows you real code examples and explains every step.

## Prerequisites

Before making your first API call, ensure you have:

* A Pullbay account (sign up at [https://dashboard.pullbay.com](https://dashboard.pullbay.com/))
* Your API key copied from the **API Keys** section of your dashboard
* A tool for making HTTP requests (cURL, Postman, programming language, etc.)
* Basic familiarity with JSON responses

## The Example Request

We'll fetch app store reviews for Facebook (App Store ID: 284882215) to demonstrate a real API call.

**Endpoint:** `GET https://api.pullbay.com/v1/app-store/reviews`

**Parameters:**

* `app_id` = `284882215` (Facebook's iOS App Store ID)

**Authentication:**

* Header: `Authorization: Bearer YOUR_API_KEY`

### cURL

```bash
curl -X GET "https://api.pullbay.com/v1/app-store/reviews?app_id=284882215" \
  -H "Authorization: Bearer test_abc123xyz789"
```

Replace `test_abc123xyz789` with your actual test API key.

### Python (requests library)

```python
import requests

# Your API key
api_key = "test_abc123xyz789"

# API endpoint and parameters
url = "https://api.pullbay.com/v1/app-store/reviews"
params = {
    "app_id": "284882215"
}

# Set up authentication header
headers = {
    "Authorization": f"Bearer {api_key}"
}

# Make the request
response = requests.get(url, params=params, headers=headers)

# Parse and print the response
data = response.json()
print(data)
```

### Node.js (Axios)

```javascript
const axios = require('axios');

// Your API key
const apiKey = 'test_abc123xyz789';

// API endpoint and parameters
const url = 'https://api.pullbay.com/v1/app-store/reviews';
const params = {
  app_id: '284882215'
};

// Set up authentication header
const headers = {
  'Authorization': `Bearer ${apiKey}`
};

// Make the request
async function getReviews() {
  try {
    const response = await axios.get(url, {
      params: params,
      headers: headers
    });
    console.log(response.data);
  } catch (error) {
    console.error('Error:', error.response.data);
  }
}

getReviews();
```

### Node.js (Native Fetch)

```javascript
const apiKey = 'test_abc123xyz789';
const url = 'https://api.pullbay.com/v1/app-store/reviews?app_id=284882215';

const response = await fetch(url, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${apiKey}`
  }
});

const data = await response.json();
console.log(data);
```

### PHP

```php
<?php
$apiKey = 'test_abc123xyz789';
$appId = '284882215';

// Build URL with parameters
$url = 'https://api.pullbay.com/v1/app-store/reviews?app_id=' . $appId;

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $apiKey,
    'Content-Type: application/json'
]);

// Execute request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Parse response
if ($httpCode === 200) {
    $data = json_decode($response, true);
    print_r($data);
} else {
    echo "Error: HTTP $httpCode\n";
    echo "Response: $response\n";
}
?>
```

## Understanding the Response

Here's what a successful response from this API call looks like:

```json
{
  "data": [
    {
      "id": "10293847561",
      "author": "HappyUser123",
      "rating": 5,
      "title": "Great app!",
      "content": "This app has changed how I work. The interface is intuitive and features are powerful. Highly recommended!",
      "date": "2024-01-15T10:30:00Z",
      "version": "5.2.1",
      "helpful_count": 42
    },
    {
      "id": "10293847562",
      "author": "CriticalReviewer",
      "rating": 3,
      "title": "Good but needs work",
      "content": "The core features are solid and the performance is decent. However, the app could use better error handling and more customization options.",
      "date": "2024-01-14T15:45:00Z",
      "version": "5.2.0",
      "helpful_count": 18
    },
    {
      "id": "10293847563",
      "author": "BugHunter42",
      "rating": 2,
      "title": "Crashes on startup",
      "content": "The app keeps crashing when I try to open it on iOS 17. This happened after the last update. Please fix!",
      "date": "2024-01-13T08:15:00Z",
      "version": "5.2.0",
      "helpful_count": 156
    }
  ],
  "pagination": {
    "next_cursor": "eyJwYWdlIjoyLCJsaW1pdCI6MTAsImFwcF9pZCI6IjI4NDg4MjIxNSJ9",
    "has_more": true
  },
  "meta": {
    "credits_used": 1,
    "request_id": "req_abc123xyz789def456"
  }
}
```

### Response Field Explanations

The response contains three main sections: `data`, `pagination`, and `meta`.

#### data (Array)

The `data` array contains review objects. Each review has these fields:

| Field              | Type     | Description                                                   |
| ------------------ | -------- | ------------------------------------------------------------- |
| **id**             | String   | Unique identifier for this review across the app store        |
| **author**         | String   | Username or display name of the reviewer                      |
| **rating**         | Integer  | Star rating given by the reviewer (1-5)                       |
| **title**          | String   | Review title or headline                                      |
| **content**        | String   | Full text of the review                                       |
| **date**           | ISO 8601 | Timestamp when the review was posted (UTC)                    |
| **version**        | String   | App version the reviewer was using when they wrote the review |
| **helpful\_count** | Integer  | Number of users who marked this review as helpful             |

#### pagination (Object)

The `pagination` object helps you fetch multiple pages of results:

| Field            | Type    | Description                                                            |
| ---------------- | ------- | ---------------------------------------------------------------------- |
| **next\_cursor** | String  | Cursor token for fetching the next page of results                     |
| **has\_more**    | Boolean | `true` if more results are available; `false` if this is the last page |

#### meta (Object)

The `meta` object contains request metadata:

| Field             | Type    | Description                                                           |
| ----------------- | ------- | --------------------------------------------------------------------- |
| **credits\_used** | Integer | Number of API credits consumed by this request (usually 1)            |
| **request\_id**   | String  | Unique identifier for this request (useful for debugging and support) |

## Fetching More Pages

When `pagination.has_more` is `true`, you can fetch the next page of results using the `next_cursor` value:

### cURL

```bash
curl -X GET "https://api.pullbay.com/v1/app-store/reviews?app_id=284882215&cursor=eyJwYWdlIjoyLCJsaW1pdCI6MTAsImFwcF9pZCI6IjI4NDg4MjIxNSJ9" \
  -H "Authorization: Bearer test_abc123xyz789"
```

### Python

```python
# Fetch the first page
response1 = requests.get(url, params=params, headers=headers)
data1 = response1.json()

# Check if more results are available
if data1['pagination']['has_more']:
    # Fetch the next page using the cursor
    next_cursor = data1['pagination']['next_cursor']
    params['cursor'] = next_cursor

    response2 = requests.get(url, params=params, headers=headers)
    data2 = response2.json()

    # Combine results
    all_reviews = data1['data'] + data2['data']
    print(f"Fetched {len(all_reviews)} reviews total")
```

### Node.js

```javascript
// Fetch the first page
const response1 = await axios.get(url, {
  params: { app_id: '284882215' },
  headers: headers
});
const data1 = response1.data;

// Check if more results are available
if (data1.pagination.has_more) {
  const nextCursor = data1.pagination.next_cursor;

  // Fetch the next page
  const response2 = await axios.get(url, {
    params: { app_id: '284882215', cursor: nextCursor },
    headers: headers
  });
  const data2 = response2.data;

  // Combine results
  const allReviews = [...data1.data, ...data2.data];
  console.log(`Fetched ${allReviews.length} reviews total`);
}
```

## Check Your Usage in the Dashboard

{% stepper %}
{% step %}

### Sign in to the dashboard

Sign in to [https://dashboard.pullbay.com](https://dashboard.pullbay.com/).
{% endstep %}

{% step %}

### Open your overview

Click **Overview** to see your remaining credits.
{% endstep %}

{% step %}

### Review usage details

Click **Usage** to see detailed request history:

* Number of requests made
* Breakdown by endpoint
* Requests over time
* Credits consumed

This confirms your API call was successful and helps you understand your usage patterns.
{% endstep %}
{% endstepper %}

## Common Errors & Troubleshooting

If your request fails, check the response status code and error message:

### 401 Unauthorized

**Cause:** Your API key is missing, invalid, or expired.

**Solution:**

* Verify your key is correctly copied from the dashboard
* Check that it's in the `Authorization` header with the format `Bearer YOUR_API_KEY`
* If you suspect the key is compromised, revoke it and create a new one

**Example response:**

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key"
  }
}
```

### 400 Bad Request

**Cause:** Invalid request parameters or malformed request.

**Solution:**

* Verify all required parameters are included (e.g., `app_id`)
* Check parameter values are correct (app IDs should be numeric strings)
* Ensure the request is properly formatted

**Example response:**

```json
{
  "error": {
    "code": "bad_request",
    "message": "Missing required parameter: app_id"
  }
}
```

### 402 Payment Required

**Cause:** You've used all your available API credits.

**Solution:**

* Check your remaining credits in the **Overview** section
* Purchase additional credits or upgrade your plan
* Credits reset on the first day of each month

**Example response:**

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Insufficient credits to process this request"
  }
}
```

### 429 Too Many Requests

**Cause:** You've exceeded your rate limit for this API key.

**Solution:**

* Wait before making additional requests (rate limits reset hourly)
* Implement exponential backoff in your application
* Contact support if you need higher rate limits

**Example response:**

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded. Please try again in 60 seconds."
  }
}
```

### 500 Internal Server Error

**Cause:** A server-side error occurred.

**Solution:**

* Retry the request after a few seconds
* Check the [Service Health](https://status.pullbay.com/) page for known issues
* If the error persists, contact support with your `request_id`

**Example response:**

```json
{
  "error": {
    "code": "internal_error",
    "message": "An internal server error occurred"
  }
}
```

## Error Reference Table

Here's a quick reference for common error codes:

| Status  | Code                   | Message                    | Action                    |
| ------- | ---------------------- | -------------------------- | ------------------------- |
| **401** | `unauthorized`         | Invalid or missing API key | Check your API key        |
| **400** | `bad_request`          | Invalid parameters         | Verify request parameters |
| **402** | `insufficient_credits` | No credits remaining       | Purchase more credits     |
| **429** | `rate_limited`         | Rate limit exceeded        | Wait and retry            |
| **500** | `internal_error`       | Server error               | Retry or contact support  |
| **503** | `service_unavailable`  | API is down                | Check status page         |

## Next Steps

Congratulations on making your first Pullbay API call! Here's what to explore next:

1. [**Pagination Guide**](broken://pages/eaafdc0aa61556675299f95968ab83b8acb73972) — Master cursor-based pagination for large datasets
2. [**Authentication Guide**](broken://pages/ad35e9fae7dd67a9108f6c7928da4ab49ed12175) — Learn about test vs. live keys and security
3. [**App Store API Reference**](broken://pages/b7e8abe11a3095796b95d24da9edcd74241f4afa) — Explore all available endpoints and parameters
4. [**Error Handling**](broken://pages/7ea30d13d98330fe74bf23f0046b45549fb98077) — Implement robust error handling in your application
5. [**Rate Limiting**](broken://pages/7c327f44c70c87a9ed59fbc33d3bf27109e2e308) — Understand rate limits and implement backoff strategies

## FAQ

<details>

<summary>How do I find an app's ID?</summary>

**iOS Apps:** App IDs appear in the App Store URL:

* URL: `https://apps.apple.com/app/facebook/id284882215`
* ID: `284882215`

**Android Apps:** Package names are used instead of numeric IDs:

* Example: `com.facebook.katana` (Facebook)
* You can find this in the Google Play Store URL or by installing the app and checking app information

**Alternative:** Use the App Store web interface to search for your app and look at the URL.

</details>

<details>

<summary>What does app_id 284882215 refer to?</summary>

**284882215** is the official Apple App Store ID for Facebook. We use this as a demonstration example because:

* It's a well-known app with many reviews
* The app is widely available and familiar to developers
* Using a real, public app ID demonstrates realistic usage

You can replace this with any app ID to fetch reviews for other applications.

</details>

<details>

<summary>Can I fetch reviews for apps on different app stores?</summary>

**Currently, Pullbay supports iOS (Apple App Store) and Android (Google Play Store) reviews.** Different endpoints serve different stores:

* iOS reviews: `GET /v1/app-store/reviews` (use iOS app ID)
* Android reviews: `GET /v1/play-store/reviews` (use package name)

Check the [API Reference](broken://pages/b7e8abe11a3095796b95d24da9edcd74241f4afa) for endpoint-specific documentation.

</details>

<details>

<summary>How often are reviews updated?</summary>

**Reviews are refreshed regularly** (typically within 24 hours of being posted). The exact refresh interval depends on your plan. Check your dashboard or contact support for the refresh schedule for your account.

</details>

<details>

<summary>What if I make the same request twice?</summary>

**You'll get fresh data,** not cached results. Each request:

* Consumes 1 API credit
* May return different reviews if new ones have been posted
* Is tracked separately in your usage dashboard

There's no automatic deduplication, so be aware if you're making multiple requests for the same data.

</details>

<details>

<summary>Can I filter reviews by rating or date?</summary>

**Check the API Reference** for filtering options available on each endpoint. Some endpoints support parameters like:

* `min_rating` / `max_rating` to filter by star rating
* `since` / `until` to filter by date
* `limit` to set page size

See the [App Store API Reference](broken://pages/b7e8abe11a3095796b95d24da9edcd74241f4afa) for your endpoint's supported filters.

</details>

You're now ready to build with the Pullbay API! If you have questions, check our documentation or reach out to support.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pullbay.com/documentation/getting-started/first-api-call.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
