Tags

  • API Features

    Vehicle Management data submitted to Vehicle Fuel Tracker is stored in the VehMan API, which also provides much of the functionality available within the site.

    The API currently has the following features

    • Fuel log storage and analysis (Fuel economy and cost calculations)
    • Service/Maintenance storage and analysis
    • Journey details storage and analysis (Route mapping via Google Maps and Journey Speed Profiling)
    • Import of GPX track files
    • Import of GPXIngest JSON objects
    • Web friendly charts (via Google Charts)
    • Generation of static PNG charts
    • Ability to make charts public 
    • Live charts continue to update with the latest data
    • Cost Per Mile calculations on a per vehicle basis

     

    The next iteration of the API will implement

    • MOT/Tax reminders
    • Service interval reminders
    • The ability to link entries to others (for example, link remedial work to an MOT failure)
    • Improved Journey analysis
    • Improved Charts

     

  • Authentication

    Almost all requests to the API require proper authentication. There are a number of ways in which a client can authenticate, depending on the details and level of access available to it.

    To summarise, a client can authenticate using any of the following methods

    •   Site API Key (and secret)
    •   User API Key (and secret)
    •   Session Token

    In order to generate a Session token, a single call must be made with a valid Site or User credential. Session tokens are IP locked, and can be locked to an arbitrary IP (i.e. a Server can create on behalf of a client).

     

    Site API Key

    A Site API Key must be requested and cannot automatically be generated. Once enabled a site can create users, and users can authorise the site to authenticate on their behalf (they must do this through their 'home' site).

    Any user created by a site will have that site set as their 'home', therefore sites creating users must implement a mechanism to allow users to authorise other site keys

    to act on their behalf (A site may be a website, a smartphone app or anything similar).

    When authenticating using a site key, three headers must be sent (unless creating a user, in which case the user key will not yet be known)

    •    X-VEHMAN-SITE
    •    X-VEHMAN-KEY
    •    X-VEHMAN-USER

    The key used should be that of the site (not the user). If the Site is authorised to act on the users behalf, all transactions will be enacted as if that user had authenticated directly.

    See the section 'Secret Keys' for information on how the key should be encoded.

     

    User API Key

    A user can authenticate directly against the API using their API key and Secret key, to do so the following HTTP headers should be included

    •    X-VEHMAN-USER
    •    X-VEHMAN-KEY

    See the section 'Secret Keys' for information on how the key should be encoded.

     

    Session Token

    In order to allow the use of the API by client-side libraries (such as Javascript) without divulging API keys, a session token can be generated. The host system should place a call to /authentication/session using either their Site API key or the User API key.

    The request should include the key "IP" with a value matching that of the client IP which will be making calls, as with all API calls this should be JSON encapsulated and submitted via POST within a variable 'data'.

    In response, the API will create a unique, signed session token, locked to the specified IP. This session data can then be used to authenticate against the API for up to 15 minutes.

    The Session token can be submitted in one of two ways

    •   HTTP Header X-VEHMAN-SESSION
    •   Request variable SESS (via POST or GET)

     

    Secret Keys

    Although it is expected that all API calls will take place over HTTPS, it's not mandated. As a result, authentication tokens are most at risk of compromise when in transit on-the-wire - they are encrypted within the API and MUST be encrypted when stored by client devices/sites.

    To lessen the risk of compromise, Secret Keys should be used to sign requests in the form of an SHA1 hash. In order to ensure that a generated hash is not re-usable, the following method should be used

    1.   Generate the JSON request string and pass it through SHA1.
    2.   Prefix the secret key with the resulting string and pass through SHA1 once more
    3.   Submit the generated hash as the secret key.

    To ensure that otherwise identical requests receive different hashes, it's strongly recommended that you include a random, arbitrary token within the JSON request string. Anything assigned to the key 'randtoken' will be ignored by the API except as part of validating the submitted hash.

     

    Example Code

    <?php
      $mykey='1234';
      $request = new stdClass();
      $request->redirect = true;
      $request->randtoken = mt_rand(0,1000000);
      $submission = json_encode($request);
      $api-secret = sha1(sha1($submission).$mykey);
      // Submit $api-secret as header X-VEHMAN-KEY

    ?>

     

    API Responses

    If authentication is successful, the requested action will be completed.

    If authentication headers were not provided, or those that were provided were invalid, the API will return a HTTP 403. In most cases a JSON encapsulated response will also be provided detailing the issue encountered.

  • Index

  • Journeys

    The Journey module is used to record journey details, of most direct use within the API are the speed records.

    The usual authentication requirements apply to all areas of this module.

     

     

    GPX File Import

    The API supports import of GPS eXchange (GPX) files. In order to provide a file for import, a request must be made using POST to

    /journey/import/{vehicle identifier}

    All journeys must be recorded against a specific vehicle.

    Note: Due to the intensive nature of this function, The GPX file will not be imported at the time of the request, but an import task will be queued.

    The response will therefore confirm whether or not the task was successfully queued and provide the JobID. See the Queue submodule documentation for information on checking the status of a Queued task.

    The GPX file should be submitted as a HTML form field, the field in question should be 'subfile'.

    The request should therefore be of the type 'multipart/form-data'.

    Data Filtering and Manipulation

    By default, the system will use 'SmartTrack'. If a trackpoint occurs more than 1 hour (3600 seconds) after the previous trackpoint, a new GPS track will automatically be started.

    To disable this, the JSON request should include the key/value

    smartTrack: false

    The smartTrack threshold can also be adjusted, the value should be passed in seconds, so to set to 2 hours, we'd send

    smartTrackThreshold: 7200

    It is also possible to suppress certain information. For example, if the user does not want their GPS position to be recorded within the system, it can be suppressed. To suppress any of the following, an array called suppress should be submitted as part of the request

    Valid values are;

    • speed
    • location
    • elevation

    Although GPXIngest supports suppression of dates, the Database schema doesn't allow for this, therefore any attempts to suppress date will lead to the import being rejected.

    Example Call

    # curl -F "subfile=@importfile.gpx;type=text/xml" \
    -H "X-VEHMAN-KEY: Test: `echo {mykey} | sha1sum | awk -F\ '{print $1}'`" \
    -H "X-VEHMAN-USER: {myuserkey}" \
    {apiurl}/journey/import/{vehicleidentifier}



    Example Response

    {
    "timestamp":1378824115,
    "response":{
    "status":"Queued",
    "JobNumber":4
    },
    "errors":null,
    "error":0
    }

     

     

    JSON File Import

    When the API receives a GPS eXchange (GPX) file, it processes it and creates a GPXIngest Object (See https://github.com/bentasker/PHP-GPX-Ingest/).

    If preferred, (for example because you intend to suppress location data and don't want to send that data across the network at all) a JSON encapsulate GPXIngest object can be submitted instead. The necessary JSON can be extracted from GPXIngest with the method getJSON().

    The JSON string should be written to a file, inclusion in the request is NOT supported.
    In order to provide a file for import, a request must be made using POST to

    /journey/importjson/{vehicle identifier}

    All journeys must be recorded against a specific vehicle.

    Note: Due to the intensive nature of this function, The JSON file will not be imported at the time of the request, but an import task will be queued.

    The response will therefore confirm whether or not the task was successfully queued and provide the JobID. See the Queue submodule documentation for information on checking the status of a Queued task.

    The JSON file should be submitted as a HTML form field, the field in question should be 'subfile'.

    The request should therefore be of the type 'multipart/form-data'.

    Example Call

    # curl -F "subfile=@importfile.json;type=text/json" \
    -H "X-VEHMAN-KEY: {mykey}" \
    -H "X-VEHMAN-USER: {myuserkey}" \
    {apiurl}/journey/importjson/{vehicleidentifier}

     

    Example Response

    {
    "timestamp":1378824216,
    "response":{
    "status":"Queued",
    "JobNumber":5
    },
    "errors":null,
    "error":0
    }

     

     

    List Journeys

    To retrieve of all journeys recorded for a specific vehicle, place a call to

    /journey/listjourneys/{vehicle identifier}

    A record will be returned for every track recorded (as 'journeys' may include more than one track).

    Example Response

    Note: The list of stats returned may vary from those shown below - new statistics are being implemented

    {
    "timestamp":1378830060,
    "response":{
    "row0":{
    "journeyID":"1",
    "trackID":"2",
    "journeyDuration":"5190",
    "start":"1377581448",
    "end":"1377586638",
    "avgSpeed":"55.83",
    "maxSpeed":"70",
    "minSpeed":"0",
    "modalSpeed":"68",
    "map":"http:\/\/example.com\/chart\/journeymap\/1\/1\/2"
    }
    },
    "errors":null,
    "error":0
    }

     

    Journey Path Details

    Use this section of the module to retrieve full details for a specific journey. Depending on the parameters used when the source GPX file was ingested, this will include all or some of the following

    • latitude
    • longitude
    • Speed
    • Elevation
    • Time
    • Journey Track ID

    In order to place a request to this function, you must provide both the correct vehicle identifier and a valid Journey ID

    /journey/journeytrack/{vehicle identifier}/{journey id}/{track id} - Optional

    So both of the following would be valid requests to retreive the track points for a full journey

    /journey/journeytrack/1/1
    /journey/journeytrack/A123%20DAL/1


    Whilst the following would be valid requests to retrieve track points for a Track with an ID of 6 within journey 1.

    /journey/journeytrack/1/1/6 /journey/journeytrack/A123%20DAL/1/6

    Note: Track ID's are completely independant of Journey ID's, so no two journeys will contain a segment with the same ID.

     

    Example Response

    {
    "timestamp":1378830787,
    "response":{
    "row0":{
    "TrackPtID":"1",
    "segmentID":"1",
    "JourneyID":"1",
    "VehicleID":"1",
    "lat":"52.129725",
    "lon":"1.415779",
    "time":"1377581448",
    "speed":"0 mph",
    "speedint":"0",
    "elevation":"62"
    },
    "row1":{
    "TrackPtID":"2",
    "segmentID":"1",
    "JourneyID":"1",
    "VehicleID":"1",
    "lat":"52.129744",
    "lon":"1.415823",
    "time":"1377581457",
    "speed":"0 mph",
    "speedint":"0",
    "elevation":"68"
    },
    },
    "errors":null,
    "error":0
    }
  • Processing Queue

    The Queue module is used to view and manage a users queued tasks. These will primarily be processing tasks (such as GPX/JSON imports) but may also include other intensive tasks.

    All requests must be properly authorised, and only items queued by (or on behalf of) the current user can be viewed.

    Job Classes

    Each API submodule has its own JobClass, and any queued jobs will be assigned to this class.

    • GPX - Journey, specifically GPX or JSON Import
    • VEH - Vehicle SubModule, usually deletion

     

    Job Statuses

    Wherever individual Jobs are returned, the relevant Job status will also be returned. There are 6 possible statuses;

    • Awaiting Processing
    • Locked - Currently being processed
    • Completed
    • Failed
    • Cancelled By User
    • Unknown

    If the API returns a job status of unknown it's representative of an internal error.

     

    Show Queue

    To View the current Queue (including some historic items) request

    /queue/queue

    Example Response


    {
    "timestamp":1379864224,
    "response":{
    "jobs":{
    "J0":{
    "jobID": 1,
    "JobClass":"GPX",
    "Task":"Import",
    "started":"1378825905",
    "ended":null,
    "status":"Locked"
    },
    "J1":{
    "jobID": 15,
    "JobClass":"GPX",
    "Task":"Import",
    "started":"1379115601",
    "ended":null,
    "status":"Failed",
    "failurereason":"Journey creation failed"
    },
    "J2":{
    "jobID": 43,
    "JobClass":"GPX",
    "Task":"ImportJSON",
    "started":"1379849777",
    "ended":"1379849779",
    "status":"Completed"
    },
    "J3":{
    "jobID": 116,
    "JobClass":"GPX",
    "Task":"ImportJSON",
    "started":null",
    "ended":"1378826723",
    "status":"Cancelled By User"
    }
    },
    "errors":null,
    "error":0
    }

     

    Job Status

    To retrieve the status of a single Job, place a request to

    /queue/jobstatus/{job id}

    e.g. to retrieve the third job in the example above, we'd place a request to

    /queue/jobstatus/43

    Example Response

    {
    "timestamp":1379871871,
    "response":{
    "jobID": 43,
    "JobClass":"GPX",
    "Task":"ImportJSON",
    "started":"1379849777",
    "ended":"1379849779",
    "status":"Completed"
    },
    "errors":null,
    "error":0
    }

     

    Historic Items

    Jobs are not automatically purged from the database on completion, but the queue is pruned periodically by a cron script. Expect completed queue items to persist for no more than 7 days, although the actual retention period may vary from time to time.

    Failed items are retained for a slightly longer period.

     

    Submodule specific failure reasons

    Journey / GPX

    There are a number of failure reasons which may be returned by Jobs in the GPX class, most of which should be self-explanatory. If an error arises, the source GPX/JSON file will need to be checked and resubmitted for processing.

    Should a warning occur, the main journey record will have been created, so if the intention is to resubmit for processing this record will need to be removed. See the Journey submodule documentation for information on removing Journey records.

    Fatal Errors

    • Source file does not exist - A file was queued for import, but doesn't appear to exist on the server
    • Invalid GPX File - A GPX Import job was queued, but the XML could not be parsed.
    • Invalid JSON File - A JSON Import job was queued, but the JSON could not be parsed.
    • Date is suppressed - Will only occur when a JSON file has been submitted for import. Whilst GPXIngest will allow you to suppress dates, the API does not support import of Journeys without date information.
    • Journey creation failed - The journey could not be created in the database. Either there's an issue with the Journey data, or more commonly, that Journey has previously been imported.

    Warnings

    • Track x: creation failed - A specific track id could not be created, any child Segments and trackpoints will have been skipped
    • Segment x / y: creation failed - A specific segment could not be created in the database. x signifies the relevant trackID. Any child trackpoints will have been skipped
    • Trackpoint x / y / z: creation failed - A specific trackpoint could not be created in the database. x signifies the relevant trackID, y the segment ID and z the trackpoint ID.
  • Request Filters

    Request filters allow you to filter the data that the API returns, for example limiting a fuel-log listing to entries between specific dates.

    All filters should be within the main JSON encapsulated request, under variable 'filter'.

    Key/value pairs within the filters object should specify what to filter on, the full range of supported keys varies by submodule, but the global filters are detailed below

    Date

    Date can be passed as a value (i.e. match exactly) or as an array - start and end.

    filters{
    "Date":[ '2013-10-14','2013-10-15' ]
    }

    Date should always be passed in MySQL format

     

    Fuel Filters

    Valid filters are;

    • Date
    • Garage
    • Mileage
    • MileageLess
    • MileageMore
    • Cost
    • CostLess
    • CostMore

     

    Service Filters

    Valid filters are;

    • Date
    • Garage
    • Mileage
    • MileageLess
    • MileageMore
    • Cost
    • CostLess
    • CostMore
    • Work
    • Fault

    Journey Filters

    • Order (ASC/DESC) - Currently only supported on ListJourneys
  • Service and Maintenance

    Service and maintenance module etc.

  • Sessions

    The Session module allows you to mint and destroy session tokens.

    The idea being that rather than needing to send explicit authentication details with every request, you can send them once to mint the token and then simply provide the token with each subsequent request.

    An additional benefit of this is that it allows you to pass a users browser a sessionKey so that they can place requests themselves (perhaps via AJAX, or at a basic level, to simply load a chart).

     

    Creating a Session Token

    To create a session token, place a request to

    /session/create

    Within the JSON request, you must specify the following

    • ClientIP: The IP address that subsequent requests will originate from. This _must_ be correct, otherwise access will be denied

    The token will be generated for whichever user is currently authenticated, so if you're using a site key to authenticate on behalf of a user, ensure your authentication headers include the user's key (See the Authentication documentation for more detail).

     

    Response

    The JSON response will be an array containing the minted token in key 0 and the expiry time in key 1;

    {
    "timestamp":1382057808,
    "response":[
    "eJw9jMsOgjAQRb+GLslMI3S66EJ0485o+IAKAxINwRYT+HtREjZnce7jyUvfeBQxDI13BFp0PHhUJMFYAhLTMrK\/cUqC5ykGn9kyk\/J8WZGpw0rCHJXO0chc\/6Q8ruR57COnrbS9kQXawiu\/P5wmbsplf6lw31aJ4+7\/2p5EeHU+PQKK1Hde17YlBdYwILaG0dUuqDvIYArtQNtQ8Bq6L577OhI=",
    1382058708
    ],
    "errors":null,
    "error":0
    }

    Be aware that session tokens are only valid for 15 minutes once they've been minted

     

    Destroying a Session

    To destroy a session, place an authenticated request to

    /session/destroy

    Within the JSON request you must specify the Session token as DestToken. As an additional security measure (to prevent users from destroying other's sessions), you must also be authenticated (whether directly, or as a site on behalf) as the user the token was created for.

     

    Response

    {
    "timestamp":1382057808,
    "response":1,
    "errors":null,
    "error":0
    }

    Note: If you fail to authenticate as the user the session relates to, no error will be returned, the session will simply remain valid.

     

    Errors

    The following errors may be returned

    • Authentication Failed: The system was unable to authenticate your request, check you've sent valid auth headers with your create/destroy request
    • IP Not Specified: You didn't specify a ClientIP in your request. The token is locked to a specific IP for security reasons, so a token could not be minted.
    • Token Not Specified: You placed a destroy request, but didn't specify the session token.
  • Vehicle Module

    Vehicle Module etc