> 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, required headers, parameters, response structures, and practical examples in multiple programming languages.

## Base URL

All Pullbay API requests use a versioned, stable base URL:

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

The `/v1` path ensures your integrations remain stable as we release new API versions in the future.

## Request Format

The standard request format follows this pattern:

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

**Example:**

```
GET /v1/app-store/reviews/all?app_id=284882215&country=us&max_results=100
```

All requests require an `Authorization` header with your API key.

## HTTP Methods

Pullbay supports two primary HTTP methods:

| Method   | Purpose                                       | Common Use Cases                                                                  |
| -------- | --------------------------------------------- | --------------------------------------------------------------------------------- |
| **GET**  | Fetch data from the API                       | Most endpoints, fetching reviews, reviews lists, app statistics                   |
| **POST** | Send complex payloads or large request bodies | Complex filtering queries, large parameter sets (when query string gets too long) |

### When to Use GET vs. POST

* Use **GET** for most simple requests (default for list endpoints)
* Use **POST** when:
  * Your request contains many parameters or complex filters
  * You're sending a large payload that exceeds URL length limits (\~2000 characters)
  * The endpoint explicitly supports POST

## Required Headers

Include these headers with every API request:

| Header          | Required      | Value                          | Example                              |
| --------------- | ------------- | ------------------------------ | ------------------------------------ |
| `Authorization` | Yes           | Bearer token with your API key | `Authorization: Bearer YOUR_API_KEY` |
| `Content-Type`  | For POST only | JSON content type              | `Content-Type: application/json`     |
| `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.

**API Key Formats:**

* Test environment: `test_xxxxxxxxxxxxxxxxxx`
* Live environment: `live_xxxxxxxxxxxxxxxxxx`

## Common Parameters

Most Pullbay API endpoints support these standard parameters:

| Parameter     | Type    | Default      | Description                                                                                        |
| ------------- | ------- | ------------ | -------------------------------------------------------------------------------------------------- |
| `app_id`      | String  | Required     | The app identifier to fetch data for.                                                              |
| `country`     | String  | `us`         | Two-letter country code (e.g., `us`, `gb`, `jp`).                                                  |
| `sort`        | String  | `recent`     | Sort order: `recent` (newest first), `helpful` (most helpful), or `critical` (lowest rated).       |
| `limit`       | Integer | 25 (max 100) | For paginated endpoints (`/reviews`): number of results per page.                                  |
| `cursor`      | String  | null         | For paginated endpoints (`/reviews`): cursor from `pagination.next_cursor` to fetch the next page. |
| `max_results` | Integer | all          | For managed endpoints (`/reviews/all`): limit the total results returned.                          |

**Example with common parameters:**

```
GET /v1/app-store/reviews?app_id=284882215&country=us&sort=recent&limit=50
GET /v1/app-store/reviews/all?app_id=284882215&country=us&max_results=500
```

## Request Examples

### Basic GET Request

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

### GET Request with Pagination

```bash
# Paginated endpoint: use limit and cursor
curl -X GET "https://api.pullbay.com/v1/app-store/reviews?app_id=284882215&limit=100&cursor=eyJvZmZzZXQiOiAxMDB9" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### GET All Reviews (Managed Pagination)

```bash
# Managed endpoint: use max_results to limit total results returned
curl -X GET "https://api.pullbay.com/v1/app-store/reviews/all?app_id=284882215&country=us&max_results=500" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### POST Request with Complex Payload

```bash
curl -X POST "https://api.pullbay.com/v1/app-store/reviews" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "com.example.app",
    "filters": {
      "rating": {"min": 4, "max": 5},
      "date_range": {"from": "2024-01-01", "to": "2024-12-31"}
    },
    "limit": 100
  }'
```

## Response Structure

All successful API responses follow this consistent JSON structure:

```json
{
  "data": [
    {
      "id": "review_abc123",
      "author": "John D.",
      "rating": 5,
      "title": "Great app!",
      "content": "This app has completely changed my workflow.",
      "date": "2024-04-13T10:30:00Z",
      "version": "1.2.3",
      "helpful_count": 42
    }
  ],
  "pagination": {
    "next_cursor": "eyJvZmZzZXQiOiAxMDB9",
    "has_more": true
  },
  "meta": {
    "credits_used": 1,
    "request_id": "req_abc123xyz789"
  }
}
```

### Response Fields Explained

**`data` (Array)**

* Contains the actual results from your API request
* Each object structure depends on the endpoint (reviews, ratings, statistics, etc.)
* Empty array `[]` means no matching results (not an error)

**`pagination` (Object)**

* `next_cursor` (String): Pagination cursor to fetch the next page. `null` when no more pages exist.
* `has_more` (Boolean): `true` if more results are available, `false` if you've reached the end.

**`meta` (Object)**

* `credits_used` (Integer): Number of API credits consumed by this request.
* `request_id` (String): Unique identifier for this request. Save this for debugging and support requests.

## Error Response Format

When an API request fails, the response includes an error object with debugging information:

```json
{
  "error": {
    "code": "invalid_parameter",
    "message": "The 'app_id' parameter is required",
    "request_id": "req_abc123xyz789"
  }
}
```

### Error Response Fields

* **`code`** (String): Machine-readable error code for programmatic handling
* **`message`** (String): Human-readable error description
* **`request_id`** (String): Unique request identifier (save this for support requests)

**Always include the `request_id` when contacting Pullbay support for faster debugging.**

## Response Headers

Pullbay includes helpful headers with every response:

| Header                  | Description                                                | Example            |
| ----------------------- | ---------------------------------------------------------- | ------------------ |
| `X-Request-Id`          | Unique identifier for this request (matches response body) | `req_abc123xyz789` |
| `X-RateLimit-Limit`     | Your plan's request limit per minute                       | `100`              |
| `X-RateLimit-Remaining` | Requests remaining in the current minute                   | `87`               |
| `X-RateLimit-Reset`     | Unix timestamp when the rate limit window resets           | `1712973600`       |
| `X-Credits-Remaining`   | API credits remaining in your account                      | `15432`            |

**Use these headers to:**

* Monitor your rate limit status in real-time
* Know when to back off requests to avoid hitting limits
* Track credit consumption
* Correlate logs with server-side request tracking

## Complete Request/Response Example

### Request

```bash
curl -X GET "https://api.pullbay.com/v1/app-store/reviews/all?app_id=284882215&country=us&max_results=2" \
  -H "Authorization: Bearer test_abc123xyz789" \
  -H "User-Agent: MyApp/1.0"
```

### Response (200 OK)

```json
{
  "data": [
    {
      "id": "review_001",
      "author": "Sarah M.",
      "rating": 5,
      "title": "Perfect productivity tool",
      "content": "This app streamlines my entire workflow. Highly recommended!",
      "date": "2024-04-12T15:22:00Z",
      "version": "2.1.0",
      "helpful_count": 89
    },
    {
      "id": "review_002",
      "author": "Mike K.",
      "rating": 4,
      "title": "Good but needs one feature",
      "content": "Overall excellent. Would love to see offline support.",
      "date": "2024-04-11T09:45:00Z",
      "version": "2.0.5",
      "helpful_count": 12
    }
  ],
  "pagination": {
    "next_cursor": "eyJvZmZzZXQiOiAyfQ==",
    "has_more": true
  },
  "meta": {
    "credits_used": 1,
    "request_id": "req_84b9c7f2e1d5"
  }
}
```

### Response Headers

```
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_84b9c7f2e1d5
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1712974200
X-Credits-Remaining: 9999
```

## Language-Specific Examples

### Python

```python
import requests
import json

API_KEY = "test_abc123xyz789"
BASE_URL = "https://api.pullbay.com/v1"

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

response = requests.get(
    f"{BASE_URL}/reviews/all",
    params={
        "app_id": "com.example.app",
        "country": "us",
        "limit": 100
    },
    headers=headers
)

if response.status_code == 200:
    data = response.json()
    reviews = data["data"]
    next_cursor = data["pagination"]["next_cursor"]
    request_id = data["meta"]["request_id"]
    print(f"Fetched {len(reviews)} reviews (Request ID: {request_id})")
else:
    error = response.json()["error"]
    print(f"Error: {error['code']} - {error['message']}")
    print(f"Request ID: {error['request_id']}")
```

### Node.js

```javascript
const fetch = require('node-fetch');

const API_KEY = "test_abc123xyz789";
const BASE_URL = "https://api.pullbay.com/v1";

async function fetchReviews() {
  const params = new URLSearchParams({
    app_id: "com.example.app",
    country: "us",
    limit: 100
  });

  const response = await fetch(`${BASE_URL}/reviews/all?${params}`, {
    method: "GET",
    headers: {
      "Authorization": `Bearer ${API_KEY}`,
      "User-Agent": "MyApp/1.0"
    }
  });

  if (response.ok) {
    const data = await response.json();
    console.log(`Fetched ${data.data.length} reviews (Request ID: ${data.meta.request_id})`);
    console.log(`Next cursor: ${data.pagination.next_cursor}`);
  } else {
    const error = await response.json();
    console.error(`Error: ${error.error.code} - ${error.error.message}`);
    console.error(`Request ID: ${error.error.request_id}`);
  }
}

fetchReviews();
```

### PHP

```php
<?php

$apiKey = "test_abc123xyz789";
$baseUrl = "https://api.pullbay.com/v1";

$ch = curl_init();

$params = http_build_query([
    "app_id" => "com.example.app",
    "country" => "us",
    "limit" => 100
]);

curl_setopt_array($ch, [
    CURLOPT_URL => "{$baseUrl}/reviews/all?{$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);

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

### Ruby

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

API_KEY = "test_abc123xyz789"
BASE_URL = "https://api.pullbay.com/v1"

params = {
  app_id: "com.example.app",
  country: "us",
  limit: 100
}

uri = URI("#{BASE_URL}/reviews/all")
uri.query = URI.encode_www_form(params)

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)

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

## Frequently Asked Questions

<details>

<summary>Does Pullbay support POST requests?</summary>

Yes. Use POST when:

* Your request has many parameters or complex filters
* You're exceeding GET query string limits (around 2,000 characters)
* The endpoint explicitly supports POST

POST requests require the `Content-Type: application/json` header and should send parameters in the request body instead of the query string.

</details>

<details>

<summary>What Content-Type should I use?</summary>

For POST requests, always use:

```
Content-Type: application/json
```

For GET requests, the `Content-Type` header is not required (and typically omitted).

</details>

<details>

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

**In GET requests, use query strings:**

```
GET /v1/app-store/reviews?app_id=284882215&country=us&sort=recent&limit=100
GET /v1/app-store/reviews/all?app_id=284882215&country=us&max_results=500
```

**In POST requests, use JSON in the request body:**

```json
{
  "app_id": "284882215",
  "country": "us",
  "sort": "recent",
  "max_results": 500
}
```

</details>

<details>

<summary>What's the difference between limit and pagination?</summary>

* **`limit`** controls how many results are returned per request (max 500)
* **Pagination** lets you fetch additional pages using the `next_cursor` from the previous response
* Small `limit` values (10-50) reduce latency; larger values (200-500) reduce pagination calls

</details>

<details>

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

Check the `pagination.has_more` field:

* `true`: More results exist; use `pagination.next_cursor` to fetch them
* `false`: You've reached the end of all results

</details>

<details>

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

While optional, it's recommended for better API diagnostics and debugging. Identify your application:

```
User-Agent: MyApp/1.0
```

</details>

<details>

<summary>What should I do with the request_id?</summary>

Save the `request_id` from responses, especially errors. If you encounter issues, include the request ID when contacting Pullbay support—it helps us quickly locate and debug your request in our logs.

</details>

<details>

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

Yes. Caching is recommended to reduce API calls and credit consumption. Consider:

* Caching review data for 1-24 hours depending on your use case
* Caching app metadata longer than dynamic reviews
* Using ETags or timestamps to validate cache freshness

</details>

<details>

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

URL-encode query parameters using your language's standard library:

* **Python:** `urllib.parse.urlencode()`
* **JavaScript:** `URLSearchParams` or `encodeURIComponent()`
* **PHP:** `http_build_query()` or `urlencode()`
* **Ruby:** `URI.encode_www_form()`

</details>

<details>

<summary>How fast is the Pullbay API?</summary>

Most requests complete in 100-500ms. Response times depend on:

* Result set size (larger results take longer)
* Your network connection
* Current server load

Use the `X-Request-Id` header and application logs to monitor response times.

</details>


---

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