Custom service returns "401 (Unauthorized : Missing required argument merchant_id)" I'm trying to call a custom service module, but it shows 401.

resource:

$resources =  array(
    'get_contacts' =&gt; array(
      'operations' =&gt; array(
        'index' =&gt; array(
          'help' =&gt; 'Get customers and their contacts',
          'file' =&gt; array('type' =&gt; 'inc', 'module' =&gt; 'sync_contacts', 'name' =&gt; 'resources/sync_contacts.resource'),
          'callback' =&gt; '_get_customer_contacts',
          'args' =&gt; array(
            array(
              'name' =&gt; 'merchant_id',
              'type' =&gt; 'int',
              'description' =&gt; t('Get customers and their contacts by merchant_id.'),
              'source' =&gt; array('data' =&gt; 'merchant_id'),
              'optional' =&gt; FALSE,              
            ),
          ),
          'access callback file' =&gt; array(
            'type' =&gt; 'inc',
            'module' =&gt; 'drupalgap',
            'name' =&gt; 'drupalgap.resource',
          ),
          'access callback' =&gt; '_sync_contacts_access',
          'access arguments' =&gt; array('view'),
          'access arguments append' =&gt; TRUE,
        ),
      ),
    ),
  );


Service function:

function sync_contacts_get_customers_list(options) {
  try { 
    options.method = 'GET'; 
    options.path = 'get_contacts.json';//'.json' removed and tested also
    options.service = 'sync_contacts';
    options.resource = 'get_contacts';

    Drupal.services.call(options);
  }
  catch (error) {
    console.log( error);
  }
}


Service function call:

try {
    var my_args = {
        merchant_id: 1
    };
    sync_contacts_get_customers_list({
      data: JSON.stringify(my_args),
      success: function(result) {           
        drupalgap_alert("SUCCESSSS");
        $("#contactList").append(JSON.stringify(result, null, 2));    
      }
    });
  } catch (error) { console.log(error); }


POSTMAN:


This is how I used the custom service. when I execute it, it shows "401 (Unauthorized : Missing required argument merchant_id)".

How can I fix this issue?

SOLUTION: Used Tyler's resource in his answer below and service call modified as below(changed GET to POST and path modified accordingly).

Note: To test, in POSTMAN also we have to call with POST and pass the merchant_id as Raw ie. {"merchant_id": 1}

function sync_contacts_get_customers_list(options) {    
   try {    
     options.method = 'POST';   
     options.path = 'sync_contacts_resources/get_contacts';
     options.service = 'sync_contacts';
     options.resource = 'get_contacts';

     Drupal.services.call(options);
  }
  catch (error) {
    console.log( error);
  }
}
You have to use the POST method in the sync_contacts_get_customers_list function:

options.method = 'POST';

Without this, you aren't "posting" anything up to Drupal Services, so your resource in Drupal will not be delivered the merchant_id.

If you want to use a GET request, then I'd recommend using a Views JSON (from Views datasource) and a contextual filter(s), otherwise custom resources in Services always use POST AFAIK, unless you're building a CRUD interface for an Entity (e.g. Services Entity API).

Also the way you are defining your custom resource in Drupal is incorrect, use actions instead:

  $resources = array(
    'sync_contacts_resources' =&gt; array(
      'actions' =&gt; array(
        'get_contacts' =&gt; array(
          'help' =&gt; 'Get customers and their contacts',
          'file' =&gt; array('type' =&gt; 'inc', 'module' =&gt; 'sync_contacts', 'name' =&gt; 'resources/sync_contacts.resource'),
          'callback' =&gt; '_get_customer_contacts',
          'args' =&gt; array(
            array(
              'name' =&gt; 'merchant_id',
              'type' =&gt; 'int',
              'description' =&gt; t('Get customers and their contacts by merchant_id.'),
              'source' =&gt; array('data' =&gt; 'merchant_id'),
              'optional' =&gt; FALSE,              
            ),
          ),
          'access callback file' =&gt; array(
            'type' =&gt; 'inc',
            'module' =&gt; 'drupalgap',
            'name' =&gt; 'drupalgap.resource',
          ),
          'access callback' =&gt; '_sync_contacts_access',
          'access arguments' =&gt; array('view'),
          'access arguments append' =&gt; TRUE,
        ),
      ),
    ),
  );