> 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/api-and-references/making-requests.md).

# Making Requests

Learn how to construct and send HTTP requests to the Pullbay API. This guide covers request formatting, headers, parameters, response structure, and practical examples in multiple languages.

## Base URL

All Pullbay API requests use this base URL:

```
https://api.pullbay.com
```

Append the service path and endpoint to this base URL.

## Request Format

```
GET /{service}/{endpoint}?{parameters}
```

Example:

```
GET /appstore/reviews?appId=389801252&country=us&page=1
```

All current Pullbay endpoints are **GET** requests. Parameters are passed in the query string.

## Required Headers

| Header          | Required | Value                          | Example                              |
| --------------- | -------- | ------------------------------ | ------------------------------------ |
| `Authorization` | Yes      | Bearer token with your API key | `Authorization: Bearer YOUR_API_KEY` |
| `User-Agent`    | Optional | Your application identifier    | `User-Agent: MyApp/1.0`              |

### Authorization header format

```
Authorization: Bearer YOUR_API_KEY
```

Replace `YOUR_API_KEY` with your actual API key from the Pullbay dashboard. Your API key is secret — never share it or commit it to version control.

## Common Parameters

Parameters vary by endpoint; each endpoint's reference page lists its own. The App Store reviews endpoint, for example, accepts:

| Parameter  | Type    | Required                  | Description                                                 |
| ---------- | ------- | ------------------------- | ----------------------------------------------------------- |
| `appId`    | string  | One of `appId`/`bundleId` | App Store app ID (numeric). Pattern `^\d{8,12}$`.           |
| `bundleId` | string  | One of `appId`/`bundleId` | App bundle ID (e.g. `com.burbn.instagram`).                 |
| `country`  | string  | No                        | Two-letter storefront code (e.g. `us`, `gb`, `jp`).         |
| `sort`     | string  | No                        | Sort order: `recent` or `helpful`.                          |
| `page`     | integer | No                        | Page number (1–10). Mutually exclusive with `maxItems`.     |
| `maxItems` | integer | No                        | One-shot bulk pull (1–500). Mutually exclusive with `page`. |

Use `page` to fetch one page at a time, or `maxItems` for a single bulk call — not both.

Example:

```
GET /appstore/reviews?appId=389801252&country=us&sort=recent&page=1
GET /appstore/reviews?appId=389801252&country=us&maxItems=500
```

## Request Examples

### Basic GET request

```bash
curl -X GET "https://api.pullbay.com/appstore/reviews?appId=389801252&country=us" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Paginated request (`page`)

```bash
curl -X GET "https://api.pullbay.com/appstore/reviews?appId=389801252&page=2" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Bulk pull (`maxItems`)

```bash
curl -X GET "https://api.pullbay.com/appstore/reviews?appId=389801252&country=us&maxItems=500" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Response Structure

All successful responses follow this consistent JSON structure:

```json
{
  "requestId": "3b8dcb68-1f8c-4a7b-b9e7-63a7b9986f24",
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "id": "13997548250",
      "date": "2026-04-25T19:57:33-07:00",
      "userName": "Catie0012",
      "userUrl": "https://itunes.apple.com/us/reviews/id1632846422",
      "version": "426.0.0",
      "score": 5,
      "title": "How I love your app",
      "text": "An unmatched experience.",
      "url": "https://itunes.apple.com/us/review?id=389801252",
      "country": "US"
    }
  ],
  "pagination": {
    "page": 1,
    "hasNextPage": null,
    "cursor": null,
    "offset": null
  },
  "pricing": {
    "creditsCharged": 2
  }
}
```

### Response fields explained

**Top level**

* `requestId` (string): Unique identifier for this request. Save it for debugging and support.
* `status` (integer): HTTP status code.
* `message` (string): Human-readable status message.
* `success` (boolean): Whether the request succeeded.

**`data` (array)**

* Contains the actual results. Each object's structure depends on the endpoint.
* An empty array `[]` means no matching results (not an error).

**`pagination` (object)** — present on list/search endpoints

* `page` (integer): Current page number.
* `hasNextPage` (boolean): Whether more pages are available.
* `cursor` / `offset` (string): Used only by cursor- or offset-paginated services (e.g. Google Maps); `null` for App Store.

**`pricing` (object)**

* `creditsCharged` (number): Credits consumed by this request.

## Error Response Format

When a request fails, the response keeps the same top-level envelope and adds an `error` object:

```json
{
  "requestId": "3b8dcb68-1f8c-4a7b-b9e7-63a7b9986f24",
  "status": 400,
  "message": "Bad request",
  "success": false,
  "error": {
    "code": "BAD_REQUEST"
  }
}
```

* `success` is `false` on failure.
* `status` / `message` describe the failure (e.g. `402 Insufficient credits`, `404 Not found`).
* `error.code` is a machine-readable code for programmatic handling.
* Include `requestId` when contacting Pullbay support for faster debugging.

## Complete Request/Response Example

**Request**

```bash
curl -X GET "https://api.pullbay.com/appstore/reviews?appId=389801252&country=us&maxItems=2" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "User-Agent: MyApp/1.0"
```

**Response (200 OK)**

```json
{
  "requestId": "3b8dcb68-1f8c-4a7b-b9e7-63a7b9986f24",
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "id": "13997548250",
      "date": "2026-04-25T19:57:33-07:00",
      "userName": "Catie0012",
      "version": "426.0.0",
      "score": 5,
      "title": "Perfect productivity tool",
      "text": "This app streamlines my entire workflow. Highly recommended!",
      "country": "US"
    },
    {
      "id": "13997548251",
      "date": "2026-04-24T09:45:00-07:00",
      "userName": "MikeK",
      "version": "426.0.0",
      "score": 4,
      "title": "Good but needs one feature",
      "text": "Overall excellent. Would love to see offline support.",
      "country": "US"
    }
  ],
  "pagination": { "page": 1, "hasNextPage": null, "cursor": null, "offset": null },
  "pricing": { "creditsCharged": 3 }
}
```

## Language-Specific Examples

### Python

```python
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.pullbay.com"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "User-Agent": "MyApp/1.0",
}

response = requests.get(
    f"{BASE_URL}/appstore/reviews",
    params={"appId": "389801252", "country": "us", "page": 1},
    headers=headers,
)

if response.ok:
    data = response.json()
    reviews = data["data"]
    print(f"Fetched {len(reviews)} reviews (Request ID: {data['requestId']})")
    print(f"Has next page: {data['pagination']['hasNextPage']}")
    print(f"Credits charged: {data['pricing']['creditsCharged']}")
else:
    body = response.json()
    print(f"Error {body['error']['code']}: {body['message']} (Request ID: {body['requestId']})")
```

### Node.js

```javascript
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.pullbay.com";

async function fetchReviews() {
  const params = new URLSearchParams({ appId: "389801252", country: "us", page: "1" });
  const response = await fetch(`${BASE_URL}/appstore/reviews?${params}`, {
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "User-Agent": "MyApp/1.0",
    },
  });

  const body = await response.json();
  if (response.ok) {
    console.log(`Fetched ${body.data.length} reviews (Request ID: ${body.requestId})`);
    console.log(`Has next page: ${body.pagination.hasNextPage}`);
  } else {
    console.error(`Error ${body.error.code}: ${body.message} (Request ID: ${body.requestId})`);
  }
}

fetchReviews();
```

### PHP

```php
<?php
$apiKey = "YOUR_API_KEY";
$baseUrl = "https://api.pullbay.com";

$params = http_build_query(["appId" => "389801252", "country" => "us", "page" => 1]);

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => "{$baseUrl}/appstore/reviews?{$params}",
    CURLOPT_HTTPHEADER => ["Authorization: Bearer {$apiKey}", "User-Agent: MyApp/1.0"],
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$body = json_decode($response, true);
if ($httpCode === 200) {
    echo "Fetched " . count($body["data"]) . " reviews\n";
    echo "Request ID: " . $body["requestId"] . "\n";
} else {
    echo "Error " . $body["error"]["code"] . ": " . $body["message"] . "\n";
}
?>
```

### Ruby

```ruby
require 'net/http'
require 'json'
require 'uri'

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.pullbay.com"

uri = URI("#{BASE_URL}/appstore/reviews")
uri.query = URI.encode_www_form(appId: "389801252", country: "us", page: 1)

request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{API_KEY}"
request["User-Agent"] = "MyApp/1.0"

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
response = http.request(request)

body = JSON.parse(response.body)
if response.code == "200"
  puts "Fetched #{body['data'].length} reviews"
  puts "Request ID: #{body['requestId']}"
else
  puts "Error #{body['error']['code']}: #{body['message']}"
end
```

## Frequently Asked Questions

<details>

<summary>What's the difference between `page` and `maxItems`?</summary>

They're mutually exclusive modes on list/search endpoints. Use `page` to fetch one page at a time (max 10 pages for App Store reviews) with fine control over credits. Use `maxItems` (max 500 for App Store reviews) to pull a full set in a single call — simpler for batch jobs. Don't send both.

</details>

<details>

<summary>How do I know if there are more results?</summary>

Check `pagination.hasNextPage`. When it's `true`, request the next page by incrementing `page`.

</details>

<details>

<summary>How do I pass multiple parameters?</summary>

Use the query string: `GET /appstore/reviews?appId=389801252&country=us&sort=recent&page=1`.

</details>

<details>

<summary>Should I include the User-Agent header?</summary>

It's optional but recommended for better diagnostics. Identify your application, e.g. `User-Agent: MyApp/1.0`.

</details>

<details>

<summary>What should I do with the `requestId`?</summary>

Save it from responses, especially errors. Include it when contacting Pullbay support so they can locate your request in the logs.

</details>

<details>

<summary>Can I cache API responses?</summary>

Yes — caching reduces calls and credit consumption. Cache app metadata longer than dynamic data like reviews, and validate freshness with timestamps.

</details>

<details>

<summary>What encoding should I use for special characters in parameters?</summary>

URL-encode query parameters with your language's standard library: Python `urllib.parse.urlencode()`, JavaScript `URLSearchParams`, PHP `http_build_query()`, Ruby `URI.encode_www_form()`.

</details>
