> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.jelliu.co/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.jelliu.co/_mcp/server.

# Query a documented WhatsApp Graph resource

POST https://api.jelliu.co/api/whatsapp-cloud/accounts/{accountId}/graph/queries/{operation}
Content-Type: application/json

Required scope is full, or an admin/owner dashboard session. Although this HTTP route uses
POST to accept structured filters, it only dispatches provider GET operations. Select the
connected local account by UUID; resourceId is a numeric Meta ID for child resources.
Parameters are validated against the selected operation. Arbitrary Graph paths, field
expressions, credentials and foreign resources are rejected. Paged results expose data
and pagination cursors; submit after/before in parameters to continue on the same endpoint.


Reference: https://developer.jelliu.co/api-reference/whats-app/query-whats-app-graph-reference

## Authentication

- `Authorization` header (bearer token, required) — Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

## Request

### Path parameters

- `accountId` (string, required) — Local connected-account UUID belonging to the authenticated workspace.
- `operation` (string, required) — Exact operation key returned by the capabilities catalog, such as waba.read or template.update.

### Body (application/json)

This endpoint expects a WhatsAppGraphReferenceRequest.

- `resourceId` (string, optional) — Meta child-node ID. WABA operations derive the WABA ID from the connected local account.
- `parameters` (map from string to any, optional, default: {}) — Operation-specific fields validated against the capability catalog. Maximum serialized size is 256000 bytes.

## Response

### 200

Provider result wrapped in data, with graphVersion and operation.

- `data` (map from string to any, optional)

## Errors

### 400 Bad Request Error

The request failed validation (`VALIDATION_FAILED`). `error.details` names what failed: either a field map (`formErrors` / `fieldErrors`, from routes that validate with `safeParse`) or a list of issues with `path`, `message` and `code` (from routes that let the schema throw). Fix the request before retrying. See [Errors](/errors#validation-errors).

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 401 Unauthorized Error

No usable credential. Either the `Authorization` header is missing or is not a well-formed `Bearer jl_…` key, or the key is unknown, revoked or expired. Do not retry with the same key. See [Authentication](/authentication#401-unauthorized).

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 403 Forbidden Error

Authenticated, but not allowed: the key's scope does not cover the method, the route is restricted to workspace admins/owners and the key is not `full`, or the workspace is suspended (`TENANT_SUSPENDED`). See [Authentication](/authentication#scopes).

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 404 Not Found Error

The resource does not exist or belongs to another workspace; the two are indistinguishable, so ids cannot be probed across workspaces. The code is `NOT_FOUND` or a resource-specific one such as `CAMPAIGN_NOT_FOUND`, and the message names the resource.

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 422 Unprocessable Entity Error

Provider eligibility or resource state prevents this operation.

- `any`

### 429 Too Many Requests Error

Provider or workspace request limit reached.

- `any`

### 502 Bad Gateway Error

Provider response could not be confirmed or validated.

- `any`

## Types

### ErrorResponseError

The error object. Always has `code` and `message`.

- `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `PAYLOAD_TOO_LARGE`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
- `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
- `details` (ErrorResponseErrorDetails, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields); * for a rejected multipart upload (file in an unexpected field, too many files), a list with the upload error `code` (for example `LIMIT_UNEXPECTED_FILE`) and the `field` name. Absent when the value was rejected outside the route's own validation: a malformed id, number or date the database could not read, or a JSON body that does not parse.
- `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps), `tier` alone (feature gates), or `tier` = `none` with `kind` = `subscription_required` when the workspace has no active subscription. See [Errors](/errors).

### ErrorResponseErrorDetails

Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields); * for a rejected multipart upload (file in an unexpected field, too many files), a list with the upload error `code` (for example `LIMIT_UNEXPECTED_FILE`) and the `field` name. Absent when the value was rejected outside the route's own validation: a malformed id, number or date the database could not read, or a JSON body that does not parse.

- Field map: Field map
- Issue list: list of ErrorResponseErrorDetailsOneOf1Items

### Field map

- `formErrors` (list of string, optional)
- `fieldErrors` (map from string to list of string, optional)

### ErrorResponseErrorDetailsOneOf1Items

- `path` (ErrorResponseErrorDetailsOneOf1ItemsPath, optional) — Dot-separated string, or an array of keys.
- `message` (string, optional)
- `code` (string, optional) — Zod issue code, for example `invalid_type`.

### ErrorResponseErrorDetailsOneOf1ItemsPath

Dot-separated string, or an array of keys.

- string
- list of ErrorResponseErrorDetailsOneOf1ItemsPathOneOf1Items

### ErrorResponseErrorDetailsOneOf1ItemsPathOneOf1Items

- string
- integer

## Examples

**Request**

```json
{
  "parameters": {
    "fields": [
      "id",
      "name",
      "health_status"
    ]
  }
}
```

**Response**

```json
{
  "data": {}
}
```

**SDK Code**

```python WhatsApp_queryWhatsAppGraphReference_example
import requests

url = "https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation"

payload = { "parameters": { "fields": ["id", "name", "health_status"] } }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript WhatsApp_queryWhatsAppGraphReference_example
const url = 'https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"parameters":{"fields":["id","name","health_status"]}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go WhatsApp_queryWhatsAppGraphReference_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation"

	payload := strings.NewReader("{\n  \"parameters\": {\n    \"fields\": [\n      \"id\",\n      \"name\",\n      \"health_status\"\n    ]\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

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

url = URI("https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"parameters\": {\n    \"fields\": [\n      \"id\",\n      \"name\",\n      \"health_status\"\n    ]\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java WhatsApp_queryWhatsAppGraphReference_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"parameters\": {\n    \"fields\": [\n      \"id\",\n      \"name\",\n      \"health_status\"\n    ]\n  }\n}")
  .asString();
```

```php WhatsApp_queryWhatsAppGraphReference_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation', [
  'body' => '{
  "parameters": {
    "fields": [
      "id",
      "name",
      "health_status"
    ]
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp WhatsApp_queryWhatsAppGraphReference_example
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"parameters\": {\n    \"fields\": [\n      \"id\",\n      \"name\",\n      \"health_status\"\n    ]\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift WhatsApp_queryWhatsAppGraphReference_example
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["parameters": ["fields": ["id", "name", "health_status"]]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/whatsapp-cloud/accounts/accountId/graph/queries/operation")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```