Add reward points to users via a secure REST endpoint exposed by the plugin.

What does this API do?

It exposes a REST endpoint that adds reward points to a WooCommerce user and returns the user’s new total.
Internally it reuses the plugin’s manually_add_user_points() logic so totals, logs, and hooks behave like a manual admin add.

What is the endpoint?

  • Method: POST
  • Route: /wp-json/wc-reward-points/v1/add-points

What permissions are required?

Only authenticated users who can manage_woocommerce may call this endpoint (typically Administrators or Shop Managers). Unauthorized requests are rejected.

What request parameters are required?

All parameters are required and validated on the server:

Field Type Rules Purpose
user_id integer Must exist in WordPress Which user to credit
points integer Must be a positive integer (> 0) How many points to add
message string Sanitized server-side (sanitize_text_field) Shown in the points log/note

Example JSON body

{
  "user_id": 123,
  "points": 250,
  "message": "Customer service gesture for delayed shipment"
}

What does a successful response look like?

{
  "success": true,
  "user_id": 123,
  "points_added": 250,
  "new_total": 1420,
  "message": "Customer service gesture for delayed shipment"
}

Note: new_total is read from user meta after the add completes.

What errors might I see?

HTTP Code When it happens
400 invalid_user user_id is missing/invalid or the user doesn’t exist
400 invalid_points points is <= 0 or missing
401 n/a Not authenticated
403 n/a Authenticated but lacks manage_woocommerce capability
404 n/a Route not registered (plugin disabled or API not enabled)

How do I authenticate?

  1. Application Passwords (recommended for server-to-server): WordPress 5.6+ → User Profile → Application Passwords → Create new. Use HTTP Basic Auth (user:application-password).
  2. Logged-in cookies + nonce (for in-dashboard calls from wp-admin).
  3. JWT/OAuth (via separate auth plugins) if your stack uses them.

cURL example (Application Passwords)

curl -X POST "https://example.com/wp-json/wc-reward-points/v1/add-points" \
  -u "admin:YOUR-APP-PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{"user_id":123,"points":250,"message":"Promo: Spring bonus"}'

Postman/Insomnia quick setup

  1. Method/URL: POST https://your-site/wp-json/wc-reward-points/v1/add-points
  2. Auth: Basic → username: your WP user, password: Application Password
  3. Headers: Content-Type: application/json
  4. Body (raw JSON): see example above

PHP example (server-side with Application Passwords)

<?php
$url = site_url('/wp-json/wc-reward-points/v1/add-points');

$resp = wp_remote_post($url, array(
  'headers' => array(
    'Authorization' => 'Basic ' . base64_encode('admin:YOUR-APP-PASSWORD'),
    'Content-Type'  => 'application/json',
  ),
  'body' => wp_json_encode(array(
    'user_id' => 123,
    'points'  => 100,
    'message' => 'Welcome bonus',
  )),
  'timeout' => 20,
));

if (is_wp_error($resp)) {
  error_log($resp->get_error_message());
} else {
  $code = wp_remote_retrieve_response_code($resp);
  $body = json_decode(wp_remote_retrieve_body($resp), true);
  // Handle $code / $body
}

WP Nonce + logged-in cookie example (AJAX from wp-admin)

fetch('/wp-json/wc-reward-points/v1/add-points', {
  method: 'POST',
  credentials: 'include', // send auth cookies
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ user_id: 123, points: 50, message: 'Manual adjustment' })
}).then(r => r.json()).then(console.log);
The endpoint relies on capability checks (current_user_can('manage_woocommerce')), so cookies + a logged-in admin session are sufficient for auth in this context.

Does this work on multisite?

Yes. If both are true: WordPress is multisite and the plugin setting multisiteSplitPoints is enabled, points are stored under a site-specific meta key:

woocommerce_reward_points_<BLOG_ID>

Otherwise, the meta key is:

woocommerce_reward_points

This matters if you read totals directly from user meta elsewhere.

Why might the route be missing (404)?

  • The plugin (or its API feature) is disabled.
  • The plugin option enable is false (routes register only when enabled).
  • Your caching layer blocks /wp-json or POST requests.
  • A security/firewall plugin interferes with REST calls.

What happens internally when I call the API?

  1. Inputs are sanitized and validated.
  2. The code sets $_POST['userId'], $_POST['points'], $_POST['text'], and $_POST['action']='woocommerce_reward_points_add_points'.
  3. It initializes WooCommerce_Reward_Points_Earning and calls manually_add_user_points().
  4. It reads the updated total from user meta and returns it in the response.

Can I use it to deduct points?

No—this endpoint only adds points (requires points > 0). To deduct, create a separate endpoint or extend this one with a safe decrement workflow.

Is there rate limiting or idempotency?

Not built-in. If you integrate with external systems, implement client-side idempotency (e.g., a unique operation ID) to avoid duplicate awards.

How can I test quickly?

  1. Enable the plugin’s API setting (enable = true).
  2. Confirm your user can manage_woocommerce.
  3. Run the cURL example.
  4. Verify the user’s points in the admin or via:
    get_user_meta(123, 'woocommerce_reward_points', true);

    (or the multisite-aware key if applicable)

Troubleshooting checklist

  • 401/403: Not authenticated or lacks capability. Use Application Passwords or an admin session.
  • 404: Ensure the feature is enabled; confirm no firewall blocks /wp-json.
  • 400 invalid_user: user_id must be an existing WP user.
  • 400 invalid_points: Use a positive integer.
  • Totals not changing: Check for custom hooks or object caching layers that might roll back/buffer changes.

Security best practices

  • Prefer Application Passwords for server-to-server calls; restrict to a low-privilege admin account if possible.
  • Serve over HTTPS only.
  • Log each award with a clear, human-readable message.
  • Consider adding rate limiting or WAF rules if exposing this beyond internal systems.

Leave a Reply

Your email address will not be published. Required fields are marked *