CVD API

 

Start

Do you want to have a better life?

CVD is a site to find inspiration, to help others if you are good at writing, to find the right words for the right situation. In other words, it is the site to communicate more and better with other people and finaly have a better

This is the beta apis for CVD and all the documentation is subject to change

These apis will allow you to find and navigate through the texts that will help you in your day to day communatication.

Last updated:
  • 2014-03-07:
  • 2014-03-06: Info, Translations
Continue with Infos

API Informations

The API provide a small information access point with some values from the server side that can help in your application

Version

Get the the version of the API

    GET /info/version
    //returns:
    {
        "version": "0.9"
    }

Build time

Get the time of the last build of the core api library. Despite the number version of the api, it should be interesting to track the build time of the api as it can change without changing the api version number

    GET /info/buildtime
    //returns:
    {
        "date": "2014-03-06T09:13:31"
    }
Continue with AREAS

Areas

The root container for CVD Apis is the list of areas, this is the place to start.

An area is a virtual application definition containing a list of intentions, a list of available cultures and some other things.

Depending on your account and rights, you'll have access to one or more areas allowing you to have a logical grouping of your intentions.

So what is an intention? An intention is a way to group texts

To start, you should query the areas:

  
  GET /areas
          

You get in return a collection of Areas with an HTTP Status code 200 OK.

Note :

  • you'll only see the areas you can see with your account.
  • The content varies depending on the culture of the client browser. You can override it by providing directly the Accept-Language : myculture in your query

This is the format of what you'll get:

  [
    {
    "AreaId": "3C834C",
    "Name": "General",
    "Intentions": [],
    "AvailableCultures": [{
        "Name": "English",
        "Code": "en-EN",
        "AreasInCulture": [],
        "IntentionsInCulture": []
        }, {
        "Name": "Français",
        "Code": "fr-FR",
        "AreasInCulture": [],
        "IntentionsInCulture": []
        }]
    }, {
    "AreaId": "CBDDEB",
    "Name": "Formalities",
    "Intentions": [],
    "AvailableCultures": [{
        "Name": "Français",
        "Code": "fr-FR",
        "AreasInCulture": [],
        "IntentionsInCulture": []
        }]
    }
  ]

Once you know your area you should get more detail for that area and have a list of intentions. You should get the area with a GET on that name:

  GET /{areaname}
        

You'll get a more complete Area entity in return with the list of defined intentions for that area with an HTTP Status code 200 OK.

The area name is not case sensitive. If you provide a wrong area name, you'll get a 404 NOT FOUND code.

The format of the Area is the one in that exemple:

{
    "AreaId": "CBDDEB",
    "Name": "Formalities",
    "Intentions": [{
        "IntentionId": "1CEE9B",
        "CreationDate": "2013-11-12T18:01:07.407",
        "UpdateDate": "2013-11-12T18:01:07.407",
        "LastUpdateBy": null,
        "Comment": null,
        "SortOrder": 160,
        "MediaUrl": null,
        "Areas": [],
        "Labels": [],
        "LabelCultures": [],
        "AreaIds": [],
        "Archived": 0
    }, {
        "IntentionId": "9B2807",
        "CreationDate": "2013-11-12T18:01:07.407",
        "UpdateDate": "2013-11-12T18:01:07.407",
        "LastUpdateBy": null,
        "Comment": null,
        "SortOrder": 200,
        "MediaUrl": null,
        "Areas": [],
        "Labels": [],
        "LabelCultures": [],
        "AreaIds": [],
        "Archived": 0
    }],
    "AvailableCultures": [{
        "Name": "Français",
        "Code": "fr-FR",
        "AreasInCulture": [],
        "IntentionsInCulture": []
    }]
}
Continue with Intentions

Intentions

update : added a 'all areas' api

All areas and intentions

You can get an exhaustive list of all the intentions without any area classification with this simple call:

    GET /intentions

It will return a complete list of intentions with all the details as in the exemples below

All collection

Intentions is one of the logical ways of grouping Text entities

As an Intention is available in more than one Area and in order to provide specific information or content depending on this area, you need to provide the Area name when you call for an Intention or a list of Intentions.

Your call should be:

  GET /{area-name}/intentions

As an Intention contains one or more labels, the resulting intentions that the server returns is dependent on the culture of the client browser. It will automatically choose the right one but you can override it by providing the Accept-Language header of your choice.

You will get a collection of Intentions with a format like these:

  
  [{
      "IntentionId": "1CEE9B",
      "UpdateDate": "2013-11-12T18:01:07.443",
      "SortOrder": 160,
      "MediaUrl": null,
      "Culture": "fr-FR",
      "AreaIds": ["CBDDEB"],
      "OtherCultureLabels": [],
      "Slug": "lettre-type-assurance",
      "Label": "Lettres types assurances",
      "MostRecentTextUpdate": "0001-01-01T00:00:00"
  }, {
      "IntentionId": "B47AE0",
      "UpdateDate": "2013-11-12T18:01:07.443",
      "SortOrder": 150,
      "MediaUrl": null,
      "Culture": "fr-FR",
      "AreaIds": ["CBDDEB", "3C834C"],
      "OtherCultureLabels": [],
      "Slug": "condoleances",
      "Label": "Condoléances",
      "MostRecentTextUpdate": "0001-01-01T00:00:00"
  }, {
      "IntentionId": "FFF937",
      "UpdateDate": "2013-11-12T18:01:07.443",
      "SortOrder": 155,
      "MediaUrl": null,
      "Culture": "fr-FR",
      "AreaIds": ["CBDDEB"],
      "OtherCultureLabels": [],
      "Slug": "formules-de-politesse",
      "Label": "Formules de politesse",
      "MostRecentTextUpdate": "0001-01-01T00:00:00"
}]

The response should have a 200 OK code, or 404 NOT FOUND if not found.

Notes:

  • The Slug will be used as an identifier for your localized intention: Slug = IntentionId + Culture
  • The UpdateDate is the last modification of the intention for this label
  • AreaIds contains a list of the areas where that Intention is present
  • OtherCultureLabels contains a list of the other cultures existing for that Intention
  • MostRecentTextUpdate gives you a freshness indication about the most recent date of modification of a text for this intention.

Get One

Get By ID

You may need to get information for one intention from its id:

    GET /{areaName}/intention/{intentionId}
exemple:
    GET /General/intention/006B9F

Get By Slug

You can get an indention by it's prototype slug:

    GET /{areaName}/{intentionSlug}
exemple:
    GET /General/thank-you
Continue with Texts

Texts

status : complete for GET

Definitions

A Text, as presented to the user is called a TextProjection and it is the aggregate between a TextPrototype containing core and shared information and a TextRealization corresponding to a version of that prototype for a specific culture and with specific attributes. Under a same TextPrototype you can have different related realizations : in french from Man to woman, in french from woman to man, and the same in english.

As for intentions, you need to always specify the Area in order to know what application is running

Some text actions are related to culture. The Culture Code is automatically get from your browser. That parameter takes the following form: en-EN;q=0.4,fr-FR;q=0.6. The q parameter defines the preference: here the fr-FR will be prefered it's affinity is 0.6 and en-EN is only 0.4

You can also, by your choice, specify explicitely the culture in your ajax query with the Accept-Language definied in the headers you'll send:

    Accept-Language : en-EN;q=0.4,fr-FR;q=0.6

Get all texts for an intention

When you have an intention, you'll want to get the texts for it. From client side, you'll get the text projections for that intention and in the specified culture. You can retrieve texts for an intention by intention id or intention slug name

By Id

A query to get that will have the following form

    GET /{areaName}/intention/{intentionId}/texts
exemple:
    GET http://api-cvd-dev.azurewebsites.net/General/intention/BD7387/texts

By intention Slug name

A query to get that will have the following form

    GET /{areaName}/{intentionSlug}/texts
exemple:
    GET http://api-cvd-dev.azurewebsites.net/General/thanks/texts

By intention Slug and relation type

if you need an additional filtering of the intention with the relation type this is the right api:

You can also provide optionaly the gender in the query parameters:

    GET /{areaName}/{intentionSlug}/{relationType}/texts?relationtgender={gender}
exemple:
    GET http://api.cvd.io/HelloMum/facebook-status/64C63D/texts?relationtgender=H

Get a projection

Sometimes you should need to reload a text projection, you should do it like that:

    GET /{areaName}/text/{realizationId}
exemple:
    GET http://api-cvd-dev.azurewebsites.net/General/text/014E19

Note that the id passed is the one of the realization, not the one for the prototype

Get all realizations of a Text

You can also get all the realizations of a same text

    GET /{areaName}/text/realizations/{prototypeId}
exemple:
    GET http://api-cvd-dev.azurewebsites.net/General/text/realizations/014E19

Note that the id passed is the one of the prototype

Continue with Actions

Actions

An action is event that you can notify the server attached to an entity (an intention, a text...). This part is still in construction but you still can use the old format urls:

    GET http://api.cvd.io/userevent?{querystring}

where {querystring} has the following values:

  • ActionType : stores the user action : click, ...
  • ActionLocation : where the action is initiated (MenuBar, SplashScreen, TextDetailView, TextList, IntentionList,.....)
  • TargetType : Area / Intention / Text / Navigation / Command (such as filter, profile or language buttons)
  • TargetId :
    • for areas, intentions and texts : their id,
    • for navigation : a chosen name for the target (GeneralArea, ImportantArea, RecipientList)
    • for commands : the id of the property they are targeting (like Gender - Male, Age - over45,...)
  • TargetParameter : additional value given in the context of the call for a target
  • AreaId
  • ClientTime
Additionnal parameters will be grabbed from query directly (and should not be passed):
  • UserId : logged user or anonymous unique Id stored in cookies
  • UserAgent : we'll get it from headers
  • ServerTime : affected when recorded on the server

A few other things that define the user profile will also be stored but via a another dedicated interface:

  • Genre
  • PreferedCulture
  • CampainType
  • CampainId
  • CampainUrl
  • Properties(Key value strings)

For exemple:

  GET http://api.cvd.io/userevent?ActionType=click&ActionLocation=TextList&TargetType=text&TargetId=123456&areaId=1234

Which means that you're notifying the server that the user (which id is sent by cookies) is doing the action Click on the text with id 123456.

If it succeed, the server will notify you with an HTTP Status code 200 OK

Continue with Store

Store

Store, is a generic purpose device to server key value store. It is build for being able to do simple backups from an identified device to servers

Store a value

You store values (string or stringified json value), for a key and a storeid. Storeid is an id managed by you. no security is done here, you should use a guid or equivalent to be sure that the store id is unique for your device/client.

    POST /centralstore/{storeid}
    {
    'key':'name of the key',
    'value':'json string'
    }
    //returns:
    {
        "Context": "name of the key",
        "Status": "success", //or "error"
        "Message": null      //or the error message    
    }

An exemple:

    POST /centralstore/{storeid}
    {
     'key':'profile',
     'value':'{ age:"35-45",name:"Rui", sex:"male", counter:4}'
    }
    
    //result:
    {
        "Context": "profile",
        "Status": "success",
        "Message": null         
    }

You use the same interface for adding or updating a key, you don't need to care about that

Get a value for a Key

You just need to provide your storeid and the key you want to read. Note that in return you get a full record object, the value is a property inside

    GET /centralstore/{storeid}/{key}
    //returns
    {
        "StoreId": "your store id",
        "Key": "the key",
        "Value": "json string value",
        "Context": null,
        "Created": "2014-03-07T13:37:34.257",
        "Id": "internal id you don't care only usefull for debug"
    }

An exemple:

    GET /centralstore/rui123/profile
    {
        "StoreId": "rui123",
        "Key": "profile",
        "Value": "{ age:\"35-45\", name:\"Rui Carvalho\", sex:\"male\", counter:5}",
        "Context": null,
        "Created": "2014-03-07T13:37:34.257",
        "Id": "12345"
    }

Translation API

The translation API is dedicated to provide all the needed interfaces to manage translations for texts provided by users

Profile

Get information about the current user profile defined by its id

        
    GET /translation/profile/{id}
        //result:
    {
        "AuthenticationUserId": "mylogin",
        "ProfileUniqueId": "123-my-id",
        "Name": "My real Name",
        "CultureSource": "fr-FR",
        "CultureTarget": "es-ES",
        "Created": "2014-02-24T00:00:00",
        "IntentionList": "016E91,03B6E4,9B2C8B"
    }
        

Intentions

If you don't load the profile or want to ensure having the right array of allowed intentions for that profile you can call the translation intentions api for that profile

        
    GET /translation/{id}/intentions
        //result:
    [   
        "016E91", 
        "03B6E4", 
        "9B2C8B"
    ]
        

Texts

You can get the actual translations available from a user profile for an intention

    GET /translation/{id}/{intention}/texts
    //result:
    [{
        "PrototypeId": "2341",
        "Prototype": null,
        "ProfileUniqueId": "123-my-id",
        "Culture": "es-ES",
        "Content": "Querida Mamá, no he estado muy disponible por estos días. Que dirías si pasamos una tarde juntas, como antes cuando me llevabas a nos se donde, solo para ver las vitrinas?",
        "Status": "proposed",
        "Created": "2014-03-06T08:23:42.083",
        "Id": "1234"
    }, {
        "PrototypeId": "0987",
        "Prototype": null,
        "ProfileUniqueId": "123-my-id",
        "Culture": "es-ES",
        "Content": "Mi amorcito, tengo que trabajar hasta tarde esta noche. Pero estoy pensando en ti y espero que pases una linda noche. Cuando llegue, te daré un besito sobre tus ojitos dormidos. Tu Papá que te ama.",
        "Status": "proposed",
        "Created": "2014-03-06T08:20:20.033",
        "Id": "2345"
    }]
Please note that PrototypeId is a bad name and will be changed in a near future because a translation is not related to a prototype but to a realization.

How to use APIs for Static Resources

Shared static resources are available physicaly through gw-static.azurewebsites.net (but also through an Azure CDN later on).

Static resources, mostly images, are available and organized through containers.

The containers are a simple way to qualify the image contents. Even if we profide qualified information through the Apis, all the information is available in the path of the resource:

/{application-name}/{recipient}/{theme}/{size}

For exemple:

/cvd/parent/puppies/small

This container represents images, in small size, for the cvd app with the theme puppies and is valid for parent recipient. Then the url for an image inside that container, should be like that:

http://gw-static.azurewebsites.net/cvd/parent/istockpuppies/small/iStock_000005341891_Medium.jpg.

In order to access these qualified resources, you should query first the server APIs to get the list of containers and then get the list of images in a container.

Note that each container can have it's own definition to qualify it's

List all the children containers available for your app

You should get the array of all containers by calling /container/{appname}:

GET gw-static.azurewebsites.net/container/general

The resulting json is in the same format that for all containers.

But you can also filter by it's properties. Let's say that you want to have only the containers that contain small size photos:

GET  gw-static.azurewebsites.net/container/general?size=small

The properties defined for each container are configured by the admin and may change in time, but currently they are defined like that:

  • application : the name of the application it targets
  • recipient : the recipient target
  • theme : what is this about
  • size : to get the full size of the images or the thumbnail.

These properties are defined as key/value pairs and look like:

[
    ...
    {
        "id": "/generic/CloseFriends/good-morning/full",
        "properties": {
            "application": "generic",
            "recipient": "closefriends",
            "intention": "good-morning",
            "size": "full"
        },
        "additionalInfo": "",
        "childrenContainers": null
        },...
]

Each of these properties corresponds of a segment of the path in that order

Each segment of the path is also a container and can be called like that.

If there is more subfolders inside to organize even better the files, their names will be stored in extra property field.

the additionalInfo field may content meta information about the container (a textual description of it).

Get the images of a container

Once you get containers information, you can ask for their contents with the pattern /container/files/{container-id}. Like :

GET gw-static.azurewebsites.net/container/files/generic/CloseFriends/good-morning/full

which returns an array of image paths (relative to the gw-static server):

[
  "/myapp/goodmorning/sayhello/full/file1-full.jpg",
  "/myapp/goodmorning/sayhello/full/file2-full.jpg"
]

You can also ask for the parent container and then you get all the images contained in the children containers:

GET gw-static.azurewebsites.net/containers/files/myapp/goodmorning/sayhello
[   ...
    "/generic/CloseFriends/good-morning/full/kitten 2.jpg",
    "/generic/CloseFriends/good-morning/full/kitten 3.jpg",
    "/generic/CloseFriends/good-morning/full/kittenglass1.jpg",
    "/generic/CloseFriends/good-morning/full/kittenglass2.jpg",
    ...
]

Or you can also filter the container for specific properties:

GET gw-static.azurewebsites.net/container/files/myapp/goodmorning?size=small
[
     "/generic/CloseFriends/good-morning/small/kitten 3.jpg",
    "/generic/CloseFriends/good-morning/small/kittenglass1.jpg",
    "/generic/CloseFriends/good-morning/small/kittenglass2.jpg",
]

Get a random image for a container

It works exactly the same way as for getting all of the images of a container but instead it returns only one picked randomly:

  • if you call a parent container, it will work with all the children images
  • you can filter container by properties

The method for this call is:

GET  gw-static.azurewebsites.net/container/randomfile/{container-name}?{properties}

Then for exemple for a call:

GET gw-static.azurewebsites.net/container/randomfile/cvd?size=small

You'll get directly a string with a relative path to image:

/cvd/parent/default/small/shutterstock_70773556.jpg

Get the images

From here you just have to recompose host+path to get access to the images:

gw-static.azurewebsites.net/myapp/goodmorning/sayhello/full/file2-full.jpg

List all the containers for all the apps

In case you need to get all the containers available, you should get the array of all containers by calling /containers:

GET gw-static.azurewebsites.net/containers