YoolinkPro API Documentation

This documentation describes the YoolinkPro API interface. It's designed for developers who wants to interconnect YoolinkPro with their own applications, or create new application relying on their YoolinkPro account.

Getting Started

In this section we will cover the concepts every developer should know before interacting with the API.

Common concepts

The API uses a REST-like interface. This means that our YoolinkPro method calls are made over the internet by sending HTTP GET, POST, PUT or DELETE requests to the YoolinkPro API server (http://api.yoolinkpro.com). Nearly any computer language can be used to communicate over HTTP with the REST server.

Any application that want to use the YoolinkPro API must be able either to access api.yoolinkpro.com via HTTP (80) or via HTTPS (443).

Prerequisites

Before starting developing a YoolinkPro third-party application, an administrator of the YoolinkPro account should ask us to enable the YoolinkPro API support for his account.

When the API support is enabled, three informations are provided to allow the communication between the third-party application and the YoolinkPro API:

api_public_key

This key will be used to identify the yoolinkpro account which is sending the request.

Any request sent must provide that key along with the given parameters.

api_private_key

This key is private and must not be sent with the request parameters. It's used by the third-party application to sign its requests (as explained below, in the Request Authentication section).

That key is only known by YoolinkPro API and the third-party application, it must be kept secret by the third-party application.

This key is private and must not be sent with the request parameters.

api_admin_key

That key is used by the third-party application for making privileged actions. All of the requests for actions described in the Administrator section should be signed with this key, rather than with api_private_key.

Request Authentication

First of all, we'll see in this section how to build and send a valid authenticated request to the YoolinkPro API. In order to make sure a request is sent by the third-party application, YoolinkPro API will perform a signature verification before processing the request.

This section will explain how it works.

Signing the request

The thrid-party application must sign every request it sends. To do so, it has to do build the signature string like the following:

  1. Sort the parameters hash table alphabetically by key.

  2. Concatenate all key/value pairs together in the format key=value (omitting the signature itself, since that is what we are calculating).

    a_var=a_value other_var=other_value

  3. Concatenate to the HTTP method string in lowercase (get), the path string (/user/42.json) and the params string created during the previous step.

    get /user/42.json a_var=a_value other_var=other_value

  4. Append the api_private_key and two mandatory parameters :

    X-YP-MilliTime

    Unix time in milliseconds, defined as the number of milliseconds elapsed since midnight UTC of January 1, 1970

    X-YP-Int

    a uniq integer or at least a random one

  5. Take the base64 of the SHA1 hash of the whole string (wihout any spaces) :

    get /user/42.json a_var=a_value other_var=other_value 87e1f221a672a14a323e57bb65eaea19d3ed3804 1334742783000 282

Note that for all administrator actions, the key to use for signing the request is not api_private_key but api_admin_key.

Below is a Ruby code example that shows how to implement the signing method:

require 'base64'

millitime = Time.now.to_i*1000
int = rand(1000)

query_string = params.sort.map{|v| v.join('=')}.join

key = "get/user/search.json#{query_string}#{PRIVATE_KEY}#{millitime}#{int}"

signature = Base64.encode64(Digest::SHA1.digest(key)).gsub(/=$/, '')
# Important note : we do not append '=' at the end of the signature.
# If your library adds a trailing '=' remove it.

Sending the request

Once the signature has been built, the request can be sent to the YoolinkPro API. To do so, all meta-data such as the public key and the signature should be sent via the request headers:

X-YP-AppKey

This header should contain the api_public_key of the application.

X-YP-Signature

This header should contain the signature built for the request.

X-YP-MilliTime

This header should contain the unix time in milliseconds, defined as the number of milliseconds elapsed since midnight UTC of January 1, 1970.

X-YP-Int

This header should contain a uniq integer or at least a random one.

Here is an example of a signed GET request:

GET /user/42.json?a_var=a_value&other_var=other_value
X-YP-AppKey: api_public_key
X-YP-Signature: signature
X-YP-MilliTime: millitime
X-YP-Int : int

Checking the signature

Whenever a request is received by YoolinkPro API, it first checks that the signature is valid. To do so, it does the very same process as described above to rebuild the signature, and makes sure both signatures are the same.

If so, the request is authenticated and granted for processing.

Note, the request can played only once and is valid for 30 minutes after X-YP-MilliTime.

Response format

All requests performed on the YoolinkPro API should provide a format argument, as the file extension in the path of the request.

Supported formats

Here is an example:

GET http://api.yoolinkpro.com/users/24.json

Error responses

When an error is triggered, the action will always return a response with the following entries:

error:      the error code of the error
message:    a message with details about the error that occurs

Checking if error is present in the response object is a good way to check if the actions succeeded or not.

Privileges

There are 3 levels of privileges:

When the YoolinkPro API is enabled, another key is given to the client: the api_admin_key. This key is provided to allow an API request to perform privileged actions.

This key gives to the application the power of a regular administrator. As a developer of a third-party application, you should not consider shipping your application with your api_admin_key (for example if you deploy a desktop app within your company).

Ideally and if you need it, that key should be prompted to the user (if they are administrator, they have access to the YoolinkPro API information in their account).

All requests for actions described in the section Administrator must been signed with the api_admin_key.

Unprivileged actions

All the actions described in this section are read-only. These actions aren't privileged and don't require any identity_token.

GET /user/search


This method retreives a user corresponding to the given email.

Parameters:

Example:

GET /user/search.json?email=vincent@yoolink.fr
GET /user/search.json?external_id=123ABC

Sample JSON Response:

{
  "user": {
    "id": 1,
    "customer_id": 1,
    "slug": "yoolink",
    "firstname": "Vincent",
    "lastname": "Durand",
    "name": "Vincent Durand",
    "is_active": true,
    "email": "vincent@yoolink.fr",
    "disabled": false,
    "locale": "fr",
    "external_id": "123ABC",
    "telephone": "0123456789",
    "im": "vincent.durand"
    "im_type": "3",
    "mobile_phone": "0623456789",
    "description": "Yoolink CTO",
    "birth_day": "25",
    "birth_month": "12",
    "has_full_feed": true,
    "role": "CTO",
    "past_experience": "Rails Developer",
    "education": "",
    "profile_like": "Ruby, Rails",
    "profile_dislike": "",
    "twitter_url": "",
    "facebook_url": "",
    "linkedin_url": "",
    "viadeo_url": "",
    "office_number": "1337",
    "company": "Yoolink",
    "address": "",
    "country": "France",
    "website": "http://www.yoolinkpro.com",
    "project": "YoolinkPro"
  }
}

GET /user/:id


This method retreives a user corresponding to the given id.

Parameters:

Example:

GET /user/42.json

Sample JSON Response:

{
  "user": {
    "id": 1,
    "customer_id": 1,
    "slug": "yoolink",
    "firstname": "Vincent",
    "lastname": "Durand",
    "name": "Vincent Durand",
    "is_active": true,
    "email": "vincent@yoolink.fr",
    "disabled": false,
    "locale": "fr",
    "external_id": "123ABC",
    ...
  }
}

User actions

All of the actions described here require the user_id as parameter.

POST /links.json


This method creates a new link object corresponding to the params given in the request body.

Parameters:

Note that at least one tag is expected. The API won't accept a new link if no tag is given.

If the link is already posted, you will get an error message with the id of the link. In this example 7327 is the id of the link found:

{"error":302,"message":"the link already exists","id":7327}

Example:

POST /links.json
user_id: 1
url: http://www.yoolinkpro.com
title: Yoolink Pro
tags: Pro,Corporate,Yoolink
description: Awesome application for the companies
post_to: My private community
is_private: true
comment: Must be seen by the whole company
subscribers: john@doe.com,roger@doe.com

Sample JSON Response:

{
  "id": 123,
  "url": http://www.yoolinkpro.com,
  "title": "Yoolink Pro",
  "description": "Awesome application for the companies",
  "posts": [
    {
      id: 1234,
      user_id: 1,
      tags: "Pro,Corporate,Yoolink",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "comments": [
    {
      id: 654,
      user_id: 1,
      content: "Must be seen by the whole company",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "likes": []
}

POST /links/:id/comments.json


This method create a comment belonging to the user on the link object specified by the id.

Parameters:

Example:

POST /links/123/comments.json
user_id: 1
comment: Comment to add to the link

Sample JSON Response:

{
  "id": 123,
  "url": http://www.yoolinkpro.com,
  "title": "Yoolink Pro",
  "description": "Awesome application for the companies",
  "posts": [
    {
      id: 1234,
      user_id: 1,
      tags: "Pro,Corporate,Yoolink",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "comments": [
    {
      id: 654,
      user_id: 1,
      content: "Must be seen by the whole company",
      created_at: "2014-03-27T22:41:26.000Z"
    },
    {
      id: 655,
      user_id: 1,
      content: "Comment to add to the link",
      created_at: "2014-03-27T23:00:04.000Z"
    }],
  "likes": []
}

PUT /links/:id


This method retreives the existing link object identified by the given id in the path and updates it with the parameters given in the request body.

In order to remove an existing value for a given attribute, the attribute must be given with a null value (when an attribute is not given in the request params, its value is untouched).

Parameters:

Note that it's not possible to change the URL of an existing link. If you want to actually change the URL, you have to first DELETE the object and re-create it with the good URL.

Example:

In the following example, we alter the link object #42, changing the value of its attributes title and tags and removing the value of the attribute description.

PUT /links/42.json
userd_id: 1
title: YoolinkPro
tags: YoolinkPro
description:

DELETE /links/:id


This method deletes the existing link object identified by the id given in the path.

Parameters:

Example

DELETE /link/42.json
user_id: 1

POST /messages.json


This method create a tweet-like message.

Parameters:

Example:

POST /tweets.json
post_to: My private community
is_private: true
content: Thank you for choosing YoolinkPro!

Sample JSON Response:

{
  "id": 13,
  "user_id": 1,
  "content": "Thank you for choosing YoolinkPro!",
  "created_at": "2014-03-27T22:41:26.000Z"
}

Administrator Actions

In this section, we'll see all the methods available in the YoolinkPro API that require an api_admin_key.

All the actions must be signed with the api_admin_key rahter than whith the api_private_key.

These actions are performed with administrator privileges.

GET /users


This method retreives all users.

Example:

GET /users.json

Sample JSON Response:

{ "users":
  [
    {
      "user": {
        "id": 1,
        "customer_id": 1,
        "slug": "yoolink",
        "firstname": "Vincent",
        "lastname": "Durand",
        "name": "Vincent Durand",
        "is_active": true,
        "email": "vincent@yoolink.fr",
        "disabled": false,
        "locale": "fr",
        "external_id": "123ABC",
        ...
      }
    },
    {
      "user": {...}
    },
    {
      "user": {...}
    }
  ]
}

POST /user


Creates a new user in the YoolinkPro account.

Parameters:

Example:

POST /user.json
email: john.smtih@company.com
firstname: John
lastname: Smith

Sample JSON Response:

{
  "user": {
    "id": 123,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Smith",
    "name": "John Smith",
    "is_active": false,
    "email": "john.smtih@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

PUT /user/:id


Update the user.

As for any resource, in order to remove an existing value for a given attribute, the attribute must be given with a null value (when an attribute is not given in the request params, its value is untouched).

Parameters:

Example:

PUT /user/42.json
lastname: Doe
email: john.doe@company.com

Sample JSON Response:

{
  "user": {
    "id": 123,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Doe",
    "name": "John Doe",
    "is_active": false,
    "email": "john.doe@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

POST /user/photo/:id


Upload photo for user corresponding to the given id.

The photo_data parameter given in the request body must not be concatenate in the key for signing the request.

Key calculation example:

method path api_admin_key X-YP-MilliTime X-YP-Int

post /user/photo/42.json 87e1f221a672a14a323e57bb65eaea19d3ed3804 1334742783000 282

Parameters:

Example:

POST /user/photo/42.json
photo_data: File.open('/home/vdurand/pictures/John-Doe.jpg') # Ruby example

Sample JSON Response:

{
  "user": {
    "id": 123,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Doe",
    "name": "John Doe",
    "is_active": false,
    "email": "john.doe@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

PUT /user/enable/:id


Enables a previously disabled user. Once enabled, the user is able to check in again to the service.

Parameters:

Example:

PUT /user/enable/42.json

PUT /user/disable/:id


Disable a user. Once disabled, the user is not able to check in again to the service.

Parameters:

Example:

PUT /user/disable/42.json

GET /groups


This method retreives all groups.

Example:

GET /groups.json

Sample JSON Response:

{
  "groups": [
    {
      "group": {
        "id": 1,
        "name": "API",
        "category": "YoolinkPro",
        "description": "API",
        "is_private": false,
        "is_team": false,
        "is_followed_by_default": false
      }
    },
    {
      "group": {...}
    },
    {
      "group": {...}
    }
  ]
}

GET /teams


This method retreives all teams.

Example:

GET /teams.json

Sample JSON Response:

{
  "teams": [
    {
      "team": {
        "id": 2,
        "name": "Marketing",
        "category": null,
        "description": "Everything on Marketing go there.",
        "is_private": false,
        "is_team": true,
        "is_followed_by_default": false
      }
    },
    {
      "team": {...}
    },
    {
      "team": {...}
    }
  ]
}

GET /group/:id


This method retreives a group corresponding to the given id.

Parameters:

Example:

GET /group/1.json

Sample JSON Response:

{
  "group": {
    "id":1,
    "name": "API",
    "category": "YoolinkPro",
    "description": "API",
    "is_private": false,
    "is_team": false,
    "is_followed_by_default": false
  }
}

GET /team/:id


This method retreives a team corresponding to the given id.

Parameters:

Example:

GET /team/2.json

Sample JSON Response:

{
  "team": {
    "id": 2,
    "name": "Marketing",
    "category": null,
    "description": "Everything on Marketing go there.",
    "is_private": false,
    "is_team": true,
    "is_followed_by_default": false
  }
}

GET /[team|group]/:id/followers


This method retreives the followers for a group/team corresponding to the given id.

Parameters:

Example:

GET /group/42/followers.json
GET /team/42/followers.json

Sample JSON Response:

{
  "followers": [
    {
      "user": {
        "id": 123,
        "customer_id": 123,
        "slug": "company",
        "firstname": "John",
        "lastname": "Doe",
        "name": "John Doe",
        "is_active": false,
        "email": "john.doe@company.com",
        "disabled": false,
        "locale": "en",
        "external_id": "",
        ...
      }
    },
    {
      "user": {...}
    },
    {
      "user": {...}
    }
  ]
}

GET /team/:id/members


This method retreives the members for a team corresponding to the given id.

Parameters:

Example:

GET /team/42/members.json

Sample JSON Response:

{
  "members": [
    {
      "user": {
        "id": 123,
        "customer_id": 123,
        "slug": "company",
        "firstname": "John",
        "lastname": "Doe",
        "name": "John Doe",
        "is_active": false,
        "email": "john.doe@company.com",
        "disabled": false,
        "locale": "en",
        "external_id": "",
        ...
      }
    },
    {
      "user": {...}
    },
    {
      "user": {...}
    }
  ]
}

POST /group


Creates a new group in the YoolinkPro account.

Parameters:

Example:

POST /group.json
name: API
category: YoolinkPro
description: API

Sample JSON Response:

{
  "group": {
    "id":42,
    "name": "API",
    "category": "YoolinkPro",
    "description": "API",
    "is_private": false,
    "is_team": false,
    "is_followed_by_default": false
  }
}

POST /team


Creates a new team in the YoolinkPro account.

Parameters:

Example:

POST /team.json
name: Marketing
description: Everything on Marketing go there.

Sample JSON Response:

{
  "team": {
    "id": 2,
    "name": "Marketing",
    "category": null,
    "description": "Everything on Marketing go there.",
    "is_private": false,
    "is_team": true,
    "is_followed_by_default": false
  }
}

POST /team/:id/join/:user_id


This method add user as member for a team corresponding to the given id.

Parameters:

Example:

POST /team/2/join/39.json

Sample JSON Response:

{
  "team": {
    "id": 2,
    "name": "Marketing",
    "category": null,
    "description": "Everything on Marketing go there.",
    "is_private": false,
    "is_team": true,
    "is_followed_by_default": false
  },
  "user": {
    "id": 39,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Doe",
    "name": "John Doe",
    "is_active": false,
    "email": "john.doe@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

POST /team/:id/leave/:user_id


This method remove user as member for a team corresponding to the given id.

Parameters:

Example:

POST /team/2/leave/39.json

Sample JSON Response:

{
  "team": {
    "id": 2,
    "name": "Marketing",
    "category": null,
    "description": "Everything on Marketing go there.",
    "is_private": false,
    "is_team": true,
    "is_followed_by_default": false
  },
  "user": {
    "id": 39,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Doe",
    "name": "John Doe",
    "is_active": false,
    "email": "john.doe@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

POST /[group|team]/:id/follow/:user_id


This method add user as follower for a group/team corresponding to the given id.

Parameters:

Example:

POST /group/42/follow/39.json

Sample JSON Response:

{
  "group": {
    "id":42,
    "name": "API",
    "category": "YoolinkPro",
    "description": "API",
    "is_private": false,
    "is_team": false,
    "is_followed_by_default": false
  },
  "user": {
    "id": 39,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Doe",
    "name": "John Doe",
    "is_active": false,
    "email": "john.doe@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

POST /[group|team]/:id/unfollow/:user_id


This method remove user as follower for a group/team corresponding to the given id.

Parameters:

Example:

POST /group/42/unfollow/39.json

Sample JSON Response:

{
  "group": {
    "id":42,
    "name": "API",
    "category": "YoolinkPro",
    "description": "API",
    "is_private": false,
    "is_team": false,
    "is_followed_by_default": false
  },
  "user": {
    "id": 39,
    "customer_id": 123,
    "slug": "company",
    "firstname": "John",
    "lastname": "Doe",
    "name": "John Doe",
    "is_active": false,
    "email": "john.doe@company.com",
    "disabled": false,
    "locale": "en",
    "external_id": "",
    ...
  }
}

GET /links/search.json


This method retrieves a link corresponding to the given url. This method needs admin privileges as it allow potentially to retrieve info from private groups.

Parameters:

Example:

GET /links/search.json?url_value=http://www.yoolinkpro.com

Sample JSON Response:

{
  "id": 123,
  "url": http://www.yoolinkpro.com,
  "title": "Yoolink Pro",
  "description": "Awesome application for the companies",
  "posts": [
    {
      id: 1234,
      user_id: 1,
      tags: "Pro,Corporate,Yoolink",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "comments": [
    {
      id: 654,
      user_id: 1,
      content: "Must be seen by the whole company",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "likes": []
}

GET /links/:id


This method retrieves a link object corresponding to the given id.

Parameters:

Example:

GET /links/123.json

Sample JSON Response:

{
  "id": 123,
  "url": http://www.yoolinkpro.com,
  "title": "Yoolink Pro",
  "description": "Awesome application for the companies",
  "posts": [
    {
      id: 1234,
      user_id: 1,
      tags: "Pro,Corporate,Yoolink",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "comments": [
    {
      id: 654,
      user_id: 1,
      content: "Must be seen by the whole company",
      created_at: "2014-03-27T22:41:26.000Z"
    }],
  "likes": []
}

GET /links.json


This method retrieves all the link objects ordered by creation date desc limited to 50.

Parameters:

Example:

GET /links.json
posted_in: My private community
is_private: true
with_comments: true

Sample JSON Response:

{
  [
    {
      "id": 123,
      "url": http://www.yoolinkpro.com,
      "title": "Yoolink Pro",
      "description": "Awesome application for the companies",
      "posts": [
        {
          id: 1234,
          user_id: 1,
          tags: "Pro,Corporate,Yoolink",
          created_at: "2014-03-27T22:41:26.000Z"
        }],
      "comments": [
        {
          id: 654,
          user_id: 1,
          content: "Must be seen by the whole company",
          created_at: "2014-03-27T22:41:26.000Z"
        }],
      "likes": []
    },
    {.....},
    {.....}
  ]
}

GET /links/:id/comments.json


This method retrieves all comments of a link object corresponding to the given id.

Parameters:

Example:

GET /links/42/comments.json

Sample JSON Response:

{
  [
    {
      id: 654,
      user_id: 1,
      content: "Must be seen by the whole company",
      created_at: "2014-03-27T22:41:26.000Z"
    },
    {
      id: 655,
      user_id: 1,
      content: "Comment to add to the link",
      created_at: "2014-03-27T23:00:04.000Z"
    }
  ]
}

Errors

This section describes all the error codes you might receive when using the YoolinkPro API. It's organized by categories corresponding ot the king of error.

  1. Internals

    Error codes representing failures during request processing.

    101.    Runtime error
    102.    Service unavailable
    
  2. Protocol

    Error codes representing protocol violation

    201.    The api key is not given (header X-YP-AppKey is mandatory)
    202.    The signature is not given (header X-YP-Signature is mandatory)
    203.    Invalid signature
    204.    Missing parameter
    205.    The api key is invalid
    
  3. Resources

    Error codes representing failures during resources handling.

    301.    Unknown resource
    302.    Create failure
    303.    Update failure
    304.    Delete failure
    
  4. User

    Error codes representing failures during user actions (that needs an identity token).

    401.    Authentication failed
    402.    Missing identitiy token
    403.    Invalid identitiy token
    404.    Expired identity token
    
  5. Administrator

    Error codes representing failures during administrator actions (that needs an admin key).

    501.   Missing Admin Key
    502.   Invalid Admin Key
    

Code Sample

Ruby


Code:

require 'base64'
require 'uri'
require 'net/http'
require 'json'

PUBLIC_KEY  = "09fdca3e7825007813820dfd9436f5bb"
PRIVATE_KEY = "bb5f6349dfd0283187005287e3acdf90"

millitime = Time.now.to_i*1000
int = rand(1000)

key = "get/user/1.json#{PRIVATE_KEY}#{millitime}#{int}"
signature = Base64.encode64(Digest::SHA1.digest(key)).gsub(/=$/, '')

uri = URI("http://api.yoolinkpro.com/user/1.json")
res = Net::HTTP.start(uri.host, uri.port) do |http|
  http.get(uri.request_uri,
    { 'X-YP-AppKey' => PUBLIC_KEY, 'X-YP-Signature' => signature, 'X-YP-MilliTime' => "#{millitime}", 'X-YP-Int' => "#{int}" })
end

puts res.body

user = JSON.parse(res.body)['user']
puts user['email']

Output:

{
  "user": {
    "id": 1,
    "customer_id": 1,
    "slug": "yoolink",
    "firstname": "Vincent",
    "lastname": "Durand",
    "name": "Vincent Durand",
    "is_active": true,
    "email": "vincent@yoolink.fr",
    "disabled": false,
    "locale": "fr",
    "external_id": "123ABC",
    "telephone": "0123456789",
    "im": "vincent.durand"
    "im_type": "3",
    "mobile_phone": "0623456789",
    "description": "Yoolink CTO",
    "birth_day": "25",
    "birth_month": "12",
    "has_full_feed": true,
    "role": "CTO",
    "past_experience": "Rails Developer",
    "education": "",
    "profile_like": "Ruby, Rails",
    "profile_dislike": "",
    "twitter_url": "",
    "facebook_url": "",
    "linkedin_url": "",
    "viadeo_url": "",
    "office_number": "1337",
    "company": "Yoolink",
    "address": "",
    "country": "France",
    "website": "http://www.yoolinkpro.com",
    "project": "YoolinkPro"
  }
}

vincent@yoolink.fr