API Documentation

The Indexceptional REST API lives under the index/api/v1 namespace and currently exposes authenticated endpoints for checking credits, submitting indexing orders, listing orders, checking order status, and checking indexed status.

This page reflects the current code in class-api.php, class-check-indexed.php, class-rate-limiter.php, and CreditNex\App\Credits\Pricing.

Authentication uses Basic Auth with a WordPress Application Password. In class-api.php, the determine_current_user filter accepts credentials from PHP_AUTH_USER and PHP_AUTH_PW, or from a raw Authorization: Basic ... header that is base64-decoded and passed to wp_authenticate().

  1. Log in to your Indexceptional account.
  2. Open the Account page and go to the API Access tab.
  3. Create a WordPress Application Password for your integration.
  4. Use your WordPress username as the Basic Auth username.
  5. Use the generated application password exactly as issued as the Basic Auth password.
Authorization: Basic {base64(username:application-password)}
Content-Type: application/json
Accept: application/json

https://www.indexceptional.com/wp-json/index/api/v1

Namespace: index/api/v1

Example with query parameters: https://www.indexceptional.com/wp-json/index/api/v1/orders?per_page=20&page=1&status=completed


Returns the authenticated user's current credit balance.

GET https://www.indexceptional.com/wp-json/index/api/v1/check-balance

Response shape: { success: true, data: { credits: int } }

  • credits is an integer balance.
  • -1 means the account has unlimited credits.

Example Response

{
"success": true,
"data": {
"credits": 125
}
}

Creates a new indexing order for the authenticated user.

POST https://www.indexceptional.com/wp-json/index/api/v1/order

Request Body

ParameterTypeRequiredDescription
urlsstring[]YesArray of URLs to submit.
product_idintegerNoOptional WooCommerce product ID. Only products with slug index or drip-index are accepted.
validatedbooleanNoOptional client flag indicating the URLs were HTTP-validated before submission. Defaults to false.

Pricing

  • Slug index costs 5 credits per URL.
  • Slug drip-index costs 1 credit per URL.
  • If product_id is omitted, the endpoint defaults to slug drip-index.
  • Pricing::ALLOWED_SLUGS only allows drip-index and index.
  • The indexceptional_credit_costs filter can raise prices above the defaults, but it cannot lower them.

Order Submission Limits

  • Maximum 500 URLs per order.
  • Minimum 20 seconds between order submissions.
  • Maximum 10 orders per day.

Request Body Example

{
"urls": [
"https://example.com/page1",
"https://example.com/page2"
],
"product_id": 1234,
"validated": true
}

Success Response Fields

  • order_id: WooCommerce order ID.
  • status: Current order status.
  • total_urls: Number of submitted URLs.
  • credits_charged: Total credits debited for this order.
  • credits_remaining: Updated credit balance after payment. Unlimited accounts return -1.
  • view_order_url: WooCommerce order view URL.
  • urls: Array of per-URL objects with url, date_created, status, and bot_ip.

Example Response

{
"success": true,
"data": {
"order_id": 12345,
"status": "api-ordered",
"total_urls": 2,
"credits_charged": 2,
"credits_remaining": 123,
"view_order_url": "https://www.indexceptional.com/my-account/view-order/12345/",
"urls": [
{
"url": "https://example.com/page1",
"date_created": "2026-05-22",
"status": "queued",
"bot_ip": "-"
},
{
"url": "https://example.com/page2",
"date_created": "2026-05-22",
"status": "queued",
"bot_ip": "-"
}
]
}
}

Common Error Codes

  • missing_urls: The request did not include a valid URL array.
  • too_many_urls: More than 500 URLs were submitted.
  • rate_limit_exceeded: Another order was submitted less than 20 seconds ago.
  • daily_limit_exceeded: The user already placed 10 orders today.
  • product_not_found: No allowed indexing product could be resolved.
  • product_not_priceable: The chosen product is not a recognized credit-purchase indexing product.
  • insufficient_credits: The account balance is lower than the required credit charge.
  • payment_failed: CreditNex payment processing did not succeed.

Returns the authenticated user's orders as a paginated list of WooCommerce order IDs.

GET https://www.indexceptional.com/wp-json/index/api/v1/orders?per_page=10&page=1&status=any

Query Parameters

ParameterTypeRequiredDefaultDescription
per_pageintegerNo10Orders per page. Sanitized with absint.
pageintegerNo1Page number. Sanitized with absint.
statusstringNoanyOptional order status filter.

Allowed Status Values

  • any
  • api-ordered
  • manual-action
  • gbot-visited
  • checking-index
  • completed

Example Response

{
"success": true,
"data": {
"orders": [12345, 12346, 12347],
"total": 23,
"per_page": 10,
"current_page": 1,
"total_pages": 3
}
}

If status is invalid, WordPress REST argument validation rejects the request before the callback runs.


Returns the current status of a specific order owned by the authenticated user.

GET https://www.indexceptional.com/wp-json/index/api/v1/order/status/{order_id}

URL Parameters

ParameterTypeRequiredDescription
order_idintegerYesWooCommerce order ID.

Success Response Fields

  • order_id
  • status
  • date_created in ISO 8601 format from $order->get_date_created()->format('c').
  • total_urls
  • validated_urls as a boolean derived from item meta.
  • urls with per-URL fields: url, indexable, date_created, status, date_indexed, serp, and bot_ip.

Example Response

{
"success": true,
"data": {
"order_id": 12345,
"status": "api-ordered",
"date_created": "2026-05-22T12:00:00+00:00",
"total_urls": 2,
"validated_urls": true,
"urls": [
{
"url": "https://example.com/page1",
"indexable": "200",
"date_created": "2026-05-22",
"status": "queued",
"date_indexed": "-",
"serp": "-",
"bot_ip": "-"
},
{
"url": "https://example.com/page2",
"indexable": "200",
"date_created": "2026-05-22",
"status": "queued",
"date_indexed": "-",
"serp": "-",
"bot_ip": "-"
}
]
}
}

Common Error Codes

  • order_not_found: The order ID does not exist.
  • unauthorized: The current user does not own the order and does not have WooCommerce management capabilities.

This separate controller in class-check-indexed.php lets authenticated users check indexed status for a batch of URLs.

POST https://www.indexceptional.com/wp-json/index/api/v1/check-indexed

Request Body

ParameterTypeRequiredDescription
urlsstring[]YesMust contain between 1 and 500 valid URLs.
batch_namestringNoOptional label stored with the batch history.

The controller enforces a daily quota of 500 checked URLs per user, stored in a transient with a TTL of 86400 seconds.

Example Response

{
"success": true,
"data": {
"batch_id": "chk_664d1c0012345",
"indexed": 1,
"not_indexed": 1,
"items": [],
"quota_used_today": 2,
"quota_remaining": 498
}
}

Common Error Codes

  • invalid_urls: The request body did not contain between 1 and 500 URLs.
  • invalid_url: At least one URL failed validation.
  • quota_exceeded: The daily indexed-check quota was exceeded.
  • missing_dependency: The indexed status dependencies are unavailable.
  • db_insert_failed: Check history could not be stored.

{
    "success": true,
    "data": {
        // Endpoint-specific payload
    }
}
{
    "code": "error_code",
    "message": "Error message description",
    "data": {
        "status": 400
    }
}

  1. Order submission limits: 500 URLs per order, 20 seconds between submissions, and 10 orders per day.
  2. Order product rules: only slugs drip-index and index are accepted for credit-purchase indexing orders.
  3. Indexed-check quota: 500 URLs per user per 86400-second quota window.

{
"code": "too_many_urls",
"message": "Maximum of 500 URLs allowed per order. You provided 750 URLs.",
"data": {
"status": 400
}
}
{
"code": "rate_limit_exceeded",
"message": "Please wait 20 seconds before submitting another request.",
"data": {
"status": 429
}
}

The actual wait time is dynamic. The code returns the remaining seconds until the 20-second minimum interval is satisfied.

{
"code": "daily_limit_exceeded",
"message": "Maximum of 10 orders per day reached. Please try again tomorrow.",
"data": {
"status": 429
}
}

Status CodeDescription
200Success
400Bad Request
403Forbidden
404Not Found
429Too Many Requests
500Server Error

The order list endpoint allows these status filters:

  1. api-ordered
  2. manual-action
  3. gbot-visited
  4. checking-index
  5. completed

Per-URL entries created by POST /order start at queued. The route code does not define a documented not-started status.


  1. Check /check-balance before large submissions if your account is not unlimited.
  2. Store the returned order_id and poll /order/status/{order_id} when you need URL-level progress.
  3. Pass product_id explicitly if you need the index tier. Omitting it defaults to drip-index.
  4. Handle 400, 403, 404, 429, and 500 responses explicitly.
  5. Do not rely on rate-limit response headers. The current code enforces limits in PHP and returns errors when limits are hit.

For support or questions, contact us at: