# @gravityforms/request

> Utility to make WordPress REST API requests. It's a wrapper around window.fetch.

Latest version **6.1.0** (published 2026-01-06) · GPL-2.0-or-later license · 0 weekly downloads

## Install

```sh
npm install @gravityforms/request
pnpm add @gravityforms/request
yarn add @gravityforms/request
bun add @gravityforms/request
```

## Health

**Score 45/100 (D)** — status: stable.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

## Facts

| | |
|---|---|
| Version | 6.1.0 |
| Published | 2026-01-06 |
| First published | 2021-08-25 |
| Weekly downloads | 0 |
| License | GPL-2.0-or-later |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >=24.11.1 |
| Dependencies | 5 |
| Unpacked size | 42.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Rocketgenius |
| Maintainers | faction23, sswebster, laborin, alexcancado, sherifmesallam, paulmskim, ryanurban, carlhancock, nickpelton |
| Keywords | gravityforms, javascript, fetch |

## Links

- npm: https://www.npmjs.com/package/@gravityforms/request
- Repository: https://github.com/gravityforms/gravitypackages
- Homepage: https://github.com/gravityforms/gravitypackages/tree/HEAD/packages/npm/request/README.md
- Issues: https://github.com/gravityforms/gravitypackages/issues
- npm.io page: https://npm.io/package/@gravityforms/request

## Dependencies (5)

- [ramda](https://npm.io/package/ramda.md) 0.27.1
- [find-config](https://npm.io/package/find-config.md) 1.0.0
- [query-string](https://npm.io/package/query-string.md) 7.0.1
- [@babel/runtime](https://npm.io/package/@babel/runtime.md) ^7.26.0
- [underscore.string](https://npm.io/package/underscore.string.md) 3.3.5

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 6.1.0 (latest) — 2026-01-06
- 6.0.0 — 2025-11-27
- 5.0.2 — 2025-06-11
- 5.0.1 — 2024-12-27
- 5.0.0 — 2024-11-19
- 4.0.0 — 2023-12-05
- 3.0.1 — 2023-07-13
- 2.0.0 — 2023-04-06
- 1.1.2 — 2022-05-26
- 1.1.1 — 2022-01-11
- 1.1.0 — 2021-12-13
- 1.0.3 — 2021-09-08
- 1.0.2 — 2021-08-31
- 1.0.0 — 2021-08-31
- 0.0.1 — 2021-08-31
- … 2 more at https://npm.io/package/@gravityforms/request/versions

## README

# @gravityforms/request

HTTP request utilities for Gravity Forms products. Provides wrappers around `window.fetch` for common use cases including WordPress AJAX and the Hermes GraphQL-like API.

## Installation

```bash
npm install @gravityforms/request
```

## Exports

| Export | Description |
|--------|-------------|
| `get` | Simple GET request wrapper |
| `post` | POST request with automatic form data encoding |
| `createHermesClient` | Factory for Hermes API client with template literals |
| `serialize` | Serialize JavaScript values for Hermes queries |
| `raw` | Mark strings for raw insertion without serialization |
| `args` | Helper for object argument serialization (combines raw + serialize) |
| `request` (default) | Configuration-based request handler |

---

## `post`

The most commonly used export. Makes POST requests to WordPress AJAX endpoints with automatic form data encoding.

### Usage

```javascript
import endpoint from 'ajaxUrl'; // Webpack alias for WordPress ajaxurl
import { post } from '@gravityforms/request';

const saveData = async ( data ) => {
    const response = await post( {
        endpoint,
        body: {
            action: 'my_ajax_action',
            security: window.myPlugin.nonce,
            ...data,
        },
    } );

    if ( response?.data?.success ) {
        console.log( 'Saved:', response.data );
    } else {
        console.error( 'Error:', response?.error || response?.data );
    }
};
```

### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `endpoint` | `string` | The URL to POST to |
| `body` | `object` | Request body (automatically converted to FormData) |
| `headers` | `object` | Optional HTTP headers |
| `options` | `object` | Optional fetch options |

### Response

```javascript
{
    data: { ... },    // Parsed JSON response
    status: 200,      // HTTP status code
}
// Or on error:
{
    error: Error      // Error object with .detail property
}
```

---

## `get`

Simple GET request wrapper.

### Usage

```javascript
import { get } from '@gravityforms/request';

const fetchData = async () => {
    const response = await get( '/wp-json/my/v1/endpoint', {
        headers: { 'X-Custom-Header': 'value' },
    } );
    return response.json();
};
```

### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `endpoint` | `string` | The URL to fetch |
| `params` | `object` | Optional fetch options |

---

## Hermes Client

For interacting with the Hermes GraphQL-like API. Uses **template literals** for intuitive query construction.

### `createHermesClient`

Creates a configured client with `query` and `mutation` functions.

```javascript
import { createHermesClient, serialize, raw, args } from '@gravityforms/request';

const client = createHermesClient( {
    endpoint: window.ajaxurl,
    queryAction: 'gcrm_hermes_query',
    mutationAction: 'gcrm_hermes_mutation',
    security: window.gcrm.nonce,
    onLoadingChange: ( isLoading ) => {
        // Optional: track loading state
    },
} );
```

### Configuration Options

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `endpoint` | `string` | Yes | AJAX endpoint URL |
| `queryAction` | `string` | Yes | WordPress action for queries |
| `mutationAction` | `string` | Yes | WordPress action for mutations |
| `security` | `string` | Yes | Security nonce |
| `queryKey` | `string` | No | Body key for queries (default: `'query'`) |
| `mutationKey` | `string` | No | Body key for mutations (default: `'mutation'`) |
| `headers` | `object` | No | Custom headers for all requests |
| `options` | `object` | No | Custom fetch options |
| `onLoadingChange` | `function` | No | Callback when loading state changes |

### Query Examples

```javascript
const { query, mutation } = client;

// Simple query
const contacts = await query`{
    contact(limit: 10) {
        id,
        firstName,
        lastName
    }
}`;

// Query with interpolated values
const limit = 20;
const searchTerm = 'John';
const results = await query`{
    contact(limit: ${ limit }, search: ${ searchTerm }) {
        id,
        firstName,
        lastName,
        email { address, isPrimary }
    }
}`;

// Query with nested relationships
const deals = await query`{
    deal(limit: ${ 50 }) {
        id,
        label,
        value,
        contact {
            id,
            firstName,
            lastName
        },
        company {
            id,
            companyName
        }
    }
}`;
```

### Mutation Examples

```javascript
// Insert
const newContact = await mutation`{
    insert_contact(objects: ${ [ { firstName: 'John', lastName: 'Doe' } ] }) {
        returning {
            id,
            firstName,
            lastName
        }
    }
}`;

// Update
const contactId = '123';
await mutation`{
    update_contact(id: ${ contactId }, firstName: "Jane", lastName: "Smith") {}
}`;

// Delete
const idsToDelete = [ '1', '2', '3' ];
await mutation`{
    delete_contact(id: ${ idsToDelete }) {}
}`;

// Connect relationships
await mutation`{
    connect_company_contact(objects: ${ [ { from: companyId, to: contactId } ] }) {}
}`;

// Disconnect relationships
await mutation`{
    disconnect_company_contact(objects: ${ [ { from: companyId, to: contactId } ] }) {}
}`;
```

---

## `serialize`

Converts JavaScript values to Hermes query format. Used automatically in template literals but can be called directly for complex cases.

### Type Handling

| JavaScript Type | Hermes Output |
|-----------------|---------------|
| `null` / `undefined` | `null` |
| `boolean` | `true` / `false` |
| `number` | `123` |
| `string` | `"quoted string"` |
| `array` | `[item1, item2]` |
| `object` | `{key: value}` |

### Examples

```javascript
import { serialize } from '@gravityforms/request';

serialize( 'hello' );           // "hello"
serialize( 42 );                // 42
serialize( true );              // true
serialize( null );              // null
serialize( [ 1, 2, 3 ] );       // [1, 2, 3]
serialize( { name: 'John' } );  // {name: "John"}
```

---

## `args`

Convenience function for building query/mutation argument strings from JavaScript objects. Combines `serialize()` and `raw()` for the common argument-building pattern.

### Usage

```javascript
import { args } from '@gravityforms/request';

// Instead of building argument strings manually:
const argsStr = Object.entries({ limit: 10, search: 'test' })
    .map(([k, v]) => `${k}: ${serialize(v)}`)
    .join(', ');
await query`{ contact(${ raw( argsStr ) }) { ... } }`;

// Use args() for cleaner syntax:
await query`{ contact(${ args({ limit: 10, search: 'test' }) }) { ... } }`;
```

---

## `raw`

Marks a string for raw insertion without serialization. Use this when you've pre-built an argument string.

### Problem

```javascript
// Without raw() - becomes: pipeline("limit: 1") - WRONG!
const argsStr = 'limit: 1';
await query`{ pipeline(${ argsStr }) { id } }`;
```

### Solution

```javascript
import { raw } from '@gravityforms/request';

// With raw() - becomes: pipeline(limit: 1) - CORRECT!
const argsStr = 'limit: 1';
await query`{ pipeline(${ raw( argsStr ) }) { id } }`;
```

### Common Use Cases

```javascript
// Dynamic argument strings
const buildArgs = ( filters ) => {
    const parts = [];
    if ( filters.limit ) parts.push( `limit: ${ filters.limit }` );
    if ( filters.search ) parts.push( `search: ${ JSON.stringify( filters.search ) }` );
    return parts.join( ', ' );
};

const argsStr = buildArgs( { limit: 20, search: 'test' } );
await query`{ contact(${ raw( argsStr ) }) { id, firstName } }`;

// Dynamic field/type names
const objectType = 'contact';
await mutation`{
    delete_${ raw( objectType ) }(id: ${ ids }) {}
}`;

// Dynamic field names with serialize for values
const fieldName = 'firstName';
const value = 'John';
await mutation`{
    update_contact(id: ${ id }, ${ raw( fieldName ) }: ${ value }) {}
}`;
```

---

## `request` (Default Export)

Configuration-based request handler. Requires endpoint configuration in `gravityforms.config.js`.

### Configuration

In your project's `gravityforms.config.js`:

```javascript
module.exports = {
    requestConfig: {
        endpoints: {
            get_entries: {
                path: '/wp-json/gf/v2/entries',
                rest_params: '',
                nonce: null,
            },
            save_form: {
                path: '/wp-json/gf/v2/forms',
                action: 'gf_save_form',
                nonce: null,
            },
        },
    },
};
```

### Usage

```javascript
import request from '@gravityforms/request';

// GET request
const entries = await request( 'get_entries', endpoints, {
    method: 'GET',
    params: { form_id: 1 },
} );

// POST request
const result = await request( 'save_form', endpoints, {
    method: 'POST',
    body: { title: 'My Form', fields: [ ... ] },
} );
```

---

## React Integration

For React applications, use `@gravityforms/react-utils` which provides hooks and context:

```javascript
import { useHermesTemplateContext, HermesTemplateProvider } from '@gravityforms/react-utils';

// In your app root
<HermesTemplateProvider
    defaultProps={ {
        endpoint: window.ajaxurl,
        queryAction: 'gcrm_hermes_query',
        mutationAction: 'gcrm_hermes_mutation',
        security: window.gcrm.nonce,
    } }
>
    <App />
</HermesTemplateProvider>

// In components
const MyComponent = () => {
    const { query, mutation, isLoading } = useHermesTemplateContext();

    const fetchContacts = async () => {
        const result = await query`{
            contact(limit: 10) { id, firstName, lastName }
        }`;
        return result?.data?.data?.contact;
    };
};
```

---

## Error Handling

All request functions return errors in a consistent format:

```javascript
const response = await post( { endpoint, body } );

if ( response.error ) {
    // Network error or exception
    console.error( response.error.message );
    console.error( response.error.detail ); // Contains endpoint, status, etc.
} else if ( ! response.data?.success ) {
    // Server returned an error response
    console.error( 'Request failed:', response.data );
} else {
    // Success
    console.log( 'Data:', response.data );
}
```

---

## Best Practices

1. **Always use `post` for WordPress AJAX** - handles FormData encoding automatically
2. **Include action and security nonce** - required for WordPress AJAX handlers
3. **Use template literals for Hermes** - clearer syntax that matches server expectations
4. **Use `raw()` for dynamic field names** - prevents unwanted string quoting
5. **Check `response?.data?.success`** - standard WordPress AJAX success pattern
6. **Provide user feedback** - use snackbar or similar for success/error messages

```javascript
import { post } from '@gravityforms/request';
import { useSnackbar } from '@gravityforms/components/react/admin/modules/SnackBar';

const addSnackbarMessage = useSnackbar();

const saveItem = async ( data ) => {
    const response = await post( {
        endpoint,
        body: {
            action: 'my_action',
            security: nonce,
            ...data,
        },
    } );

    if ( response?.data?.success ) {
        addSnackbarMessage( 'Saved successfully!' );
    } else {
        addSnackbarMessage( 'Failed to save', 'error' );
    }
};
```

---
_Source: https://npm.io/package/@gravityforms/request · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
