> For the complete documentation index, see [llms.txt](https://readme.directual.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://readme.directual.com/web-pages/components/html-code/custom-browser-api.md).

# Custom Browser API

### Overview

The FPS platform provides a global browser API for custom HTML components. This API handles authentication automatically using secure HTTP-only cookies, eliminating the need to manage session tokens in your code.

### Available APIs

#### `window.callEndpoint()`

Makes authenticated API requests to your backend endpoints.

**Signature:**

```javascript
window.callEndpoint(endpoint, method, body, params, callback, options)
```

**Parameters:**

* `endpoint` (string) - The API endpoint name (e.g., `'getFeatures'`, `'updateUser'`)
* `method` (string) - HTTP method: `'GET'`, `'POST'`, `'PUT'`, `'DELETE'`
* `body` (object) - Request body for POST/PUT/DELETE requests (ignored for GET)
* `params` (object) - Query parameters (e.g., `{ page: 1, limit: 10 }`)
* `callback` (function) - Callback function: `(status, data, settings, fullResponse) => {}`
  * `status` (string) - `'ok'` or `'error'`
  * `data` (array|object) - Response data
  * `settings` (object) - View settings (optional)
  * `fullResponse` (object) - Full API response
* `options` (object) - Optional settings (e.g., `{ signal: abortController.signal }`)

**Returns:** Nothing (results passed to callback)

### Examples

#### Basic GET Request

```javascript
// Fetch user list
window.callEndpoint(
  'getUsers',           // endpoint
  'GET',                // method
  undefined,            // body (not used for GET)
  { limit: 10 },        // params
  (status, data) => {   // callback
    if (status === 'ok') {
      console.log('Users:', data);
      // Render your data here
    } else {
      console.error('Error:', data);
    }
  }
);
```

#### POST Request with Body

```javascript
// Create new item
window.callEndpoint(
  'createItem',
  'POST',
  { 
    title: 'New Item',
    description: 'Item description',
    price: 99.99
  },
  {},
  (status, data) => {
    if (status === 'ok') {
      console.log('Created:', data);
    }
  }
);
```

#### Update Request

```javascript
// Update existing record
window.callEndpoint(
  'updateItem',
  'POST',
  { 
    id: '123',
    title: 'Updated Title'
  },
  {},
  (status, data, settings, fullResponse) => {
    if (status === 'ok') {
      console.log('Updated successfully');
      console.log('Full response:', fullResponse);
    }
  }
);
```

#### Search with Filters

```javascript
// Search with query parameters
window.callEndpoint(
  'searchItems',
  'GET',
  undefined,
  {
    _value: 'search term',
    category: 'electronics',
    minPrice: 50
  },
  (status, data) => {
    if (status === 'ok') {
      document.getElementById('results').innerHTML = 
        data.map(item => `<div>${item.title}</div>`).join('');
    }
  }
);
```

#### With Abort Controller

```javascript
const abortController = new AbortController();

window.callEndpoint(
  'getLargeData',
  'GET',
  undefined,
  {},
  (status, data) => {
    console.log('Data received:', data);
  },
  { signal: abortController.signal }
);

// Cancel request after 5 seconds
setTimeout(() => abortController.abort(), 5000);
```

### Authentication

**All requests are automatically authenticated.** The session token is stored in a secure HTTP-only cookie and is automatically included with every request. You don't need to:

* Store tokens in localStorage/sessionStorage
* Manually add authorization headers
* Handle token refresh

The platform manages authentication for you.

### Error Handling

```javascript
window.callEndpoint(
  'riskyOperation',
  'POST',
  { data: 'value' },
  {},
  (status, data) => {
    if (status === 'error') {
      // API returned an error
      console.error('API Error:', data.msg || data);
      // Show error to user
      alert('Operation failed: ' + (data.msg || 'Unknown error'));
    } else {
      // Success
      console.log('Success:', data);
    }
  }
);
```

### Migration Guide

If you have existing code using `fetch()` directly, you need to migrate to `window.callEndpoint()` for authentication to work properly.

#### Before (Old Code - Will Not Work)

```javascript
// ❌ This will NOT work - no access to session token
fetch('https://api.example.com/endpoint?sessionID=TOKEN', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ key: 'value' })
})
.then(res => res.json())
.then(data => console.log(data));
```

#### After (New Code - Works)

```javascript
// ✅ This works - automatic authentication
window.callEndpoint(
  'endpoint',
  'POST',
  { key: 'value' },
  {},
  (status, data) => {
    if (status === 'ok') {
      console.log(data);
    }
  }
);
```

### File Upload with FormData

```javascript
// Upload file to backend
const fileInput = document.getElementById('fileInput');

fileInput.addEventListener('change', (e) => {
  const file = e.target.files[0];
  
  if (!file) return;
  
  // Create FormData and append file
  const formData = new FormData();
  formData.append('file', file);
  
  // You can add additional fields
  formData.append('description', 'My uploaded file');
  formData.append('category', 'documents');
  
  window.callEndpoint(
    'uploadFile',         // endpoint name
    'POST',               // method
    formData,             // FormData body (not JSON!)
    { 
      fileStorage: 'my-storage',
      maxSize: 10485760  // optional params
    },
    (status, data) => {
      if (status === 'ok') {
        console.log('File uploaded:', data);
        // data might contain file URL, ID, etc.
        alert('File uploaded successfully!');
      } else {
        console.error('Upload failed:', data);
        alert('Upload error: ' + (data.msg || 'Unknown error'));
      }
    }
  );
});
```

Important for file uploads:

* Use FormData instead of plain object for body parameter
* The browser automatically sets correct Content-Type with boundary for multipart/form-data
* Field name 'file' must match your backend FileUpload data structure field
* You can append multiple files or additional text fields to FormData

### AI Migration Prompt

Use this prompt with an AI assistant to automatically convert your old code:

***

**PROMPT:**

```
I need to migrate my fetch() API calls to use window.callEndpoint() for the FPS platform.

OLD PATTERN (fetch):
- Direct fetch() calls to API endpoints
- Manual sessionID/token in URL or headers
- Promise-based (.then/.catch)

NEW PATTERN (window.callEndpoint):
- window.callEndpoint(endpoint, method, body, params, callback)
- Automatic authentication (no token needed)
- Callback-based

CONVERSION RULES:
1. Extract endpoint name from URL (last segment)
2. Convert HTTP method (GET/POST/PUT/DELETE)
3. Move body from fetch options to 3rd parameter
4. Move URL query params to 4th parameter (as object)
5. Convert .then(res => res.json()).then(data => ...) to callback: (status, data) => { if (status === 'ok') { ... } }
6. Remove all sessionID, token, Authorization headers
7. Keep only 'signal' in options if using AbortController

Please convert this code:

[PASTE YOUR CODE HERE]
```

***

**Example Conversion:**

Input:

```javascript
fetch('/api/sl?sl=getFeatures&limit=10', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ category: 'electronics' })
})
.then(res => res.json())
.then(data => {
  console.log(data);
  renderItems(data);
})
.catch(err => console.error(err));
```

AI Output:

```javascript
window.callEndpoint(
  'getFeatures',
  'POST',
  { category: 'electronics' },
  { limit: 10 },
  (status, data) => {
    if (status === 'ok') {
      console.log(data);
      renderItems(data);
    } else {
      console.error(data);
    }
  }
);
```

### Best Practices

1. **Always check status** in the callback before using data
2. **Don't store tokens** - authentication is handled automatically
3. **Use meaningful endpoint names** that match your backend structure
4. **Handle errors gracefully** with user-friendly messages
5. **Use AbortController** for long-running requests that can be cancelled
6. **Test in browser console** before integrating into your component

### Troubleshooting

#### Request not authenticated

* Make sure you're logged in to the platform
* Check that the user has valid session (check browser cookies for `token_new_*`)

#### Endpoint not found

* Verify the endpoint name matches your backend configuration
* Check for typos in the endpoint string

#### Data not received

* Verify the callback function is being called
* Check browser console for errors
* Inspect network tab in DevTools to see the actual request/response

### Additional Resources

* See `SESSION_AUTH.md` for details on session management
* Check your backend API documentation for available endpoints
* Use browser DevTools Network tab to debug requests


---

# 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, and the optional `goal` query parameter:

```
GET https://readme.directual.com/web-pages/components/html-code/custom-browser-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
