System API

From Apez

Jump to: navigation, search

Contents

This page documents the API (Application Programming Interface) provided by the Apez system. The API is exposed as a public service and supports XML-RPC or JSON-RPC calls. The API can also be called from in-world objects.

For information about on developing for Apez services in general, refer to the Development page.

Using the API

The API takes the form of a set of functions which can be accessed using XMLRPC or JSON-RPC via SSL/TLS (i.e. HTTPS POST requests). In order to simplify client implementations an Open Source PHP XMLRPC and an Apez client library, including PHP example code, is available. However, the functions will be documented in a way that can be utilized by any XMLRPC client implementation (language independently). PHP Example scripts are also included below.

Authentication and Authorization

The majority of the API functions require authorization in order to perform their function. The authentication and authorization scheme involves the use of capabilities. So, before the function reference section, we describe what a capability is and how it works below. If you only want to call one of the few functions that doesn't require authentication, such as general.getAvatarKey(), you can skip the capabilities section below. Capabilities A capability is a character string token that gives the holder the authorization to access and manipulate some resource, just by having it. It is cryptographically encoded so that capability strings can't be generated. You can think of it as being analogous to a browser cookie or a password, except that there are many different types of capabilities and they also encode an explicit expiry date.

The capability type used most in the Apez API, is the login capability. This is returned in response to a call to the general.getLoginCapability() function (or from in-world LSL scripts using the general.getAvatarLoginCapability() function)

Most Apez API calls take a variable-length array of capabilities as an argument. If the function in question requires some specific authorization in order to perform its task, then some appropriate capability must be present in the capabilities array passed to it. The login capability is required for the majority functions. With a login capability supplied in response to authenticating as a particular avatar, you'll have the ability to do most things you can do via the web-site interface.

Some times, you may need to perform operations on behalf of other avatars. For example, patrons to your site may want to allow your server to access their Apez.vend product information, in order to make it available to the value-add services your site provides. In most cases, the user won't want to provide your server with their Apez login - hence giving you full access to their Apez account, including bank accounts, product delivery etc. In this case, there is a mechanism via which an Apez user can consent to the creation of a capability that, when passed to your server, will allow it to have access only to the necessary functions in the Apez API to perform the tasks it needs on their behalf.

One such mechanism is a special Apez web-page that prompts a user for particular permissions. For example, your site may direct a user to this Apez site page if it needs a particular capability it doesn't currently have. The Apez page can be thought of a analogous to the in-world permissions dialogs that can be triggered by LSL scripts. For example, the page may ask the user (who much be logged into Apez via their browser), if they'd like to grant your site permission to have read access the product information in their Apez.vend product collections. Once they answer, they'll be directed back to your site (via a URL you specify as an argument during the redirect), and if they answered Yes, you site will also be passed a capability. That capability, when passed in the capability array argument to API functions (in addition to your login capability), will authorize your server to read the Apez.vend database information it needs about the user's products. NB: The web-interface discussed hasn't yet been implemented.

There are various type of capabilities, for access to logs, read or read&modify access to bank accounts and others as described in the function reference section below.

Calling API functions

XMLRPC

The API interface is provided via XMLRPC - which is simply a way to send function name and parameter information in XML via HTTP/S web requests. Hence, you can make Apez API calls from any environment/language for which there exists an XMLRPC client library (or even roll-you-own, since the XML is simple and most environments have the ability to make HTTP/S calls). The Affiliate Services Kit includes a PHP client library and Apez function wrapper library to hide the details of XMLRPC for you. If you're going to use that and aren't interested in the XMLRPC details, you may skip to the next section.

While the functions are detailed below, a quick example will make things clearer. Suppose you wish to call the general.getAvatarKey() function, which is documented below as taking a single string parameter - the avatar name for whom you wish to look up their key. To do so, you'd make a HTTP POST request to the URL http://www.apez.biz/api.php containing the following XML payload: (note that the space isn't significant)

<?xml version="1.0" ?>
<methodCall>
  <methodName>general.getAvatarKey</methodName>
  <params>
    <param>
      <value>
        <string>Secret2 Linden</string>
      </value>
    </param>
  </params>
</methodCall>

What you'd get back in the HTTP response body would be:

<?xml version="1.0" ?>
<methodResponse>
  <params>
    <param>
      <value>
         <string>3d9c9417-6b10-594b-b7b0-7d21616aaf50</string>
      </value>
    </param>
  </params>
</methodResponse>

Most of the API functions take an array of capability strings as their first argument. Here is an example of a call that includes a capability array with one element (followed by string and int arguments as the 2nd and 3rd parameters):

<?xml version="1.0" ?>
<methodCall>
   <methodName>bank.grantAllAccountsFullCapability</methodName>
   <params>
       <param>
           <value>
               <array>
                   <data>
                       <value>
                           <string>V1ad4ab3b51453de416ed87371b80a8231270-e4b4f1b3-f9fb-ceb4-b031-1a128795d26b00001365265</string>
                       </value>
                   </data>
               </array>
           </value>
       </param>
       <param>
           <value>
               <string>ba7d14ff-a43e-4a04-982a-141e25290142</string>
           </value>
       </param>
       <param>
           <value>
               <int>86400</int>
           </value>
       </param>
   </params>
</methodCall>

JSON-RPC

...



In the reference section below, for simplicity, the functions will be documented using a C-like declaration syntax. So, the above function is documented as having the call signature: string bank.grantAllAccountsFullCapability(array<string> capabilities, string auth_akey, int valid_for_secs). Notice that the parameter names are just explanatory, they don't appear in the XML - so the order is important. In the event of an error, the Apez server returns a standard XMLRPC fault, which includes a faultCode and a string explanation of the error.

Because many functions take and return capabilities, it is recommended that you call the Apez server using the HTTPS protocol rather than plain HTTP for added security. For example, if someone intercepts your login capability string, they'll be able to use the API as if they were you (until the capability expires - which is why requesting short capability valid periods is a good idea where appropriate - see below). This is also why web browser cookies present a similar security risk. PHP Although you may use any PHP XMLRPC client library you wish, for convenience, the Affiliate Services Kit includes two PHP files: apez-api.php and xmlrpclib.php. The xmlrpclib.php file is an open-source XMLRPC client library originally written by Keith Devens and subsequently enhanced by others, including the addition of HTTPS support by Gwyneth Llewelyn through the use of the libCURL library (which comes standard with most PHP installations). The apez-api.php provides simple PHP function wrappers around the Apez functions, including documentation. Note that, if the documentation in this guide and the PHP source differ, the source is probably more up-to-date. There are also several PHP example file included in the kit, which can be run directly from the command-line/shell (which implies you'll need to adapt them slightly if running them in the context of a web-server-side script). To give a simple example:

<?php
include("apez-api.php");

$name = "Secret2 Linden";

list($ok, $akey) = general_getAvatarKey($name);

if ($ok) echo "Secret2's key is $akey \n";

?>

Most of the PHP wrapper functions return an array with two elements: the first is a success code (a boolean) and the second is the actual return value. So, it is common to call functions like this:

list($ok, $balance) = bank_accountBalance($capabilities, $akey, "working");
if ($ok)
  echo "Balance is $balance \n";
else
  print_r($balance); // display error

If an error occurs, the Apez server returns a standard XMLRPC fault, which gets translated into a PHP array containing the faultCode and an error string. One important thing to note is that PHP doesn't allow the period "." character in function names, so it is replaced with an underscore "_" in the client library. Hence general.getAvatarKey becomes general_getAvatarKey in PHP code.


API Function Reference

The function reference is divided into sections according to the Apez service being documented (e.g. bank, lease, vend etc.). However, the general functions are documented first.

General

Utility



general.getAvatarKey(public,SL)

Get UUID/key associated with an avatar's name

Parameters:

avatar_name (string)

Returns: (string) The key if the named avatar is known to the Apez database, or an error.

Notes: If an avatar's name isn't know to the Apez database, ask them to touch an ATM, interact with an Apez device or register.



general.getAvatarName(public,SL)

Get an avatar's name from their key

Parameters:

akey (string)

Returns: (string) The avatar name of the given avatar key if it is known to the Apez database, or an error.

Notes: If an avatar's name isn't know to the Apez database, ask them to touch an ATM, interact with an Apez device or register.



general.siteStatus(public,SL)

The status of Apez services

Parameters:

None

Returns: (array) An array of two bool values indicating if the Apez system is connected to the SL grid and if the site is up (respectively)


Login



general.login(public,PHP-only)

Returns a login capability for the specified avatar and Apez site password. The capability can be passed in the capabilities array of all functions that require login authentication. The capability returned will only be valid for the number of seconds specified. Since anyone obtaining this string can access API functions with full capabilities, it should be kept secure.

Parameters:

akey (string) - SL key of avatar to attempt login for
password (string) - Apez site password (not sent over the connection)
valid_for_secs (int) - Number of seconds the login capability should be valid for.

Returns: (string) Login capability for the specified avatar and Apez site password, or the empty string if the login fails.

Notes: PHP convenience function ONLY. This isn't an Apez API function, but a convenience wrapper for the two functions below. It calls the them with the appropriate challenge response - so the password argument is never actually sent to the Apez server over the Internet.



general.getLoginChallenge(public)

Authenticating with the server ('logging in' / 'obtaining login capability') is a two-step process in order to avoid sending your password over the Internet. First, this function is called, which returns a login challenge string for the avatar. Then, this challenge must be combined with the Apez site password, MD5 hashed, and the hash passed to the function below to obtain the actual login capability string. Being able to generate the correct response to the challenge proves that the correct password is known.

Parameters:

akey (string) - UUID/key of the SL avatar to attempt login for.

Returns: (string) The challenge for the specified avatar to be passed to the function below




general.getLoginCapability(public)

The challenge_response is computed from the challenge returned by general_getLoginChallenge() according to the following experssion:

challenge_response = md5( challenge+akey+md5(password) ) where md5() is the standard MD5 hash function and "+" represents string concatenation.

Parameters:

akey (string) - UUID/key of the SL avatar to attempt login for.
challenge_response (string) - Value computed using the expression above.
valid_for_secs (int) - Number of seconds the login capability should be valid for.

Returns: (string) Login capability string that can be passed to any API function that requires login capability.

Notes: The PHP library contains the general.login() above which implements this two-step sequence in a single function call.



general.getAvatarLoginCapability(public,in-world-only)

Returns a login capability for the owner of the in-world object in which the calling script is contained. Note that the password is sent from the grid sim machine over the internet to the Apez service (unfortunately: due to the fact that LSL doesn't have a plain MD5 hash function, only one that appends a string).

Parameters:

password (string) - Apez site password of the avatar who owns the object making the call.
valid_for_secs (int) - Number of seconds the login capability should be valid for.

Returns: (string) Login capability for the owner of the in-world object in which the calling script is contained.

Notes: LSL convenience function; API function NOT available in PHP client library. This function can be ONLY be called from in-world LSL scripts.


Groups



general.listGroupsCreated(public)

List the groups created by the specified agent

Parameters:

capabilities ([string*]) - Array of capabilities
groups_creator_key_or_name (string) - The agent name or key of the creators of the groups to be listed
groups_creator_agent_realm (string) - The realm for the creator agent (empty for auto)
format (string) - Either "array" or "csv"
offset (int) - Offset into groups list for which sublist should be returned
limit (int) - Maximum number of groups to return or -1 for unlimited

Returns: (string or [ [group_key:string,group_name:string]* ]) If format is "array" returns an array of pairs (2-element array) of the group key and text name. If format is "csv" a single string is returned with the group keys and names in sequence separated by commas.

Notes: A capability granting access to the creator's Apez groups must be supplied. If called from LSL and too many groups are requested, the HTTP response may be truncated by the sim yielding an invalid response.



general.isGroupmember(public)

Check if an agent is a member of a specific group

Parameters:

capabilities ([string*]) - Array of capabilities
group_creator_key_or_name (string) - Name or key of group creator (can be empty if group key specified)
group_creator_agent_realm (string) - Realm for group_creator_key_or_name (empty for auto)
group_key_or_name (string) - Name of group created by group_creator_key_or_name or group key
member_key_or_name (string) - Name or key of agent to test group membership for
member_agent_realm (string) - Realm for member_key_or_name (empty for auto)

Returns: (int) True/1 if member is actually a member of the specified group or fault on error.

Notes: A capability granting access to the creator's Apez groups must be supplied.



general_listGroupMembers(public)

Access list of group members (including keys and group percentages).

Parameters:

capabilities ([string*]) - Array of capabilities
group_creator_key_or_name (string) - Name or key of group creator (can be empty if group key specified)
group_creator_agent_realm (string) - Realm for group_creator_key_or_name (empty for auto)
group_key_or_name (string) - Name of group created by group_creator_key_or_name or group key
format (string) - Either "array" or "csv"
offset (int) - Offset into member list for which sublist should be returned
limit (int) - Maximum number of members to return or -1 for unlimited

Returns: (string or [ [group_key:string,group_name:string]* ]) If format is "array" returns an array of triples (3-element array) of the member agent key, name and assigned percentage. If format is "csv" a single string is returned with the member keys, names and percentages in sequence separated by commas.

Notes: A capability granting access to the creator's Apez groups must be supplied. If the group doesn't have the use percentages option enabled online the percentages may be meaningless and should be ignored.



general.addToGroup(public)

Add an agent to an Apez group (or update their percentage and status)

Parameters:

capabilities ([string*]) - Array of capabilities
group_creator_key_or_name (string) - Name or key of group creator (can be empty if group key specified)
group_creator_agent_realm (string) - Realm for group_creator_key_or_name (empty for auto)
group_key_or_name (string) - Name of group created by group_creator_key_or_name or group key
new_member_key_or_name (string) - Name or key of agent to add to the group
new_member_agent_realm (string) - Realm for new_member_key_or_name (empty for auto)
new_member_percent (float) - Group percentage (e.g. for share payments when group used for sharing), or -1 for auto (initially assigned 1/numer_members ratio)
new_member_as_officer (int) - If 1 the member becomes an officer of the group, if 0 a regular member

Returns: either "added" or "updated" depending on if the agent was already a member of the group (in which case the percentage and status is updated)

Notes: A capability granting access to the creator's Apez groups must be supplied. If the assigned percentage causes the total percentage for all members in the group summed to be no equal to 100%, all members percentages are scaled to maintain the same relative ratios so that the total sum is 100%.



general.removeFromGroup(public)

Remove an agent from an Apez group.

Parameters:

capabilities ([string*]) - Array of capabilities
group_creator_key_or_name (string) - Name or key of group creator (can be empty if group key specified)
group_creator_agent_realm (string) - Realm for group_creator_key_or_name (empty for auto)
group_key_or_name (string) - Name of group created by group_creator_key_or_name or group key
member_key_or_name (string) - Name or key of agent to remove from the group
member_agent_realm (string) - Realm for member_key_or_name (empty for auto)

Returns: (string) Either "ok", "notmember" or "onlyofficer" or a fault if a unexpected failure occurred.

Notes: A capability granting access to the creator's Apez groups must be supplied. You cannot remove the only remaining officer in a group. Groups always have at minimum one member who is an officer.

Bank



bank.accountBalance(public)

Balance of named account

Parameters:

capabilities ([string*]) - array of capabilities
akey (string) - Key of agent who owns the account
account_name (string) - Name of the account (e.g. "working")

Returns: (float) Account balance of akey's named account. The amount represents the currency in which the account is denominated

Notes: Requires a capability giving the login agent read access to the specified account



bank.accountList(public)

Obtain agent's accounts (by name)

Parameters:

capabilities ([string*]) - array of capabilities
akey (string) - Key of agent who owns the accounts to be returned

Returns: ([string*]) Array of account names owned by akey

Notes: Requires a capability giving the login agent read access to the specified account



bank.transfer(public)

Transfer an amount from one account to another owned by the same agent

Parameters:

capabilities ([string*]) - array of capabilities
akey (string) - Key of agent who owns the accounts
amount (int) - Amount to transfer (in currency in which accounts are denominated)
from_account_name (string) - The name of the source account owned by akey
to_account_name (string) - The name of the target account owned by akey
comment (string) - A comment for the transfer (which will be displayed in the transaction logs for both accounts). Limited to 64 characters.

Returns: (string) Transaction ID of the transaction if sucessful or a fault if there were insufficient funds in the from_account.

Notes: Requires a capability granting the login agent modify access to both of the accounts. Both accounts much be denominated in the same currency.



bank.pay(public)

Pay an amount from one account to another account (or avatar). Requires the login agent to supply either bank full-access capabilities for the from_akey avatar, or modify capability on the from account (except if own account). If no particular capabilities are supplied for the to_akey avatar's account, the to_account_name will be ignored and the payment will be made into to_akey's working account - *except* if to_account_name is 'avatar', in which case the payment is dispensed in-world instead (also useful for making withdrawals), or either to_account has public deposit enabled or from_akey is a member of the account deposit auth group. If the to_akey avatar doesn't have an Apez account at all (i.e. no login), the funds are dispensed in-world.

Parameters:

capabilities ([string*]) - array of capabilities
amount (int) - Amount to transfer (in currency in which from_account is denominated)
from_akey (string) - agent who owns from_account
from_account_name (string) - Name of source account owned by from_akey
to_akey (string) - agent who owns from_account
to_account_name (string) - Name of source account owned by from_akey
comment (string) - A comment for the payment (which will be displayed in the transaction logs for one or both accounts). Limited to 64 characters.
notify (int) - If notify is 1/true, the to_akey avatar will be notified of the payment.

Returns: (string) Transaction ID of the payment on success or a fault on failure (insufficient funds available in the from account, or the payment cannot be dispensed (e.g. for in-world payents)).




bank.grantAllAccountsFullCapability(public)

Creates a capability that grants avatar 'auth_akey' full access to all accounts of the login agent.

Parameters:

capabilities ([string*]) - array of capabilities
auth_akey (string) - The key of the avatar who is to be authorized for account access
valid_for_secs (int) - Number of seconds the returned capability with be valid for.

Returns: (string) Capability, which when used by auth_akey in conjunction with their login capability, will allow balance query, inter-account transfers and payments from login cap avatar's accounts).

Notes: Use the returned capability with caution as it will allow any auth_key to enumerate and withdraw all funds from the login agent's accounts.



bank.grantAllAccountsReadCapability(public)

Creates a capability that grants avatar 'auth_akey' read-only access to all accounts of the login agent.

Parameters:

capabilities ([string*]) - array of capabilities
auth_akey (string) - The key of the avatar who is to be authorized for account access
valid_for_secs (int) - Number of seconds the returned capability with be valid for.

Returns: (string) Capability, which when used by auth_akey in conjunction with their login capability, will allow balance query and transaction history access of login cap avatar's accounts.



Lease



lease.stats(public)

Overall lease statistics (all locations); such as total number of spaces, number leased, number vacant and number overdue.

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who's lease statistics are being queried

Returns: ([total:int, leased:int, vacant:int, overdue:int]) Single array of statistics. Requires login capability by for owner or lease capability granting access to owner's locations.




lease.locationStats(public)

Lease statistics for a specific lease-location; such as total number of spaces, number leased, number vacant and number overdue.

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who's lease statistics are being queried
location_name (string) - Name of lease-location owned by owner_akey (e.g. "Shops")

Returns: ([total:int, leased:int, vacant:int, overdue:int]) Single array of statistics. Requires login capability by for owner or lease capability granting access to owner's locations.




lease.regionStats(public)

Lease statistics for all owner's spaces in a specific region (sim); such as total number of spaces, number leased, number vacant and number overdue.

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who's lease statistics are being queried
region (string) - Name of region (sim) in which spaces much be positioned to be included

Returns: ([total:int, leased:int, vacant:int, overdue:int]) Single array of statistics. Requires login capability by for owner or lease capability granting access to owner's locations.





lease.locationNames(public)

Lease location names owned by specific agent.

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who's lease location-names are being queried

Returns: ([string*]) Single array of location-names. Requires login capability by for owner or lease capability granting access to owner's locations.




lease.unitNamesAtLocation(public)

Space/Lease names in specific lease-location.

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who owns lease-location being queried
location_name (string) - Name of lease-location owned by owner_akey
offset (int) - Offset of index into array of names to return (optional; default 0)
limit (int) - Maximum number of unit names to return (optional; default -1 - no limit)
format (string) - Either 'std' or 'compact' (optional; default 'std')

Returns: ([string*]) Single array of space-names if format is 'std' or single string of comma separated names if format is 'compact'. Requires login capability by for owner or lease capability granting access to owner's locations. If an auto-lease unit is associated with a space/lease, this is the object name of the auto-lease unit itself.




lease.unitDetailsAtLocation(public)

Get detailed information about spaces/leases in a given lease-location.

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who owns lease-location being queried
location_name (string) - Name of lease-location owned by owner_akey
offset (int) - Offset of index into array to return (optional; default 0)
limit (int) - Maximum number of unit detail elements to return (optional; default -1 - no limit)
format (string) - Either 'std' or 'compact' (optional; default 'std')

Returns: ([ [unit_name:string, model:string, region_coords:string, is_leased:int, leased_akey:string, lease_name:string, week_rate:int,secs_remaining:int]* ]) An array of detail information for each space in the location, each of which is an array if format is 'std'. If format is 'compact' returns a single string of "

Notes: Requires capability granting agent access to owner's lease information (either login capability for owner or someone in owner's lease location management group, or a lease capability for the owners lease locations). Although the time remaining is given in seconds, Auto-Lease models v2.x only have 1day resolution.



lease.unitDetailsByName(public)

Space/lease details at given location-name and with given unit/object name (single space)

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who owns lease-location containing the named space
location_name (string) - Name of lease-location owned by owner_akey
unit_name (string) - Unit (space/lease) name within the named location owned by owner_akey
format (string) - Either 'std' or 'compact' (optional; default 'std')

Returns: ([unit_name:string, model:string, region_coords:string, is_leased:int, leased_akey:string, lease_name:string, week_rate:int, secs_remaining int]) Details for the specified space as array if format is 'std' or a single string of comma separated values if the format is 'compact'. If is_leased is 0/false, then leased_akey and leased_name are blank.

Notes: Requires capability granting agent access to owner's lease information (either login capability for owner or someone in owner's lease location management group, or a lease capability for the owners lease locations). Although the time remaining is given in seconds, Auto-Lease models v2.x only have 1day resolution.



lease.unitDetailsByNumber(public)

Space/lease details at given location name and with given unit/object index number (single space)

Parameters:

capabilities ([string*]) - array of capabilities
owner_akey (string) - Key of agent who owns lease-location containing the specified space
location_name (string) - Name of lease-location owned by owner_akey
unit_number (int) - Unit (space/lease) number within the named location owned by owner_akey. The unit index number is the number after the "#" character in the unit/object name. If the number isn't unique only the first match is returned.
format (string) - Either 'std' or 'compact' (optional; default 'std')

Returns: ([unit_name:string, model:string, region_coords:string, is_leased:int, leased_akey:string, lease_name:string, week_rate:int, secs_remaining int]) Details for the specified space as array if format is 'std' or a single string of comma separated values if the format is 'compact'. If is_leased is 0/false, then leased_akey and leased_name are blank.

Notes: Requires capability granting agent access to owner's lease information (either login capability for owner or someone in owner's lease location management group, or a lease capability for the owners lease locations). Although the time remaining is given in seconds, Auto-Lease models v2.x only have 1day resolution.



lease.logs(public)

Fetch lease log entries between given time range at specified lease location name.

Parameters:

count_limit (int) - Number of entries returned (max 100)
owner_akey (string) - Key of agent who owns lease-location named
location_name (string) - Name of lease-location owned by owner_akey

Returns: ([ [time:string, type:string, owner_akey:string, unit_object_name:string, location_name:string, agent_key:string, agent_name:string, amount:int, duration_secs:int] ]*) Array of lease log entries. Entry members are:

  • time is the date/time stamp when the log was recorded (UTC/GMT), e.g. "2006-10-23 03:08:00Z"
  • type is one of new,extend,terminated or expire
  • the agent_akey and agent_name is the key/name of the lease holder / tenant
  • amount is the $L amount if applicable (e.g. for extensions or new leases)
  • duration_secs is the duration is applicable (e.g. for new leases, extensions)

Notes: Requires capability granting agent access to owner's lease information (either login capability for owner or someone in owner's lease location management group, or a lease capability for the owners lease locations).

Vend



vend.collectionNames(public)

Get product collection names created by specified agent.

Parameters:

capabilities ([string*]) - array of capabilities
creator_akey (string) - Agent key of the creator of the collections to be returned

Returns: ([string*]) Array of product collection names

Notes: Requires a capability granting access to the product collections of creator_akey.



vend.productsInCollection(public)

get product IDs in the specified collection.

Parameters:

capabilities ([string*]) - array of capabilities
collection_creator_akey (string) - Agent key of the creator of the named collection
collection_name (string) - Name of a product collection owned by collection_creator_akey

Returns: ([int*]) Array of product IDs

Notes: Requires a capability granting access to the specified product collection.



vend.publicCollections(public)

List public product collection details

Parameters:

capabilities ([string*]) - array of capabilities
offset (int) - Offset index into list of public collections
limit (int) - Max number of collections returned

Returns: ([ {name:string, merchant:string, merchant_akey:string, desc:string, seller_commission:float, image_url_part:string, texture_key:string, rating:float, tags:string}* ]) Array of product collection details, where each is a dict/map of named properties.

Notes: Requires login capability.



vend.publicCollectionProducts(public)

Get public product information for the specified public collection

Parameters:

capabilities ([string*]) - array of capabilities
merchant (string) - Merchant (creator) key of named collection
merchant_realm (string) - Realm of merchant (or empty for auto)
collection_name (string) - Name of public collection owned by merchant
offset (int) - Offset index into list of products
changes_since_unixtime (int) - Only return products modified/added/deleted since given Unix time (secs since epoch). Pass 0 for all.

Returns: ([ {prod_id:int, name:string, short_desc:string, creator:string, creator_akey:string, cats:[string+], tags:string, rating:float, total_votes:int, price:float, currency:string, image_url_part:string, texture_key:string, is_mature:int, vendors:[{owner_akey:string, owner_name:string, position:string, mature_region:bool}*] }* ]) An array of products. Each product is a dict/map of properties. The cats property is in-turn an array and the vendors property is another dict/map (where the merchant's vendors are listed first).

Notes: Requires login capability.



vend.publicCollectionProductsDeleted(public)

Get list of products deleted from specified public collection

Parameters:

capabilities ([string*]) - array of capabilities
merchant (string) - Merchant (creator) key of named collection
merchant_realm (string) - Realm of merchant (or empty for auto)
collection_name (string) - Name of public collection owned by merchant
offset (int) - Offset index into list of products
changes_since_unixtime (int) - Only return products deleted since given Unix time (secs since epoch).

Returns: ([ {prod_id:int, creator:string, creator_akey:string }* ]) An array of products that have been deleted. Each product is a dict/map of properties.

Notes: Requires login capability. Deleted products are not recorded indefinitely, so if a large amount of time has passed between the deletion and this call, the deleted product may not be listed. Currently, deleted products are recorded for 2 years.



vend.findProductsVendor(affiliate)

Find products matching search criteria.

Results will include any public product even if no capabilities are supplied. If capabilities for reading collections are supplied (or a login capability for the collection owner / merchant), results will also contain matches from those collections, even if they are otherwise private. Results will also contain matches from any collection for which the login agent is an affiliate seller group member (if a login capability is supplied).

Parameters:

capabilities ([string*]) - array of capabilities
search_string64 (string) - a base 64 encoded search string (currently treated as a single keyword/term. Support for space-separated terms is planned)
merchant_key (string) - restrict results to products by the supplied merchant. Pass the empty string to match any merchant.
include_mature (int) - 1 to match and products, 0 to match only PG/non-adult products. Always pass 0 for devices in PG sims.
orderby (string) - results sort order. An order word and one of "asc" or "desc" seperated by a hash (-), for example "sales-desc". Allowed ordering words are "sales","price","prims","name","created", "rating", "collection" and the special keyword "featured"
low_price (float) - Only match products equal to or greater than this in price (L$) - set to -1 not to filter
high_price (float) - Only match products equal to or less than this in price (L$) - set to -1 not to filter
offset (int) - The offset into the result set
limit (int) - maximum number of results to return. This must be <= 30.

Returns: (string) Single string including the count of matches and zero or more comma separated products (designed for easy parsing in-world). Each product is triple prod_id/texure_key/texture_anim_params (i.e. separated by a slash "/"). The texture_anim_param is "-" if the texture isn't animated, otherwise a set of standard anim parameters separated by "|". The texture_key may be empty or NULL_KEY for some products. For example: "3,1219:d6433103-f2e0-354d-4f8e-79cd53de5ae8:-,19240:64871c36-3dc1-f109-26f6-22e02356ce73:-,1002:a8b0e36b-66cb-f109-5f01-27d4abfa6113:-".


Examples

PHP client library examples

For convenience, a PHP client library that included an XML-RPC implementation and function wrappers around the Apez API functions is provided [here]. It also includes various PHP examples.

(NB: the API wrapper may not always be up-to-date as more functions are added to the API. If you discover a function you'd like to call that isn't included in the wrapper, please let us know. You can also create the wrapper yourself if necessary by following the form in the provided PHP file).

Querying Apez.bank account balances

<?php
include("apez-api.php");

$name = "ImSoCool Mann";
$password = "yourpasswordhere";


// Most of the API functions require an avatar key.  While it is more efficient
//  to hard-code or cache the key, you can look it up via the general_getAvatarKey()
//  API call, which doesn't require any authentication
list($ok, $akey) = general_getAvatarKey($name);
if (!$ok) {
  echo "Unknown avatar name ".$name."\n";
}
else {
  echo $name."'s key is ".$akey."\n";
  
  // Login to Apez server API (returns login capability)
  //  Ask for capability that will expire in 1 hour
  //  (NB: this is a convenience function that wraps 2 API functions 
  //      - neither the password or its hash are actually sent to the server [see the source])

  echo "Logging in...  ";
  $login_cap = general_login($akey, $password, 60*60);
  if ($login_cap != "") {
  
    echo "Got login capability:".$login_cap."\n";
    
    $capabilities = array($login_cap); // we only have/need one capability for now
    
    // Ask for the account balance on our "working" account 
    // (login capability is sufficient for access to our own accounts)
    list($ok, $balance) = bank_accountBalance($capabilities, $akey, "working");
    
    if ($ok)
      echo "Working balance is ".$balance."\n";
    else {
      echo "An error occured:";
      print_r($balance); // errors are always an array in the 2nd returned list elt if ok is false
    }
  }
  else
    echo "Login failed.\n";
}

?>

Query groups and add/remove members

<?php
include("apez-api.php");

//
// This script demonstrates how to list your Apez groups, list group members and add and remove
//  an avatar to/from a group.  It assumes you have at least one group created already.


$name = "YOUR AVATAR NAME";
$password = "YOUR APEZ PASSWORD";

$member_avatar = 'An avatar'; // name of avatar to add & remove from group for example


// Most of the API functions require an avatar key.  While it is more efficient
//  to hard-code or cache the key, you can look it up via the general_getAvatarKey()
//  API call, which doesn't require any authentication
list($ok, $akey) = general_getAvatarKey($name);
if (!$ok) {
  echo "Unknown avatar name ".$name."\n";
}
else {
  echo $name."'s key is ".$akey."\n";
  
  // Login to Apez server API (returns login capability)
  //  Ask for capability that will expire in 1 hour
  //  (NB: this is a convenience function that wraps 2 API functions 
  //      - neither the password or its hash are actually sent to the server [see the source])

  echo "Logging in...  ";
  $login_cap = general_login($akey, $password, 60*60);
  if ($login_cap != "") {
  
    echo "Got login capability:".$login_cap."\n";
    
    $capabilities = array($login_cap); // we only have/need one capability for now
    
    // Ask for the list of groups we created 
    // (login capability is sufficient for access to our own accounts)
    list($ok, $groups) = general_listGroupsCreated($capabilities, $akey, '');

    if ($ok) {
      // returns an array of key,name pairs for the groups
      echo count($groups)." groups\n";
      for($i=0; $i<count($groups); $i++) {
        echo $groups[$i][1]." [".$groups[$i][0]."]\n";
      }
    }
    else {
      // errors are always an array in the 2nd returned list elt if ok is false
      echo "An error occured:".print_r($groups,true)."\n";
      return;
    }

    // add an avatar to the first group in the list    
    list($ok, $rsp) = general_addToGroup($capabilities, $akey, '', $groups[0], $member_avatar, '', -1);
    if ($ok) {
      echo "\nResult of adding avatar to group '".$groups[1]."':".$rsp."\n";
    }
    else {
      // errors are always an array in the 2nd returned list elt if ok is false
      echo "An error occured adding avatar:".print_r($rsp,true)."\n";
      return;
    }
    
    // check the avatar is a member of the group
    list($ok, $rsp) = general_isGroupMember($capabilities, $akey, '', $groups[0], $member_avatar, '');
    if ($ok) {
      echo "\nResult of is member for group '".$groups[1]."':".$rsp."\n";
    }
    else {
      // errors are always an array in the 2nd returned list elt if ok is false
      echo "An error occured while querying membership:".print_r($rsp,true)."\n";
      return;
    }

    
    // list group members    
    list($ok, $members) = general_listGroupMembers($capabilities, $akey, '', $groups[0]);
    if ($ok) {
      echo "\nMembers of group '".$groups[1]."':\n";
      for($i=0; $i<count($members); $i++)
        echo $members[$i][1]." ".$members[$i][2]."%  [".$members[$i][0]."]\n";
    }
    else {
      // errors are always an array in the 2nd returned list elt if ok is false
      echo "An error occured listing group members:".print_r($rsp,true)."\n";
      return;
    }

    
    
    // remove avatar from the group again    
    list($ok, $rsp) = general_removeFromGroup($capabilities, $akey, '', $groups[0], $member_avatar, '');
    if ($ok) {
      echo "\nResult of removing avatar from group '".$groups[1]."':".$rsp."\n";
    }
    else {
      // errors are always an array in the 2nd returned list elt if ok is false
      echo "An error occured removing avatar:".print_r($rsp,true)."\n";
      return;
    }
    
    
  }
  else
    echo "Login failed.\n";
}

?>


LSL Examples

Avatar key from name lookup

// Apez Corp Example LSL script 
// This script is hereby placed in the public domain.
//
// {"obj":"Apez DevKit", "ver":"1.1", "src":"devkit/Apez-name2key-example.lsl"}
// $Revision$

//
// This is an example of how to use the Apez Affiliate Services API
// Make sure the Apez scripts are in the same prim as the script containing
//  your code (like this example).
//
//
// Simple example of using the Apez XMLRPC web service API to obtain
//  and avatar UUID/key from their name



// See below for an example of what you need to implement.  The functions immediately
//  below here are the functions you can call (no need to worry about what's in them)

// Apez Link messgae numbers
integer ApezUserAPINum = 4590;


// Call this function to call any Apez API function
apezCall(list capabilities, string funcName, list params)
{
    llMessageLinked(LINK_THIS, ApezUserAPINum, llDumpList2String(["call",funcName,
                        llDumpList2String(capabilities,"#")]+params,"::"),"");
}



requestKey(string avatar_name)
{
    // general.getAvatarKey(name,realm)
    apezCall([], "general.getAvatarKey", [avatar_name,""]);
}




//string avatar_name = "Governor Linden";
string avatar_name = "Secret2 Linden";

default
{
    state_entry()
    {
        llSay(0,llGetScriptName()+": Touch to query key for avatar "+avatar_name);
    }


    touch_start(integer total_number)
    {
        requestKey(avatar_name);
    }
    
    

    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == ApezUserAPINum) {
            list reply = llParseStringKeepNulls(str,["::"],[]);
            string rsp = llList2String(reply,0);
            
            if (rsp == "general.getAvatarKey-rsp") { 
                string akey = llList2String(reply,1);
                
                llSay(0,"The key for avatar "+avatar_name+" is "+akey);
            }
        }
    }    
}

Apez.bank account balance

// Apez Corp Example LSL script 
// This script is hereby placed in the public domain.
//
// {"obj":"Apez DevKit", "ver":"2.0", "src":"devkit/Apez-balance-example.lsl"}
// $Revision$


//
// This is an example of how to use the Apez Affiliate Services API
// Make sure the Apez scripts are in the same prim as the script containing
//  your code (like this example).
//

// See below for an example of what you need to implement.  The functions immediately
//  below here are the functions you can call (no need to worry about what's in them)

// Apez Link messgae numbers
integer ApezUserAPINum = 4590;

// Call this function to cause a pop-up dialog to ask for Apez account login permissions
//  The capability returned gives full access to the owners Apez functions
//  (note, it might not actually need to ask again, if the pop-up was answered Yes
//   previously and the script hasn't reset or changed owner since)
// *Currently the capability expires after 24hours, so should be re-requested before then*
apezGetAvatarLoginCapability()
{
    llMessageLinked(LINK_THIS, ApezUserAPINum, "login", llGetOwner());
}


// Call this function to call any Apez API function
apezCall(list capabilities, string funcName, list params)
{
    llMessageLinked(LINK_THIS, ApezUserAPINum, llDumpList2String(["call",funcName,
                        llDumpList2String(capabilities,"#")]+params,"::"),"");
}






//
// Example of your code
//

integer gotApezLoginCapability = FALSE;
string login_cap = "";


// On reset, this will ask for login permission.
//  Then when touched, it will fetch the owner's working account balance


default
{
    state_entry()
    {
        llOwnerSay(llGetScriptName());
        
        llSleep(2); 

        if (!gotApezLoginCapability)
            apezGetAvatarLoginCapability();
    }

    on_rez(integer passed)
    {
        llResetScript(); // just in case the owner is new,
                         //  better reset to ask them permission
    }
    

    touch_start(integer total_number)
    {
        key touchedBy = llDetectedKey(0);
        
        llSay(0,llGetScriptName()+": Hello "+llKey2Name(touchedBy)+", querying you account balance...");
        
        apezCall([login_cap], "bank.accountBalance", [llGetOwner(), "working"]);                
    }
    
    
    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == ApezUserAPINum) {
            list reply = llParseStringKeepNulls(str,["::"],[]);
            string rsp = llList2String(reply,0);
            
            if (rsp == "login-rsp") { // got response to login cap request
                login_cap = llList2String(reply,1);
                if (login_cap != "denied") {
                    llOwnerSay("Apez account login permission granted");
                    gotApezLoginCapability = TRUE;
                    
                    llSay(0,"Touch me to display your working account balance");
                    
                }
                else {
                    llOwnerSay("Apez account login permission NOT granted");
                    gotApezLoginCapability = FALSE;
                }
            }
            else if (rsp == "bank.accountBalance-rsp") { // got reponse to balance enquiry
                integer balance = llList2Integer(reply,1);
                
                llSay(0,"Your working account balance is "+(string)balance);
            }
        }
    }
}

Group and membership query example

// Apez Corp Example LSL script 
// This script is hereby placed in the public domain.
//
// {"obj":"Apez DevKit", "ver":"2.0", "src":"devkit/Apez-groups-example.lsl"}
// $Revision$


//
// This is an example of how to use the Apez Affiliate Services API
// Make sure the Apez scripts are in the same prim as the script containing
//  your code (like this example).
//

// See below for an example of what you need to implement.  The functions immediately
//  below here are the functions you can call (no need to worry about what's in them)

// Apez Link messgae numbers
integer ApezUserAPINum = 4590;

// Call this function to cause a pop-up dialog to ask for Apez groups permission
//  The capability returned gives full access to the owners Apez groups (including modify rights)
//  (note, it might not actually need to ask again, if the pop-up was answered Yes
//   previously and the script hasn't reset or changed owner since)
// *Currently the capability expires after 24hours, so should be re-requested before then*
apezGetAvatarGroupsCapability()
{
    llMessageLinked(LINK_THIS, ApezUserAPINum, "groupscap", llGetOwner());
}


// Call this function to call any Apez API function
apezCall(list capabilities, string funcName, list params)
{
    llMessageLinked(LINK_THIS, ApezUserAPINum, llDumpList2String(["call",funcName,
                        llDumpList2String(capabilities,"#")]+params,"::"),"");
}






//
// Example of your code
//

integer gotApezGroupsCapability = FALSE;
string groups_cap = "";


// On reset, this will ask for groups permission.
//  Then when touched, it will fetch the owner's list of Apez groups


default
{
    state_entry()
    {
        // if we don't already have a groups capability for the owner's Apez groups,
        //  call the ApezPermissions script to ask for one (which causes a permission
        //  pop-up menu to be displayed to the owner)
        if (!gotApezGroupsCapability)
            apezGetAvatarGroupsCapability();
    }

    on_rez(integer passed)
    {
        llResetScript(); // just in case the owner is new,
                         //  better reset to ask them permission
    }
    

    touch_start(integer total_number)
    {
        key touchedBy = llDetectedKey(0);
        
        llSay(0,llGetScriptName()+": Hello "+llKey2Name(touchedBy)+", querying your group list...");
        
        // general.listGroupsCreated(caps,groups_creator_key_or_name,groups_creator_agent_realm,
        //                           format,offset,limit)
        apezCall([groups_cap], "general.listGroupsCreated", [llGetOwner(), "","csv",0,-1]);
    }
    
    
    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == ApezUserAPINum) {
            list reply = llParseStringKeepNulls(str,["::"],[]);
            string rsp = llList2String(reply,0);
            
            if (rsp == "groupscap-rsp") { // got response to groups cap request
                groups_cap = llList2String(reply,1);
                if (groups_cap != "denied") {
                    llOwnerSay("Apez groups permission granted");
                    gotApezGroupsCapability = TRUE;
                    
                    llSay(0,llGetScriptName()+": Touch me to list your Apez groups");
                    
                }
                else {
                    llOwnerSay("Apez groups permission NOT granted");
                    gotApezGroupsCapability = FALSE;
                }
            }
            else if (rsp == "general.listGroupsCreated-rsp") { // got reponse to group list query
                // result is a list of group_key,name pairs in a flat array as CSV
                list group_key_names = llCSV2List( llList2String(reply,1) );
                if (llGetListLength(group_key_names) > 1) {
                    integer i=0;
                    for(i=0;i<llGetListLength(group_key_names); i+=2) {
                        llSay(0,llList2String(group_key_names,i+1)+" ["+llList2String(group_key_names,i)+"]");
                    }                
                    llSay(0,"----");
                    
                    // request member list for first group in list (if any)
                    string group_key = llList2String(group_key_names,1);
                    string group_name = llList2String(group_key_names,0);
                    llSay(0,"Requesting membership list for group "+group_name);
                    
                    // general_listGroupMembers(caps,group_creator_key_or_name,group_creator_agent_realm,
                    //                          group_key_or_name,format,offset,limit)
                    apezCall([groups_cap], "general.listGroupMembers", [llGetOwner(), "",group_key,"csv",0,-1]);
                }
                else
                    llSay(0,"You're not a member of any Apez groups");
            }
            else if (rsp == "general.listGroupMembers-rsp") { // got reponse to group member query
                // result is a list of avatar_key,name,percent triples in a flat array as CSV
                list group_members = llCSV2List( llList2String(reply,1) );
                integer i=0;
                for(i=0;i<llGetListLength(group_members); i+=3) {
                    llSay(0,llList2String(group_members,i+1)+" ["+llList2String(group_members,i)+"]  "
                                +llList2String(group_members,i+2)+"%");
                }
            }
            
        }
    }
}
Personal tools

A d v e r t i s m e n t