External Access API
The External Access API allows commands to be issued into the system from an external server or service. The External Access system has a large quantity of access to users and user data.
You will require a Developer Key to be issued to your user account, contact Iain Maltz for this, and any instance you wish to interact with must grant your avatar external connection access to their instance
Note: This functionality has been simply “bolted on” to the existing infrastructure (Commands, Responses, etc) which made it a lot easier to implement and will stay “current” as an API going forwards (since it uses the core published API). If you need additional functionality it's probably quite easy to add and should be requested. Some responses may be useful to expand (e.g. awarding XP returns the current number of XP afterwards, or the ammount available, or when available, as a separate JSON element), and in other cases (interrogating information) custom JSON Response commands can be created (see the end).
Acceptable Use Policy
- No repeating or fully autonomous polling - Requests to the API must be generated in direct response to user action, there should be no “regular” polling of any kind and certainly no external implementation of timers that poll things regularly. Things like e.g. health regeneration mechanisms are not allowed due to the ammount of traffic generated. All developer keys are logged for every access, the number of accesses and the total bytes throughput.
- No data scraping/exports - Do not use the API to enumerate all characters or all data of a particular type, the “request by request” model is pretty inefficient for this process. If you need access to a full export of any data please get in contact. This limitation has more to do with utilisation limitation and bandwidth usage.
I'm sure there's more to write here
Accessing the external API
All requests must be presented over HTTPS to the URL https://sl.coagulate.net/GPHUD/external and are JSON formatted POST blocks/responses. Each request has the following common fields:
developerkey
' (String), the developer key assigned to you (seeExternal.GetDeveloperKey
)runasinstancename
(String), the name of the instance to run asrunasinstanceid
(Integer), the ID of the instance to run asrunasavatarname
(String) the “full avatar name” OR UUID to set as the “invoking (calling) avatar”runasavatarid
(Integer) the “internal avatar ID” to set as the “invoking (calling) avatar”. Takes precedence over the name (but still don't specify both, wastes time).runascharactername
(String)runascharacterid
(Integer)command
(String) the name of the API command to callcheckavatarpermission
(String) UUID (preferably) or Avatar Name to check (see below)
Some fields are mandatory, some are optional, some you must complete one or the other.
- You MUST set the developerkey
- You MUST set one of runasinstancename or runasinstanceid, it's likely you'll prefer to use the name form.
- You MAY supply runasavatarname or runasavatarid, they are optional and if not supplied will default actions to the (fake) SYSTEM avatar.
- You MAY supply a runascharactername or runascharacterid but not all commands require an active character - if the command has an Operating Context of AVATAR then no character needs to be specified. See Introspection/API web page.
- You MUST supply a command.
- You MAY supply a checkavatarpermission, this will take the avatar UUID or name and ensure they have been granted the permission
External.ConnectObjects
, this can be used where you have privileged in-world objects that would benefit from making use of GPHUD's access controls. An instance owner will have all permissions and thus this permission by default, and the instance owner can grant/revoke it from other avatars, for their instance only, at their leisure.
If the checkAvatarPermission field is not supplied, no check against External.ConnectObjects
will be made, this is the typical use case for the External interface where it assumed that authorisation and authentication have been performed by the external system. If the avatar passed in the checkavatarpermission field does not have the External.ConnectObjects
permission an Error response will be returned of responsetype UserException with error class “ExternalInterfaceObjectAccessDeniedException” (see example below)
Note that permissions checks are “normally” enforced, that is, if you try “runasavatar” a command that user doesn't have permissions for, you will get a permissions error. The SYSTEM user has full access to all permissions, so this may be appropriate for administrative operations.
Example accesses
In these examples (against the Development environment) we use “curl” to do the simple HTTP POST/Response part ; you probably want a JSON API and a HTTPS library for your own applications.
Responses can be distinguished by their “responseType”, so an OKResponse signifies success and probably contains a “message”, an ErrorResponse should contain an “error”.
Terminate Response
If you botch the request badly you may be given a “terminate” string response ; this indicates you should discontinue your queries until you resolve the (otherwise permanent) failure, e.g. an incorrect developer key
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test2" , "applicationname":"Demo Application" , "command":"external.status" , "runascharactername":"test989" , "runasinstanceid":15 }'
Response:
{ "terminate": "Developer key is not known", "responsetype": "TerminateResponse" }
Exception Reports
If something internally fails with an error inside GPHUD, and the error is of a “User” nature, it will be reported as an error string along with the class of the error. For “System” errors you'll only get the generic “Sorry, an internal error occured!” message. All exception reports are logged to developers for their review, and eventually some Exception cases are downgraded to Error cases once they're considered suitably normal.
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkeyy":"test" , "applicationname":"Demo Application" , "command":"external.status" , "runascharactername":"test989" , "runasinstanceid":15 }'
Response
{ "errorclass": "UserInputEmptyException", "error": "No developer credentials were supplied in the request", "responsetype": "UserException" }
If you are using the checkAvatarPermission field, you may get an access denied error, which you can use to tell the invoking user to go away (shut their connection, etc), it can be identified by the unique error class “ExternalInterfaceObjectAccessDeniedException” e.g.
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test" , "applicationname":"Demo Application" , "runasinstanceid":15 , "command":"experience.award" , "target":"iain" , "type":"xp" , "ammount":"1" , "reason":"Demonstration only" , "checkavatarpermission":"kate burner"}'
Response
{ "errorclass": "ExternalInterfaceObjectAccessDeniedException", "error": "User Kate Burner does not have permission External.ConnectObjects at instance DEV Test[#15]", "responsetype": "UserException" }
Error Message
Sometimes operations fail for non-exceptional reasons, in this case just an “error” message would be returned. These are not mailed to developers as they're user induced errors rather than anything failing.
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test" , "applicationname":"Demo Application" , "runascharactername":"test989" , "runasinstanceid":15 , "command":"experience.award" , "target":"test989" , "type":"xp" , "ammount":"1" , "reason":"Demonstration only"}'
Response
{ "error": ">>> ERROR : award errored: \n--- This character has already reached their xp XP limit. They will next be eligable for a point in in 13h24m", "responsetype": "ErrorResponse" }
Successful Response
When an operation succeeds, most of the time you will just get a “message” prefixed by OK, this is the standard response the HUD gives.
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test" , "applicationname":"Demo Application" , "runascharactername":"test989" , "runasinstanceid":15 , "command":"experience.award" , "target":"test989" , "type":"xp" , "ammount":"1" , "reason":"Demonstration only"}'
Response
{ "message": "OK : Awarded 1 xp to test989", "responsetype": "OKResponse" }
Or:
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test" , "applicationname":"Demo Application" , "command":"notes.avatar" , "runascharactername":"test989" , "runasinstanceid":15 , "target":"Iain Maltz" , "note":"This is a note from the external interface"}'
Response
{ "message": "OK : Admin only avatar note added.", "responsetype": "OKResponse" }
JSON Response
Finally, some commands, particularly those built explicitly for External connections, will return a full fledged JSON response, these are mostly interrogative commands:
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test" , "applicationname":"Demo Application" , "command":"external.status" , "runascharactername":"test989" , "runasinstanceid":15 }'
Response
{ "nodename": "Saturn", "environment": "DEVELOPMENT", "character": "test989[#163]", "instance": "DEV Test[#15]", "sourcename": "Demo Application", "avatar": "SYSTEM[#11]", "sourcedeveloper": "Kate Burner[#12769]", "responsetype": "JSONResponse", "sourceowner": "Kate Burner[#12769]" }
This command allows an avatar to be resolved into contextual information about their login:
curl https://sl.coagulate.net/GPHUD/external -d '{ "developerkey":"test" , "applicationname":"Demo Application" , "command":"external.lookupAvatar" , "user":"Iain Maltz" , "runasinstanceid":15 }'
Response
{ "avatarid": 1, "playingcharactername": "test", "avatarname": "Iain Maltz", "playingcharacterid": 103, "responsetype": "JSONResponse", "playingcharacterregion": "Cerasi", "playingcharacterzone": "goodies base" }
Or, if the avatar isn't currently detected as being logged in, you'll get an error from the Avatar→Character lookup:
{ "error": ">>> ERROR : lookupAvatar errored: \n--- Avatar Iain Maltz is not wearing the HUD or is not logged in as a character presently.", "responsetype": "ErrorResponse" }
Auditing
Note that all requests are logged in the system's console logs. Events that generate an Auditing event will be logged in the log against the sourceavatar/sourcecharacter e.g.
Note that hovering the mouse over the [Via] will generate a popup display of the accessing application's name, the developer key used, and 'also your originating IP address
'
List of ALL Response types
Many of these are esoteric and unlikely to be of interest to External access developers.
- UserException/SystemException - these are not really response types, the system catches any errors that escape and reports them (fully for user exceptions, or masked for system exceptions). These are normally converted to ErrorResponses for the HUD which causes it to emit the error message.
- ErrorResponse - an expected inability to process the user request, contains an “error” element.
- JSONPushResponse - Internally used to trigger a new transmission to a HUD, you should not see this as an External.
- JSONResponse - A flexible response type that allows any data to be returned via JSON structure. See the API for the called command for more information.
- MenuResponse - A HUD custom response that causes a menu to be displayed. Unlikely to show up in External access.
- NoResponse - An empty response
- NullResponse - An internal placeholder when a response doesn't yet exist. This will never be observed as any attempt to access it as a normal response throws a System level Exception.
- OKResponse - the standard response for successful completion ; includes a verbose “message” element that the HUD normally emits to its wearer.
- SayResponse - unlikely to be seen, contains a “sayas” and “say” element and causes the HUD to emit the message in Nearby Chat with the 'sayas' name (usually the characters name).
- TabularResponse - used to present a grid of information, this is rarely used due to the HUD its self being limited in presentation options, but exists in (e.g.) Instance.Status. External.Status produces a more appropriate JSONResponse. The default way External renders this is like the HUD interface - it will boil it down to a text string “message”, this is not great, but so rarely used I'm not going to fix this up yet.
- TerminateResponse - A response used to tell the HUD/RegionServer/Your System to abort actions and not submit any further requests until a user has reviewed the problem, ideally corrected it, and retried it. Most Second Life elements (HUD, Region server) shut down until they are reset by being clicked on. Your application should take appropriate actions on receiving a TerminateResponse ; any application ignoring them is likely to have their developerkey revoked and if traffic continues, the IP address will be filtered at the firewall level.