ProxyBridge API Docs

ProxyBridge lets you route any HTTP request through it to bypass CORS and normalize responses. These docs show you exactly how to call your backend through ProxyBridge from any frontend app.

What is ProxyBridge?

ProxyBridge is a deployed HTTP relay server. Instead of calling your backend API directly from the browser (which often causes CORS errors), you send your request to ProxyBridge and it forwards it to your real API, then returns the response back to you in a clean, consistent shape.

Your Frontend
     |  fetch("https://proxybridge.focket.app/api/relay/users")
     |
     v
ProxyBridge  -->  https://api.yourbackend.com/users
     ^                        |
     +------------------------+
          normalized response

URL Structure

Every request follows this single pattern.

Endpoint
https://proxybridge.focket.app/api/relay/<your-api-path>
  ?webUrl=<your-frontend-origin>
  &baseApiUrl=<your-backend-base-url>
  &[...any other query params forwarded to backend]
PartWhat it is
https://proxybridge.focket.appThe root URL of this ProxyBridge instance (this server)
<your-api-path>The path on your backend API, e.g. users/123 or products
webUrlYour frontend origin -- ProxyBridge uses this to set the CORS header on the response
baseApiUrlThe root URL of the backend you want to reach, e.g. https://api.example.com
...restAny extra query params are passed through transparently to your backend

Make Your First Call

Say your ProxyBridge is at https://proxybridge.focket.app, your frontend runs at https://myapp.com, and you want to hit GET https://api.example.com/users.

const PROXY = 'https://proxybridge.focket.app';
const WEB_URL = 'https://myapp.com';
const API_BASE = 'https://api.example.com';

const res = await fetch(
  `${PROXY}/api/relay/users` +
  `?webUrl=${encodeURIComponent(WEB_URL)}` +
  `&baseApiUrl=${encodeURIComponent(API_BASE)}`
);

const data = await res.json();
// data.success  -> true
// data.data     -> the actual payload from your backend
// data.meta     -> pagination info (if any)
console.log(data.data);

Query Parameters

These are the special parameters ProxyBridge reads. All others are forwarded to your backend.

ParameterRequiredDescription
webUrlRequiredYour frontend origin URL. ProxyBridge echoes this back in Access-Control-Allow-Origin so the browser allows the response.
baseApiUrlRequiredThe base URL of your actual backend. ProxyBridge appends the relay path to this and makes the upstream call.
acceptHeadersKeyOptionalComma-separated list of request header names to forward on to the upstream API. Useful for authorization or custom headers.
...anything elseOptionalAny other query params are passed through directly to your backend -- page, limit, search, etc.

Forwarding Headers

Need to send an Authorization token or a custom header to your backend? Use acceptHeadersKey.

By default, ProxyBridge automatically forwards standard browser headers (Accept, Content-Type, Origin, etc.). To also forward headers like Authorization, pass them by name in acceptHeadersKey.

const res = await fetch(
  `${PROXY}/api/relay/orders` +
  `?webUrl=${encodeURIComponent(WEB_URL)}` +
  `&baseApiUrl=${encodeURIComponent(API_BASE)}` +
  `&acceptHeadersKey=authorization`,   // tell ProxyBridge to forward this header
  {
    headers: {
      Authorization: 'Bearer eyJhbGci...',  // your token
    },
  }
);

Passing Query Params to Your Backend

Filtering, pagination, search -- just add them and they flow through.

Any query param that isn't webUrl, baseApiUrl, or acceptHeadersKey is forwarded verbatim to your backend.

// Calls: https://api.example.com/products?page=2&limit=20&search=shoes&category=sport
const params = new URLSearchParams({
  webUrl: WEB_URL,
  baseApiUrl: API_BASE,
  // these go straight to your backend:
  page: '2',
  limit: '20',
  search: 'shoes',
  category: 'sport',
});

const res = await fetch(`${PROXY}/api/relay/products?${params}`);
const { data, meta } = await res.json();

console.log(meta.total);  // total records
console.log(data);        // products array

POST / PUT / PATCH / DELETE

Mutation requests work exactly like GET -- add a body and change the method.

All mutation methods follow the same pattern. Each has its own section below with a direct link.

POST

Create a new resource on your backend.

const res = await fetch(
  `${PROXY}/api/relay/users` +
  `?webUrl=${encodeURIComponent(WEB_URL)}` +
  `&baseApiUrl=${encodeURIComponent(API_BASE)}` +
  `&acceptHeadersKey=authorization`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer eyJhbGci...',
    },
    body: JSON.stringify({
      name: 'Jane Doe',
      email: 'jane@example.com',
    }),
  }
);

const result = await res.json();
// result.success -> true
// result.data    -> created user object

PUT

Replace an entire resource on your backend.

const res = await fetch(
  `${PROXY}/api/relay/users/42` +
  `?webUrl=${encodeURIComponent(WEB_URL)}` +
  `&baseApiUrl=${encodeURIComponent(API_BASE)}` +
  `&acceptHeadersKey=authorization`,
  {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer eyJhbGci...',
    },
    body: JSON.stringify({
      name: 'Updated Name',
      isActive: true,
    }),
  }
);
const result = await res.json();

PATCH

Partially update a resource -- only send the fields you want to change.

const res = await fetch(
  `${PROXY}/api/relay/users/42` +
  `?webUrl=${encodeURIComponent(WEB_URL)}` +
  `&baseApiUrl=${encodeURIComponent(API_BASE)}` +
  `&acceptHeadersKey=authorization`,
  {
    method: 'PATCH',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer eyJhbGci...',
    },
    body: JSON.stringify({
      // only the fields you want to update
      isActive: false,
    }),
  }
);
const result = await res.json();

DELETE

Remove a resource from your backend.

const res = await fetch(
  `${PROXY}/api/relay/users/42` +
  `?webUrl=${encodeURIComponent(WEB_URL)}` +
  `&baseApiUrl=${encodeURIComponent(API_BASE)}` +
  `&acceptHeadersKey=authorization`,
  {
    method: 'DELETE',
    headers: {
      Authorization: 'Bearer eyJhbGci...',
    },
  }
);

const result = await res.json();
if (result.success) {
  console.log('Deleted');
}

Response Shape

Every response from ProxyBridge has the same consistent envelope, regardless of what your backend returns.

Success (2xx)

{
  "success": true,
  "statusCode": 200,
  "message": "Successfully Retrieved!",
  "meta": {
    "total": 100,
    "page": 1,
    "limit": 20,
    "skip": 0
  },
  "data": [ ...your items... ]
}

Error (4xx / 5xx)

{
  "success": false,
  "statusCode": 404,
  "message": "Not Found",
  "meta": null,
  "data": null
}
FieldTypeDescription
successbooleantrue when the upstream responded with a 2xx status code.
statusCodenumberThe exact HTTP status code returned by your backend.
messagestringA message from your backend, or a default like "Successfully Retrieved!".
metaobject | nullPagination info (total, page, limit, skip) when your backend includes it.
dataanyThe actual payload your backend returned -- array, object, etc.

Tip: Always check data.success or res.ok before consuming data.data -- if the upstream call fails, data.data will be null.

Error Handling

Errors from ProxyBridge itself (not your backend) use these status codes.

StatusWhenmessage
400webUrl or baseApiUrl is missingMissing required query parameters: web url or api url
500Your backend returned HTML instead of JSON (e.g. a login redirect or error page)Expected JSON but received non-JSON (likely HTML).
500Network error or unexpected crash inside ProxyBridgeServer Error

Errors from your own backend (e.g. 401 Unauthorized, 404 Not Found) are passed through transparently — success will be false and statusCode will match your backend's response.

TypeScript Types

Import these types to get full type safety when consuming ProxyBridge responses.

// The envelope every ProxyBridge response returns
interface IBaseResponse<D = any> {
  success: boolean;
  statusCode: number;
  message: string;
  meta: IMetaResponse | null;
  data: D;
}

// Pagination metadata (present when your backend sends it)
interface IMetaResponse {
  total: number;
  page: number;
  limit: number;
  skip: number;
}

// Usage example ----------------------------------------

interface User {
  id: string;
  name: string;
  email: string;
}

const res = await fetch(url);
const result: IBaseResponse<User[]> = await res.json();

if (result.success) {
  const users: User[] = result.data;  // fully typed :)
}
← Back to HomeProxyBridge Docs