> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bundleup.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Making Requests

The BundleUp proxy lets you send requests to third-party APIs through a globally distributed **edge worker**. You send a request once, and the proxy forwards it to the upstream API with the correct credentials and execution guarantees.

The proxy is intentionally transparent. It behaves like a direct network hop, not an SDK.

## **How the proxy executes requests**

When you send a request to the proxy, it is executed at the edge in a globally distributed environment, minimizing latency and avoiding centralized routing. This reduces latency and avoids routing traffic through a centralized region. The proxy scales automatically and does not introduce cold starts.

The proxy forwards your request to the upstream API using the credentials associated with the specified connection. All rate limiting, retries, and authorization checks are applied before the request is sent.

## **Endpoint format and routing**

All proxy requests are sent to `https://proxy.bundleup.io` using the same path and query params you would send to the upstream API. The upstream base URL comes from the connection’s integration, so `/user/repos` is automatically routed to `https://api.github.com/user/repos` for a GitHub connection or to `https://slack.com/api/user/repos` for a Slack connection.

## **Request requirements**

Every proxy request must include an API key and a connection ID.

The API key is provided as a Bearer token in the `Authorization` header. The connection ID is provided in the `BU-Connection-Id` header. These headers are required for all requests.

All other headers, query parameters, and request bodies are passed through as-is. If you include your own Authorization header, the proxy will overwrite it with the credentials stored for the connection.

## **Response handling**

The proxy does not read, parse, or transform the response body. The upstream response is streamed directly back to your application.

Because the response is never inspected, the proxy does not alter payloads, normalize fields, or mask errors. What the upstream API returns is exactly what you receive.

This design keeps the proxy fast, predictable, and memory-efficient.

## **Proxy errors**

The proxy returns informative errors before the request ever reaches the upstream API:

* **401 Unauthorized** when the API key is missing or invalid.
* **400 Bad Request** with the `connection_invalid` error code when the connection ID is missing or invalid.
* **429 Too Many Requests** when the per-connection rate limit is exceeded. A `Retry-After: 60` header indicates when you can try again.

Upstream errors are passed through unchanged so you can handle them exactly as you would when calling the API directly.

## **What the proxy guarantees**

The proxy guarantees that requests are executed securely, consistently, and with minimal overhead. It handles authentication, rate limiting, retries, and credential management, but otherwise stays out of the way.

If you can make an HTTP request, you can use the proxy.

<RequestExample>
  ```shellscript cURL theme={null}
  curl https://proxy.bundleup.io/user/repos \
    -H "Authorization: Bearer sk_live_123" \
    -H "BU-Connection-Id: conn_abc123"
  ```

  ```typescript JavaScript theme={null}
  const client = new BundleUp('sk_live_123');
  const proxy = client.proxy('conn_abc123');
  const response = await proxy.get('/user/repos');
  ```

  ```python Python theme={null}
  client = BundleUp('sk_live_123')
  proxy = client.proxy('conn_abc123')
  response = proxy.get('/user/repos')
  ```

  ```ruby Ruby theme={null}
  client = BundleUp::Client.new('sk_live_123')
  proxy = client.proxy('conn_abc123')
  response = proxy.get('/user/repos')
  ```
</RequestExample>
