{"id":20409,"date":"2025-10-30T09:41:48","date_gmt":"2025-10-30T08:41:48","guid":{"rendered":"https:\/\/www.welaunch.io\/en\/?post_type=faq&p=20409"},"modified":"2025-10-30T09:43:08","modified_gmt":"2025-10-30T08:43:08","slug":"using-the-reward-points-rest-api","status":"publish","type":"faq","link":"https:\/\/www.welaunch.io\/en\/knowledge-base\/faq\/using-the-reward-points-rest-api\/","title":{"rendered":"Using the Reward Points REST API"},"content":{"rendered":"

Add reward points to users via a secure REST endpoint exposed by the plugin.<\/p>\n

\n

What does this API do?<\/h2>\n

It exposes a REST endpoint that adds reward points<\/strong> to a WooCommerce user and returns the user\u2019s new total.
\nInternally it reuses the plugin\u2019s manually_add_user_points()<\/code> logic so totals, logs, and hooks behave like a manual admin add.<\/p>\n<\/section>\n

\n

What is the endpoint?<\/h2>\n
    \n
  • Method:<\/strong> POST<\/span><\/li>\n
  • Route:<\/strong> \/wp-json\/wc-reward-points\/v1\/add-points<\/span><\/li>\n<\/ul>\n<\/section>\n
    \n

    What permissions are required?<\/h2>\n

    Only authenticated users who can manage_woocommerce<\/code><\/strong> may call this endpoint (typically Administrators or Shop Managers). Unauthorized requests are rejected.<\/p>\n<\/section>\n

    \n

    What request parameters are required?<\/h2>\n

    All parameters are required<\/strong> and validated on the server:<\/p>\n\n\n\n\n\n\n\n
    Field<\/th>\nType<\/th>\nRules<\/th>\nPurpose<\/th>\n<\/tr>\n<\/thead>\n
    user_id<\/code><\/td>\ninteger<\/td>\nMust exist in WordPress<\/td>\nWhich user to credit<\/td>\n<\/tr>\n
    points<\/code><\/td>\ninteger<\/td>\nMust be a positive integer (> 0)<\/td>\nHow many points to add<\/td>\n<\/tr>\n
    message<\/code><\/td>\nstring<\/td>\nSanitized server-side (sanitize_text_field<\/code>)<\/td>\nShown in the points log\/note<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n

    Example JSON body<\/strong><\/p>\n

    {\r\n  \"user_id\": 123,\r\n  \"points\": 250,\r\n  \"message\": \"Customer service gesture for delayed shipment\"\r\n}<\/pre>\n<\/section>\n
    \n

    What does a successful response look like?<\/h2>\n
    {\r\n  \"success\": true,\r\n  \"user_id\": 123,\r\n  \"points_added\": 250,\r\n  \"new_total\": 1420,\r\n  \"message\": \"Customer service gesture for delayed shipment\"\r\n}<\/pre>\n

    Note:<\/em> new_total<\/code> is read from user meta after the add completes.<\/p>\n<\/section>\n

    \n

    What errors might I see?<\/h2>\n\n\n\n\n\n\n\n\n\n
    HTTP<\/th>\nCode<\/th>\nWhen it happens<\/th>\n<\/tr>\n<\/thead>\n
    400<\/td>\ninvalid_user<\/code><\/td>\nuser_id<\/code> is missing\/invalid or the user doesn\u2019t exist<\/td>\n<\/tr>\n
    400<\/td>\ninvalid_points<\/code><\/td>\npoints<\/code> is <= 0<\/code> or missing<\/td>\n<\/tr>\n
    401<\/td>\nn\/a<\/td>\nNot authenticated<\/td>\n<\/tr>\n
    403<\/td>\nn\/a<\/td>\nAuthenticated but lacks manage_woocommerce<\/code> capability<\/td>\n<\/tr>\n
    404<\/td>\nn\/a<\/td>\nRoute not registered (plugin disabled or API not enabled)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/section>\n
    \n

    How do I authenticate?<\/h2>\n
      \n
    1. Application Passwords<\/strong> (recommended for server-to-server): WordPress 5.6+ \u2192 User Profile \u2192 Application Passwords<\/em> \u2192 Create new. Use HTTP Basic Auth (user:application-password<\/code>).<\/li>\n
    2. Logged-in cookies + nonce<\/strong> (for in-dashboard calls from wp-admin).<\/li>\n
    3. JWT\/OAuth<\/strong> (via separate auth plugins) if your stack uses them.<\/li>\n<\/ol>\n<\/section>\n
      \n

      cURL example (Application Passwords)<\/h2>\n
      curl -X POST \"https:\/\/example.com\/wp-json\/wc-reward-points\/v1\/add-points\" \\\r\n  -u \"admin:YOUR-APP-PASSWORD\" \\\r\n  -H \"Content-Type: application\/json\" \\\r\n  -d '{\"user_id\":123,\"points\":250,\"message\":\"Promo: Spring bonus\"}'<\/pre>\n<\/section>\n
      \n

      Postman\/Insomnia quick setup<\/h2>\n
        \n
      1. Method\/URL:<\/strong> POST https:\/\/your-site\/wp-json\/wc-reward-points\/v1\/add-points<\/span><\/li>\n
      2. Auth:<\/strong> Basic \u2192 username: your WP user, password: Application Password<\/li>\n
      3. Headers:<\/strong> Content-Type: application\/json<\/code><\/li>\n
      4. Body (raw JSON):<\/strong> see example above<\/li>\n<\/ol>\n<\/section>\n
        \n

        PHP example (server-side with Application Passwords)<\/h2>\n
        <?php\r\n$url = site_url('\/wp-json\/wc-reward-points\/v1\/add-points');\r\n\r\n$resp = wp_remote_post($url, array(\r\n  'headers' => array(\r\n    'Authorization' => 'Basic ' . base64_encode('admin:YOUR-APP-PASSWORD'),\r\n    'Content-Type'  => 'application\/json',\r\n  ),\r\n  'body' => wp_json_encode(array(\r\n    'user_id' => 123,\r\n    'points'  => 100,\r\n    'message' => 'Welcome bonus',\r\n  )),\r\n  'timeout' => 20,\r\n));\r\n\r\nif (is_wp_error($resp)) {\r\n  error_log($resp->get_error_message());\r\n} else {\r\n  $code = wp_remote_retrieve_response_code($resp);\r\n  $body = json_decode(wp_remote_retrieve_body($resp), true);\r\n  \/\/ Handle $code \/ $body\r\n}<\/pre>\n<\/section>\n
        \n

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

        Does this work on multisite?<\/h2>\n

        Yes. If both<\/em> are true: WordPress is multisite and the plugin setting multisiteSplitPoints<\/code> is enabled, points are stored under a site-specific meta key:<\/p>\n

        woocommerce_reward_points_<BLOG_ID><\/pre>\n

        Otherwise, the meta key is:<\/p>\n

        woocommerce_reward_points<\/pre>\n

        This matters if you read totals directly from user meta elsewhere.<\/p>\n<\/section>\n

        \n

        Why might the route be missing (404)?<\/h2>\n
          \n
        • The plugin (or its API feature) is disabled.<\/li>\n
        • The plugin option enable<\/code> is false<\/strong> (routes register only when enabled).<\/li>\n
        • Your caching layer blocks \/wp-json<\/code> or POST requests.<\/li>\n
        • A security\/firewall plugin interferes with REST calls.<\/li>\n<\/ul>\n<\/section>\n
          \n

          What happens internally when I call the API?<\/h2>\n
            \n
          1. Inputs are sanitized and validated.<\/li>\n
          2. The code sets $_POST['userId']<\/code>, $_POST['points']<\/code>, $_POST['text']<\/code>, and $_POST['action']='woocommerce_reward_points_add_points'<\/code>.<\/li>\n
          3. It initializes WooCommerce_Reward_Points_Earning<\/code> and calls manually_add_user_points()<\/code>.<\/li>\n
          4. It reads the updated total from user meta and returns it in the response.<\/li>\n<\/ol>\n<\/section>\n
            \n

            Can I use it to deduct<\/em> points?<\/h2>\n

            No\u2014this endpoint only adds<\/strong> points (requires points > 0<\/code>). To deduct, create a separate endpoint or extend this one with a safe decrement workflow.<\/p>\n<\/section>\n

            \n

            Is there rate limiting or idempotency?<\/h2>\n

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

            \n

            How can I test quickly?<\/h2>\n
              \n
            1. Enable the plugin\u2019s API setting (enable = true<\/code>).<\/li>\n
            2. Confirm your user can manage_woocommerce<\/code>.<\/li>\n
            3. Run the cURL example.<\/li>\n
            4. Verify the user\u2019s points in the admin or via:\n
              get_user_meta(123, 'woocommerce_reward_points', true);<\/pre>\n

              (or the multisite-aware key if applicable)<\/span><\/li>\n<\/ol>\n<\/section>\n

              \n

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

                Security best practices<\/h2>\n
                  \n
                • Prefer Application Passwords<\/strong> for server-to-server calls; restrict to a low-privilege admin account if possible.<\/li>\n
                • Serve over HTTPS<\/strong> only.<\/li>\n
                • Log each award with a clear, human-readable message<\/code>.<\/li>\n
                • Consider adding rate limiting or WAF rules if exposing this beyond internal systems.<\/li>\n<\/ul>\n<\/section>\n","protected":false},"author":1,"featured_media":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","product_cat":[],"class_list":["post-20409","faq","type-faq","status-publish","hentry","faq_topics-reward-points"],"_links":{"self":[{"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/faq\/20409","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/faq"}],"about":[{"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/types\/faq"}],"author":[{"embeddable":true,"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/comments?post=20409"}],"version-history":[{"count":2,"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/faq\/20409\/revisions"}],"predecessor-version":[{"id":20411,"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/faq\/20409\/revisions\/20411"}],"wp:attachment":[{"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/media?parent=20409"}],"wp:term":[{"taxonomy":"product_cat","embeddable":true,"href":"https:\/\/www.welaunch.io\/en\/wp-json\/wp\/v2\/product_cat?post=20409"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}