Versioning Principle
The API version number is included in the base URL:
https://jobaffinity.fr/restapi/v1
Changes Without Version Update
The following modifications do not require a major version change:
- URL modifications (other than the base URL)
- Addition of new fields in a response
- Addition of new request parameters
- Addition/removal/modification of ENUM values
- Modification of pagination page sizes
Your code should be designed to ignore unknown fields in responses to remain compatible with these evolutions.
Changes With Version Update
A major version change (e.g., v1 → v2) will only occur for:
- Removal of existing fields
- Change in data type of a field
- Incompatible behavior change
- Modifications that may cause client malfunctions
Version Monitoring
Fields to Monitor
Regularly query the root resource to monitor changes:
GET https://jobaffinity.fr/restapi/v1
Important fields:
_version: Current minor version (e.g., “1.10”)
_last_version_url: URL of the latest available version
_expiration: Expiration date of the current version
_changelog: Link to modification history
Example Response
{
"_status": "OK",
"_self": "/restapi/v1",
"_version": "1.10",
"_last_version_url": "/restapi/v1",
"_expiration": null,
"_changelog": {
"_self": "/restapi/changelog"
}
}
Interpretation
| Situation | Meaning | Action |
|---|
_last_version_url == _self | You’re using the latest version | ✅ No action required |
_last_version_url != _self | A new version is available | ⚠️ Plan a migration |
_expiration == null | No expiration planned | ✅ Stable version |
_expiration != null | Version will be disabled on the indicated date | 🚨 Urgent migration required |
Setting Up Alerts
Monitoring Script (Python)
import requests
from datetime import datetime
def check_api_version():
"""Checks the API version status"""
response = requests.get(
'https://jobaffinity.fr/restapi/v1',
auth=('login', 'password')
)
data = response.json()
# Check if a new version is available
if data['_last_version_url'] != data['_self']:
print(f"⚠️ ALERT: New version available!")
print(f" Current URL: {data['_self']}")
print(f" New URL: {data['_last_version_url']}")
# Check expiration
if data['_expiration']:
expiration_date = datetime.fromisoformat(data['_expiration'])
days_remaining = (expiration_date - datetime.now()).days
print(f"🚨 CRITICAL ALERT: Version expires in {days_remaining} days")
print(f" Expiration date: {data['_expiration']}")
print(f" See: https://jobaffinity.fr{data['_changelog']['_self']}")
return data
# Run periodically (e.g., via cron)
check_api_version()
Monitoring Script (Shell)
#!/bin/bash
RESPONSE=$(curl -s --basic --user "login:password" \
"https://jobaffinity.fr/restapi/v1")
EXPIRATION=$(echo "$RESPONSE" | jq -r '._expiration // empty')
if [ ! -z "$EXPIRATION" ]; then
echo "🚨 ALERT: API version expires on $EXPIRATION"
echo "Consult the changelog to migrate"
# Send alert (email, Slack, etc.)
exit 1
fi
Migration Process
When a new major version is announced:
Transition period
Both versions (old and new) remain accessible simultaneously
Test the new version
Test your integration with the new URL provided by _last_version_url
Adapt your code
Make necessary modifications for compatibility
Deploy changes
Update your production code before the expiration date
Post-migration monitoring
Verify that everything works correctly with the new version
Changelog
The changelog is accessible via the URL provided in the root response:
https://jobaffinity.fr/restapi/changelog
It documents:
- New features
- Bug fixes
- Behavior changes
- Deprecations
- Migration announcements
Regularly consult the changelog to discover new possibilities and optimize your integration.
Best Practices
Design for Compatibility
- Ignore unknown fields: Don’t fail on unrecognized fields
- Use provided URLs: Never manually construct URLs
- Version your code: Keep track of which API version is used
- Test regularly: Validate your integration with each minor evolution
Robust Code Example (Python)
import requests
class JobAffinityAPI:
def __init__(self, auth):
self.auth = auth
self.base_url = 'https://jobaffinity.fr/restapi/v1'
def get_resource(self, url=None):
"""Fetches a resource using provided URLs"""
if url is None:
url = self.base_url
response = requests.get(url, auth=self.auth)
data = response.json()
# Automatically ignore unknown fields
return data
def check_version_status(self):
"""Checks version status"""
root = self.get_resource()
return {
'current_version': root.get('_version'),
'is_latest': root.get('_last_version_url') == root.get('_self'),
'expiration': root.get('_expiration'),
'changelog_url': root.get('_changelog', {}).get('_self')
}
# Usage
api = JobAffinityAPI(auth=('login', 'password'))
status = api.check_version_status()
if not status['is_latest']:
print("⚠️ New version available")
if status['expiration']:
print(f"🚨 Migration required before {status['expiration']}")
Support
For any migration questions: