Introduction
Informations sur l’API
Notre API est construite à partir du framework django-rest-framework. Elle
est actuellement disponible en http et https.
Les différents endpoints sont catégorisés dans des index de endpoints. Par
exemple, en envoyant une requête GET sur l’index /restapi/quotation/,
vous obtiendrez la liste de tous les endpoints qu’elle contient.
$ curl -XGET https://www.aladom.fr/restapi/offers/
{"job-offer/my":"http://www.aladom.fr/restapi/offers/job-offer/my/","subcategory":"http://www.aladom.fr/restapi/offers/subcategory/"}
Note
Pour améliorer la lisibilité des exemples de cette documentation, la
sortie des commandes curl sera filtrée par la commande
python -m json.tool de manière à indenter proprement le JSON.
$ curl -s -XGET https://www.aladom.fr/restapi/offers/ | python -m json.tool
{
"job-offer/my": "http://www.aladom.fr/restapi/offers/job-offer/my/",
"subcategory": "http://www.aladom.fr/restapi/offers/subcategory/"
}
Description des endpoints
Il est possible d’obtenir une description formelle de chaque endpoint en
utilisant la méthode OPTIONS.
$ curl -XOPTIONS https://www.aladom.fr/restapi/offers/subcategory/
{
"name": "Subcategory List",
"description": "",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
Cette description contient le nom du endpoint et une description si nécessaire.
La clé renders donne les types mime dans lesquelles la réponse peut être
formattée (à renseigner dans le header Accept de votre requête si le type
par défaut ne vous convient pas). La plupart du temps les types de réponse sont
application/json pour les appels d’API “réels” et text/html pour les
appels faits via les navigateur. Il est en effet possible de consulter l’API
via votre navigateur : https://www.aladom.fr/restapi/offers/subcategory/
Authentification
Certains endpoints nécessitent cependant une authentification. Si vous êtes connecté sur votre compte aladom, vous pourrez accéder à l’interface web de l’API. Mais pour un appel classique d’API (via curl par exemple), vous devrez utiliser le token d’authentification qui vous a été fourni par Aladom.
$ curl -XOPTIONS https://www.aladom.fr/restapi/offers/job-offer/my/
HTTP/1.1 401 Unauthorized
Content-Type: application/json
Allow: GET, POST, HEAD, OPTIONS
WWW-Authenticate: Token
{
"detail": "Informations d'authentification non fournies."
}
$ token='fedcba9876543210deadbeef0123456789abcdef'
$ curl -H"Authorization: Token $token" -XOPTIONS https://www.aladom.fr/restapi/offers/job-offer/my/
HTTP/1.1 200 OK
Content-Type: application/json
Allow: GET, POST, HEAD, OPTIONS
{
"name": "My Job Offer List",
"description": "",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "Id"
},
"city": {
"type": "field",
"required": true,
"read_only": false,
"label": "Ville",
"help_text": "Vous pouvez entrer l'ID de la ville sous forme d'entier, le code INSEE sous forme textuelle, ou bien l'alias (slug) sous forme textuelle."
},
"provider": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Annonceur"
},
"title": {
"type": "string",
"required": true,
"read_only": false,
"label": "Titre",
"max_length": 255
},
"published_on": {
"type": "datetime",
"required": false,
"read_only": true,
"label": "Publi\u00e9e le"
},
"state": {
"type": "choice",
"required": false,
"read_only": true,
"label": "\u00c9tat"
},
"hourly_wage": {
"type": "float",
"required": false,
"read_only": false,
"label": "Salaire horaire (brut)"
},
"wage": {
"type": "json",
"required": false,
"read_only": false,
"label": "info salaire",
"wage_type": {
"type": "multiple choice",
"required": false,
"read_only": false,
"label": "Type de salaire",
"choices": [
{
"value": 1,
"display_name": "Horaire"
},
{
"value": 2,
"display_name": "Mensuel"
},
{
"value": 3,
"display_name": "Annuel"
},
]
},
"wage": {
"type": "float",
"required": false,
"read_only": false,
"label": "Salaire",
},
},
"application_email": {
"type": "email",
"required": false,
"read_only": false,
"label": "E-mail pour candidater",
"max_length": 255
},
"contract_types": {
"type": "multiple choice",
"required": false,
"read_only": false,
"label": "Types de contrat",
"choices": [
{
"value": 1,
"display_name": "CDI"
},
{
"value": 2,
"display_name": "CDD"
},
{
"value": 3,
"display_name": "Int\u00e9rim"
},
{
"value": 4,
"display_name": "Stage"
},
{
"value": 5,
"display_name": "Apprentissage"
},
{
"value": 6,
"display_name": "Autre"
}
]
},
"url": {
"type": "field",
"required": false,
"read_only": true,
"label": "Url"
}
}
}
}
La réponse ci-dessus (qui a été tronquée pour ne pas prendre trop de place)
présente la clé actions qui liste les champs qu’il est possible de
récupérer ou envoyer.
Chaque champ est décrit par :
typele type de donnée attenduerequiredle caractère obligatoire ou nonread_onlyla possibilité ou non de modifier ce champlabelle nom du champ en françaishelp_textune éventuelle précision concernant ce champ
Certains types de champs précisent également d’autres informations comme les choix possibles par exemple.
Récupérer des données
Il existe deux grands types de endpoints permettant de récupérer des données. Les endpoints de type “liste” et ceux de type “item”.
Récupérer une liste
Les endpoints proposant une liste contenant peu d’éléments renvoient simplement un tableau JSON. Par exemple :
$ curl -XGET https://www.aladom.fr/restapi/offers/subcategory/
[
{
"id": 1,
"name": "Aide aux personnes handicap\u00e9es",
"slug": "aide-personnes-handicapees",
"category": "Aide au handicap",
"category_id": 1
},
{
"id": 2,
"name": "Langue des signes",
"slug": "langue-des-signes",
"category": "Aide au handicap",
"category_id": 1
},
{
"id": 3,
"name": "Transport handicap\u00e9",
"slug": "transport-handicape",
"category": "Aide au handicap",
"category_id": 1
}
]
Dans certains cas cependant, le nombre de résultats est potentiellement trop grand pour être renvoyé en une seule réponse et doit être paginé. Dans ce cas, cet un dictionnaire qui est renvoyé avec les clés suivantes :
countle nombre total de résultatsnexturl vers la page suivante le cas échéantpreviousurl vers la page précédente le cas échéantresultsla liste des résultats
$ curl -XGET https://www.aladom.fr/restapi/offers/job-offer/my/
{
"count": 33233,
"next": "http://www.aladom.fr/restapi/offers/job-offer/my/?limit=100&offset=100",
"previous": null,
"results": [
{
"id": 123456,
"subcategory": {
"id": 26,
"slug": "cours-economie",
"name": "Cours d'\u00e9conomie"
},
"city": {
"id": 30640,
"code": "74152",
"slug": "lovagny",
"name": "Lovagny"
},
},
{
"id": 654321,
}
]
}
Récupérer un item
Pour récupérer un item en particulier en connaissant son ID, il suffit de rajouter l’ID à la fin de l’URL :
$ curl -XGET https://www.aladom.fr/restapi/offers/subcategory/26/
{
"id": 26,
"name": "Cours d'\u00e9conomie",
"slug": "cours-economie",
"category": "Soutien scolaire",
"category_id": 5
}
Envoyer de données
Il y a également deux grands types de endpoints permettant d’envoyer des données. Les endpoints de création et ceux de modification.
Création d’un item
La création d’un item se fait en utilisant la méthode POST sur l’URL
de listing. Les données doivent être envoyées au format JSON et respecter
la spécification donnée par la méthode OPTIONS.
En cas de succès, vous obtiendrez une réponse 201 au format JSON,
contenant les détails de l’objet créé.
$ curl -XPOST -H'Content-Type:application/json' -d '{"city": "rennes", "provider": 153514, "title": "test", "subcategory": 33, "content": "Test Test"}' https://www.aladom.fr/restapi/offers/job-offer/my/
{
"adhoc_mission_hours": null,
"adhoc_mission_price": null,
"application_email": "",
"application_phone": "",
"city": {
"code": "35238",
"id": 13811,
"name": "Rennes",
"slug": "rennes"
},
"content": "Test Test",
"contract_duration": null,
"contract_types": [],
"cv_required": false,
"hourly_wage": null,
"id": 1947561,
"is_adhoc_mission": false,
"is_full_time": false,
"is_part_time": false,
"latitude": null,
"longitude": null,
"minimum_age": 18,
"minimum_experience": null,
"origin_reference": "",
"origin_source": "",
"pole_emploi_id": null,
"pole_emploi_reject_reason": "",
"pole_emploi_state": "",
"provider": 153514,
"published_on": "2018-02-15T11:14:58.525928",
"start_date": null,
"state": 1,
"subcategory": {
"id": 33,
"name": "M\u00e9nage",
"slug": "menage"
},
"title": "test",
"url": "http://www.aladom.fr/emploi/test-rennes-15qqx.html",
"vehicle_required": false,
"weekly_hours": null
}
En cas d’erreur vous obtiendrez une réponse 400 au format JSON. Elle
contiendra un dictionnaire dont chaque clé sera un des champs erroné et
la valeur sera un tableau contenant la description en français des erreurs
rencontrées sur le champ en question.
$ curl -XPOST -H'Content-Type:application/json' -d '{"city": "rennes", "provider": 15354, "title": "test", "subcategory": 33}' https://www.aladom.fr/restapi/offers/job-offer/my/
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"provider": [
"Vous ne gérez pas le compte du membre '15354'"
],
"content": [
"Ce champ est obligatoire."
]
}
Modification d’un item
La modification d’un item se fait par la méthode PATCH sur l’URL d’item.
Elle fonctionne de la même manière que la création d’un item, à l’exception
que les champs que vous ne souhaitez pas modifier ne sont pas requis.
$ curl -XPATCH -H'Content-Type: application/json' -d '{"city": "35278", "title": "Test"}' https://www.aladom.fr/restapi/offers/job-offer/my/1947561/
{
"adhoc_mission_hours": null,
"adhoc_mission_price": null,
"application_email": "",
"application_phone": "",
"city": {
"code": "35278",
"id": 14146,
"name": "Saint-Gr\u00e9goire",
"slug": "saint-gregoire"
},
"content": "Test Test",
"contract_duration": null,
"contract_types": [],
"cv_required": false,
"hourly_wage": null,
"id": 1947561,
"is_adhoc_mission": false,
"is_full_time": false,
"is_part_time": false,
"latitude": null,
"longitude": null,
"minimum_age": 18,
"minimum_experience": null,
"origin_reference": "",
"origin_source": "",
"pole_emploi_id": null,
"pole_emploi_reject_reason": "",
"pole_emploi_state": "",
"provider": 153514,
"published_on": "2018-02-15T11:14:58.525928",
"start_date": null,
"state": 1,
"subcategory": {
"id": 33,
"name": "M\u00e9nage",
"slug": "menage"
},
"title": "Test",
"url": "http://www.aladom.fr/emploi/test-rennes-15qqx.html",
"vehicle_required": false,
"weekly_hours": null
}
Types de champs
integer
Les champs de type integer représentent un entier, présenté en tant que tel
au format JSON.
Ces champs peuvent définir une valeur minimum et une valeur maximum,
respectivement avec les clés max_value et min_value.
float
Les champs de type float représentent un nombre réel, présenté en tant que
tel au format JSON.
Ces champs peuvent définir une valeur minimum et une valeur maximum,
respectivement avec les clés max_value et min_value.
boolean
Les champs de type boolean représentent une information binaire pouvant
prendre la valeur true ou false.
string
Les champs de type string représentent une chaine de caractères, présentée
en tant que tel au format JSON. Le nombre de caractères peut être limité, ce
qui est spécifiée par la clé max_length.
email
Les champs de type email sont des champs de type string destinés à
recevoir une adresse e-mail.
datetime
Les champs de type datetime sont des champs de type string destinés à
recevoir un horodatage au format ISO-8601.
choice
Les champs de type choice sont des champs dont les valeurs possibles sont
limitées. La liste des choix possibles est précisée par la clé choices.
La clé choices se présente sous la forme d’une liste dont chaque élément
est un choix possible, décrit par la clé value (la valeur effective) et la
clé display_name (la signification en français).
multiple choice
Les champs de type multiple choice sont similaires aux champs de type
choice mais se présentent sous la forme d’un tableau JSON, permettant de
sélectionner plusieurs choix parmis les valeurs indiquées par la clé
choices.
field
Les champs de type field sont des champs personnalisés. Si le nom du champ
n’est pas suffisamment explicite, la valeur attendue est précisée dans la
clé help_text.
nested object
Les champs de type nested object sont des champs qui contiennent eux-mêmes
d’autres champs. La liste des champs imbriqués possibles est définie par la
clé children.
Webhooks
Il vous est possible de mettre en place des webhooks de manière à être notifiés en direct lorsque certains événements se produisent de notre côté :
Transmission d’un lead
Transmission d’un contact direct
Transmission d’une nouvelle candidature
Mettre en place un webhook
Si vous avez déjà accès à notre API, il vous suffit d’envoyer une requête POST à l’adresse https://www.aladom.fr/restapi/utils/webhooks/setup/ en précisant l’URL sur laquelle vous voulez que les données vous soient envoyées. Vous recevrez en réponse le token d’authentification que nous utiliserons dans les requêtes que nous vous enverrons.
Si vous n’avez pas encore accès à notre API, contactez nous pour en demander un.
$ token='fedcba9876543210deadbeef0123456789abcdef'
$ curl -H"Authorization: Token $token" -XPOST -d 'url=https://exemple.fr/aladom.wh' https://www.aladom.fr/restapi/utils/webhooks/setup/
{
"token": "A486kFbdNn1rvesf79ulN+ozyqPUqeRxc2aMBBwT",
"url": "https://exemple.fr/aladom.wh"
}
Une fois cette opération effectuée, les événements vous serons envoyés par
requête POST avec le header
Authorization: Token A486kFbdNn1rvesf79ulN+ozyqPUqeRxc2aMBBwT
Un header X-User-ID contenant l’ID de l’utilisateur concerné sera aussi
envoyé. Si vous gerez un réseau, ce header vous permettra de différencier les
agences. Pour obtenir la liste des utilisateurs que vous gérez, vous pouvez
envoyer une requête GET à l’adresse
https://www.aladom.fr/restapi/user/member/my/managed_users/
Nous vous enverrons également un headers X-Webhook-Version contenant un
numéro de version qui changera à chaque fois que des modifications seront
apportées à nos webhooks. Notez cependant que chaque nouvelle version sera
rétro-compatible, seuls des champs seront ajoutés.
Traiter les requêtes reçues
Les requêtes vous seront envoyées au format JSON. Le JSON envoyé comportera
toujours la clé event. Comme tous les événements sont envoyés à la même
adresse, cette clé permet de vous indiquer de quel type d’événement il s’agit.
C’est la première chose à vérifier, pour brancher correctement la suite du
traitement. Si la valeur de event ne fait pas partie des valeurs que vous
supportez, renvoyez un status code 501 (Not Implemented).
Pour les autres clés, référez-vous à la documentation de chaque événement. Dans
la plupart des cas, un objet vous sera envoyé dans la clé object et le type
de cet objet sera précisé par la clé type.
Si nous recevons une réponse 500, 502, 503, 504 ou si une erreur
de connexion survient, nous ferons jusqu’à 4 nouvelles tentatives avant
d’abandonner définitivement. D’autre part, si votre serveur ne répond pas en
moins de 10 secondes, la requête sera abandonnée.
Sauf cas particulier précisé dans la documentation de chaque événement, nous
n’attendons aucune réponse particulière et toutes les réponses autres que
500, 502, 503 et 504 seront traitées de la même manières.
Cependant, nous loggons le status code reçu pour chaque requête envoyée. Pour
débugger d’éventuels problèmes, il est donc préférable de retourner un code
HTTP pertinent.
Exemple d’implémentation en Python
import json
import warnings
from django.views.generic import View
class AladomWebhookView(View):
def get(self, request, *args, **kwargs):
authorization = request.META.get('HTTP_AUTHORIZATION')
if authorization != 'Token {}'.format(settings.ALADOM_WEBHOOK_TOKEN)
response = HttpResponse(status=401)
response['WWW-Authenticate'] = 'Token realm="aladom webhook"'
return response
version = request.META.get('HTTP_X_WEBHOOK_VERSION')
if version != settings.ALADOM_WEBHOOK_VERSION:
warnings.warn(
"New Aladom Webhook version available : {}".format(version)
)
event = json.loads(request.body.decode('utf-8'))
if event['event'] == 'new_lead':
handler = self.handle_new_lead
elif event['event'] == 'new_candidacy':
handler = self.handle_new_candidacy
elif event['event'] == 'new_contact_quote':
handler = self.handle_new_contact_quote
else:
warnings.warn("Unknown Aladom event: {}".format(event['event']))
return HttpResponse(status=501)
response = handler(event)
if response:
return response
return HttpResponse(status=204)
def handle_new_lead(self, event):
if event['type'] == 'quotation.CleaningQuoteRequest':
handler = self.record_cleaning_lead
elif event['type'] == 'quotation.HomeFurnishingsQuoteRequest':
handler = self.record_home_furnishings_lead
elif event['type'] == 'quotation.CraftsQuoteRequest':
handler = self.record_crafts_lead
elif event['type'] == 'quotation.HelpQuoteRequest':
handler = self.record_help_lead
elif event['type'] == 'quotation.ChildcareQuoteRequest':
handler = self.record_childcare_lead
elif event['type'] == 'quotation.MusicQuoteRequest':
handler = self.record_music_lead
elif event['type'] == 'quotation.TutoringQuoteRequest':
handler = self.record_tutoring_lead
else:
warnings.warn("Unknown Aladom lead type: {}".format(event['type']))
return HttpResponse(status=501)
return handler(event['object'])
def handle_new_candidacy(self, event):
pass
def handle_new_contact_quote(self, event):
pass
def record_cleaning_lead(self, lead):
pass
def record_home_furnishings_lead(self, lead):
pass
def record_crafts_lead(self, lead):
pass
def record_help_lead(self, lead):
pass
def record_childcare_lead(self, lead):
pass
def record_music_lead(self, lead):
pass
def record_tutoring_lead(self, lead):
pass
Modifier les informations du webhook
Si vous avez perdu le token d’authentification, s’il a été corrompu ou si l’URL du webhook a changé, vous pouvez rappeler le même endpoint pour nous communiquer la nouvelle URL et régénérer le token.
$ token='fedcba9876543210deadbeef0123456789abcdef'
$ curl -H"Authorization: Token $token" -XPOST -d 'url=https://www.exemple.com/aladom.wh' https://www.aladom.fr/restapi/utils/webhooks/setup/
{
"token": "1CtBRWjgmBeQmPipqk8jj/5H0mFDP272MMz1TDme",
"old_url": "https://exemple.fr/aladom.wh",
"url": "https://www.exemple.com/aladom.wh"
}