5.4.1 Élément DocumentSearchRequest requis
Processus d’intégration étape par étape
Ces étapes décrivent le processus d’intégration d’un client à Surescripts Data Solutions, de la configuration du compte jusqu’aux téléchargements de données.
ăndarăt
Remarque: Il s’agit d’une documentation Early Adopter. Les exigences et le contenu peuvent changer.

Étape 1 : Vérifier l’accès à Data Package Builder dans Workbench
- Pour obtenir des instructions sur la configuration de l’accès, consultez les instructions Configuration de l’accès à Workbench et Data Package Builder .
Étape 2 : Générer des clés
Étape 2a : Générer des paires de clés RSA pour l’authentification de Data Package Builder
Pour vous authentifier auprès de l’API Data Package Builder, vous devez générer une paire de clés RSA de 2048 bits et téléverser la clé publique via l’interface Client Keys.
Option 1 : Utilisation de Open SSL (recommandé - fonctionne sous Linux, macOS et Windows)
- Générez une clé privée RSA de 2048 bits.
-

openssl genrsa -out private_key.pem 2048- Extrayez la clé publique.
openssl req -new -x509 -key privatekey.pem -out publickey509.pem -subj '/CN=data-package-builder'- Vérifiez vos paires de clés.
# View the private key
cat privatekey.pem
# View the public key
cat publickey509.pemOption 2 : Utilisation de PowerShell (Windows)
- Générez une paire de clés RSA.
$rsa = [System.Security.Cryptography.RSA]::Create(2048)- Exportez la clé publique au format X.509 SubjectPublicKeyInfo.
$publicKey = $rsa.ExportSubjectPublicKeyInfo()
$publicPem = "-----BEGIN PUBLIC KEY-----`n" +
[Convert]::ToBase64String($publicKey, 'InsertLineBreaks') +
"`n-----END PUBLIC KEY-----"
$publicPem | Out-File -FilePath "public_key.pem" -Encoding ASCII- Exportez la clé privée.
$privateKey = $rsa.ExportRSAPrivateKey()
$privatePem = "-----BEGIN RSA PRIVATE KEY-----`n" +
[Convert]::ToBase64String($privateKey, 'InsertLineBreaks') +
"`n-----END RSA PRIVATE KEY-----"
$privatePem | Out-File -FilePath "private_key.pem" -Encoding ASCII
Write-Host "Keys generated successfully!"
Write-Host "Public key is in X.509 SubjectPublicKeyInfo format"Ce que vous obtiendrez :

Après la génération de la paire de clés, vous disposerez de deux fichiers :
- private_key.pem - Votre clé privée - CRITIQUE: Conservez-la en sécurité - Stockez-la dans un emplacement sécurisé (HSM, coffre-fort de clés, stockage chiffré) - Elle sera utilisée pour signer un JWT compact afin de demander un jeton d’accès au serveur d’autorisation
- public_key.pem - Votre clé publique - C’est ce que vous téléversez dans Data Package Builder - Peut être partagée en toute sécurité (elle est dite « publique » pour une raison) - Exemple de format : -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Z3VS5JJcds3... -----END PUBLIC KEY-----
Étape 2b : Téléverser votre clé publique
- Connectez-vous à Générateur de paquet de données.
- Accédez à Clés du client.
- Collez l’intégralité du contenu de public_key.pem (y compris les lignes BEGIN/END).
- Cliquez sur Créer un client.
- Remarque : Cela créera le Client_ID que le client utilisera plus tard dans la section Construire l’assertion JWT compacteÉtape 4a : Construire la section d’assertion JWT .
⚠️ Important : Une fois que vous avez créé votre ID client, informez votre point de contact Surescripts. Surescripts doit configurer votre package de données avant que vous puissiez passer aux étapes suivantes.
Vous ne pourrez pas continuer tant que cette configuration ne sera pas terminée.

Bonnes pratiques de sécurité :
✅ À FAIRE :
- Générez les clés dans un environnement sécurisé
- Stockez les clés privées dans un coffre de clés ou un HSM pour une utilisation en production
- Utilisez des permissions de fichier strictes pour les fichiers de clés privées (chmod 600 private_key.pem sur Unix)
- Effectuez une rotation des clés périodiquement
❌ À NE PAS FAIRE :
- Partager ou envoyer des clés privées vers un système de contrôle de version
- Envoyer des clés privées par courriel
- Stocker des clés privées en texte brut dans le code de l’application
- Réutiliser la même paire de clés pour plusieurs clients/applications
Étape 2c : Erreurs courantes
Le tableau ci-dessous comprend des informations sur les erreurs courantes pouvant être rencontrées lors de la création de paires de clés.
Erreur | Informations de dépannage |
|---|---|
Erreur « Invalid certificate/public key format » |
|
La clé semble être téléversée, mais l’authentification échoue |
|
Étape 3 : Query Builder
Le Générateur de requêtes dans Workbench vous aide à créer une URL de requête OData qui définit exactement les données de médicaments prescrits que vous souhaitez récupérer depuis l’API Data Solutions. Vous pouvez créer une requête visuellement ou la modifier directement, selon votre préférence.
Remarque : Le Query Builder est facultatif; les utilisateurs expérimentés peuvent soumettre des requêtes OData manuelles directement.
OData n’est pas le seul type de requête pris en charge. Pour plus d’informations sur les autres utilisations du Query Builder, consultez Vue d’ensemble du Query Builder .
Pour plus d’informations sur OData, consultez https://learn.microsoft.com/en-us/odata/overview
Important : Avant de commencer :
- Vous devez pouvoir vous connecter à Workbench.
- Votre utilisateur doit avoir accès à Générateur de paquet de données avec le rôle Modifier la requête.
- Vous devez utiliser le produit Médicament prescrit dans Data Solutions.
- Pour obtenir des instructions à ce sujet, consultez Configuration de l’accès à Workbench et Data Package Builder .
Étape 3a : Exécuter Query Builder (OData)
- Connectez-vous à Établi et ouvrez Générateur de paquet de données.
- Sélectionnez Générateur de requêtes.
- Choisissez le produit Médicament prescrit.
- Sélectionnez les colonnes que vous souhaitez retourner (elles correspondent à $select dans OData).
- Ajoutez des filtres pour limiter les résultats.
- Un filtre PARTITION_DAY est requis.
- Sélectionnez Générer à partir des sélections pour créer automatiquement la requête OData (ou modifiez manuellement la requête si vous connaissez bien OData).
- Copiez l’URL de requête OData générée.
- Utilisez l’URL dans votre requête GET de l’API Data Solutions pour récupérer les données de Prescribed Medication.
Remarque : Pour obtenir des informations sur l’exécution de Query Builder pour d’autres cas d’utilisation, consultez Étapes clés (s’applique à tous les cas d’utilisation)
Étape 4 : Déterminer le filtre PARTITION_DAY
Pour déterminer quel filtre PARTITION_DAY demander, consultez la page Comment utiliser les endpointsComment utiliser les endpoints .
Étape 5 : Envoyer des requêtes REST à l’API Data Solutions
Authentification
Apprenez à vous authentifier auprès de l’API Data Solutions à l’aide du flux OAuth 2.0 Client Credentials Grant avec JWT Bearer Assertion.
Ce que vous allez faire
L’API Data Solutions utilise un processus d’authentification en deux étapes :
- Créer une assertion JWT - Créez et signez une revendication JWT à l’aide de votre ClientID et de votre clé privée
- Demander un jeton d’accès - Échangez l’assertion JWT contre un jeton d’accès OAuth au endpoint /connect/token du serveur d’authentification
- Utiliser le jeton d’accès - Incluez le jeton d’accès dans les requêtes API
┌─────────────┐ ┌─────────────┐
│ Client │ │ Auth Server │
└──────┬──────┘ └──────┬──────┘
│ │
│ 1. Build JWT assertion │
│ (signed with private key) │
│ │
│ 2. POST /connect/token │
│ (client_assertion = JWT) │
├─────────────────────────────────────────────>│
│ │
│ 3. Access token response │
│<─────────────────────────────────────────────┤
│ │
│ │
│ ┌──────────────────┴─────┐
│ │ Data Solutions API │
│ └──────────────────┬─────┘
│ │
│ 4. API request with access token │
├─────────────────────────────────────────────>│
│ │
│ 5. Data response │
│<─────────────────────────────────────────────┤
│ │Avant de commencer
Assurez-vous d’avoir :
- ID client - Un identifiant unique pour votre application.
- Clé privée - Une clé privée RSA au format PKCS#8 PEM.
- Enregistrement de la clé publique - Votre clé publique doit être enregistrée auprès du serveur d’authentification pour votre ID client.
Format de la clé privée
Votre clé privée doit être au format PKCS#8 PEM :
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC...
... base64 encoded key data ...
-----END PRIVATE KEY-----Étape 5a : Créer l’assertion JWT compacte
Créez un JWT avec la structure suivante, signé avec votre clé privée à l’aide de l’algorithme RS384 (RSASSA-PKCS1-v1_5 avec SHA-384). Ce JWT prouve votre identité au serveur d’authentification.
En-tête JWT
{
"alg": "RS384",
"typ": "JWT"
}Payload JWT
{
"iss": "your-client-id", // Issuer: your client ID
"sub": "your-client-id", // Subject: your client ID
"aud": "ENVIRONMENT_AUTH_URL/connect/token", // Audience: token endpoint URL
"jti": "550e8400-e29b-41d4-a716-446655440000", // JWT ID: unique identifier (UUID)
"iat": 1706572800, // Issued at: current Unix timestamp
"nbf": 1706572800, // Not before: current Unix timestamp
"exp": 1706573100 // Expires: current timestamp + 5 minutes
}Remarques importantes sur les champs :
- iss et sub doivent tous deux être votre ID client
- aud doit être l’URL exacte du point de terminaison du jeton (y compris /connect/token)
- jti doit être unique pour chaque requête (utilisez un UUID)
- exp doit être à 5 minutes de iat (maximum recommandé)
Exemple : Création d’un JWT en Python
import jwt
import uuid
import time
from datetime import datetime, timedelta
# Your credentials
client_id = "your-client-id"
private_key = """-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC...
-----END PRIVATE KEY-----"""
token_endpoint = "ENVIRONMENT_AUTH_URL/connect/token"
# Build the JWT payload
now = int(time.time())
payload = {
"iss": client_id,
"sub": client_id,
"aud": token_endpoint,
"jti": str(uuid.uuid4()),
"iat": now,
"nbf": now,
"exp": now + 300 # 5 minutes from now
}
# Sign the JWT with RS384
client_assertion = jwt.encode(
payload,
private_key,
algorithm="RS384"
)
print(f"JWT Assertion: {client_assertion}")Exemple : Création d’un JWT en C#
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;
// Your credentials
var clientId = "your-client-id";
var privateKeyPem = @"-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC...
-----END PRIVATE KEY-----";
var tokenEndpoint = "ENVIRONMENT_AUTH_URL/connect/token";
// Load the private key
using var rsa = RSA.Create();
rsa.ImportFromPem(privateKeyPem);
var signingCredentials = new SigningCredentials(
new RsaSecurityKey(rsa),
SecurityAlgorithms.RsaSha384
);
// Build the JWT
var now = DateTime.UtcNow;
var handler = new JwtSecurityTokenHandler();
var token = handler.CreateJwtSecurityToken(
issuer: clientId,
audience: tokenEndpoint,
subject: new ClaimsIdentity(new[] { new Claim("sub", clientId) }),
notBefore: now,
expires: now.AddMinutes(5),
issuedAt: now,
signingCredentials: signingCredentials
);
// Add the jti claim
token.Payload["jti"] = Guid.NewGuid().ToString();
var clientAssertion = handler.WriteToken(token);
Console.WriteLine($"JWT Assertion: {clientAssertion}");Exemple : Création d’un JWT en JavaScript/Node.js
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');
const fs = require('fs');
// Your credentials
const clientId = 'your-client-id';
const privateKey = fs.readFileSync('private_key.pem', 'utf8');
const tokenEndpoint = 'ENVIRONMENT_AUTH_URL/connect/token';
// Build the JWT payload
const now = Math.floor(Date.now() / 1000);
const payload = {
iss: clientId,
sub: clientId,
aud: tokenEndpoint,
jti: uuidv4(),
iat: now,
nbf: now,
exp: now + 300 // 5 minutes
};
// Sign the JWT with RS384
const clientAssertion = jwt.sign(payload, privateKey, {
algorithm: 'RS384'
});
console.log(`JWT Assertion: ${clientAssertion}`);Étape 5b : Demander un jeton d’accès
Envoyez une requête POST au point de terminaison /connect/token du serveur d’authentification avec l’assertion JWT.
Format de la requête
POST /connect/token HTTP/1.1
Host: ENVIRONMENT_AUTH_URL
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=your-client-id
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<your-signed-jwt>
&scope=DsaApiParamètres :
- grant_type - Doit être identifiants_client
- identifiant_client - Votre identifiant client
- client_assertion_type - Doit être urn:ietf:params:oauth:client-assertion-type:jwt-bearer
- client_assertion - Le JWT signé de l’étape 1
- portée - Doit être DsaApi pour accéder à l’API Data Solutions
Exemple : Demander un jeton en Python
import requests
# Build the token request
token_url = "ENVIRONMENT_AUTH_URL/connect/token"
data = {
"grant_type": "client_credentials",
"client_id": client_id,
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": client_assertion,
"scope": "DsaApi"
}
# Request the access token
response = requests.post(token_url, data=data)
response.raise_for_status()
token_response = response.json()
access_token = token_response["access_token"]
expires_in = token_response["expires_in"]
print(f"Access Token: {access_token}")
print(f"Expires in: {expires_in} seconds")Exemple : Demander un jeton en C#
using System.Net.Http;
var httpClient = new HttpClient();
var tokenUrl = "ENVIRONMENT_AUTH_URL/connect/token";
var requestData = new Dictionary<string, string>
{
{ "grant_type", "client_credentials" },
{ "client_id", clientId },
{ "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" },
{ "client_assertion", clientAssertion },
{ "scope", "DsaApi" }
};
var response = await httpClient.PostAsync(tokenUrl, new FormUrlEncodedContent(requestData));
response.EnsureSuccessStatusCode();
var tokenResponse = await response.Content.ReadFromJsonAsync<TokenResponse>();
var accessToken = tokenResponse.AccessToken;
var expiresIn = tokenResponse.ExpiresIn;
Console.WriteLine($"Access Token: {accessToken}");
Console.WriteLine($"Expires in: {expiresIn} seconds");
// Token response model
public class TokenResponse
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }
[JsonPropertyName("token_type")]
public string TokenType { get; set; }
}Exemple : Demander un jeton en JavaScript/Node.js
const axios = require('axios');
const qs = require('querystring');
const tokenUrl = 'ENVIRONMENT_AUTH_URL/connect/token';
const requestData = {
grant_type: 'client_credentials',
client_id: clientId,
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: clientAssertion,
scope: 'DsaApi'
};
axios.post(tokenUrl, qs.stringify(requestData), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.then(response => {
const accessToken = response.data.access_token;
const expiresIn = response.data.expires_in;
console.log(`Access Token: ${accessToken}`);
console.log(`Expires in: ${expiresIn} seconds`);
})
.catch(error => {
console.error('Token request failed:', error.response?.data || error.message);
});Réponse réussie
{
"access_token": "eyJhbGciOiJSUzM4NCIsImtpZCI6IjEyMzQ1Njc4OTAiLCJ0eXAiOiJKV1QifQ...",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "DsaApi"
}Réponse d’erreur
{
"error": "invalid_client",
"error_description": "Invalid client or client credentials"
}Codes d’erreur courants :
- client_invalide - ID client introuvable ou incompatibilité de clé publique
- invalid_grant - Échec de la validation de l’assertion JWT
- champ_d’application_invalide - La portée demandée n’est pas disponible
Étape 5c : Utiliser le jeton d’accès dans les requêtes de l’API Data Solutions
Incluez le jeton d’accès dans l’en-tête Autorisation de vos requêtes API.
Format de la requête
GET /api/v0/odata/PrescribedMedicationData?$filter=PARTITION_DAY eq '2025-01-30' HTTP/1.1
Host: ENVIRONMENT_DATA_SOLUTIONS_URL
Authorization: Bearer <your-access-token>Exemple : Requête API en Python
import requests
api_url = "ENVIRONMENT_DATA_SOLUTIONS_URL/api/v0/odata/PrescribedMedicationData"
headers = {
"Authorization": f"Bearer {access_token}"
}
params = {
"$filter": "PARTITION_DAY eq '2025-01-30'",
"$top": 10
}
response = requests.get(api_url, headers=headers, params=params)
response.raise_for_status()
data = response.json()
print(f"Retrieved {len(data['value'])} records")Exemple : Requête API en C#
var apiUrl = "ENVIRONMENT_DATA_SOLUTIONS_URL/api/v0/odata/PrescribedMedicationData";
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
var queryParams = new Dictionary<string, string>
{
{ "$filter", "PARTITION_DAY eq '2025-01-30'" },
{ "$top", "10" }
};
var queryString = string.Join("&", queryParams.Select(kvp =>
$"{Uri.EscapeDataString(kvp.Key)}={Uri.EscapeDataString(kvp.Value)}"));
var requestUrl = $"{apiUrl}?{queryString}";
var response = await httpClient.GetAsync(requestUrl);
response.EnsureSuccessStatusCode();
var data = await response.Content.ReadFromJsonAsync<ODataResponse>();
Console.WriteLine($"Retrieved {data.Value.Count} records");Exemple : requête API en JavaScript/Node.js
const axios = require('axios');
const apiUrl = 'ENVIRONMENT_DATA_SOLUTIONS_URL/api/v0/odata/PrescribedMedicationData';
const headers = {
'Authorization': `Bearer ${accessToken}`
};
const params = {
'$filter': "PARTITION_DAY eq '2025-01-30'",
'$top': 10
};
axios.get(apiUrl, { headers, params })
.then(response => {
console.log(`Retrieved ${response.data.value.length} records`);
})
.catch(error => {
console.error('API request failed:', error.response?.data || error.message);
});Étape 5d : gérer l’expiration du jeton
Les jetons d’accès expirent après la durée spécifiée dans le champ expire_dans (généralement 3600 secondes / 1 heure).
Bonnes pratiques :
- Stockez le jeton et son heure d’expiration
- Vérifiez si le jeton est expiré avant chaque requête
- Demandez un nouveau jeton lorsque le jeton actuel expire ou est sur le point d’expirer
- Ajoutez une marge de sécurité (par exemple, actualisez 5 minutes avant l’expiration réelle)
Exemple : gestion des jetons en Python
from datetime import datetime, timedelta
class TokenManager:
def __init__(self, client_id, private_key, token_endpoint):
self.client_id = client_id
self.private_key = private_key
self.token_endpoint = token_endpoint
self.access_token = None
self.expires_at = None
def get_access_token(self):
# Return cached token if still valid
if self.access_token and datetime.utcnow() < self.expires_at:
return self.access_token
# Request new token
client_assertion = self._build_jwt()
response = requests.post(self.token_endpoint, data={
"grant_type": "client_credentials",
"client_id": self.client_id,
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": client_assertion,
"scope": "DsaApi"
})
response.raise_for_status()
token_response = response.json()
self.access_token = token_response["access_token"]
# Set expiration with 5-minute buffer
expires_in = token_response["expires_in"]
self.expires_at = datetime.utcnow() + timedelta(seconds=expires_in - 300)
return self.access_token
def _build_jwt(self):
# JWT building logic from Step 1
now = int(time.time())
payload = {
"iss": self.client_id,
"sub": self.client_id,
"aud": self.token_endpoint,
"jti": str(uuid.uuid4()),
"iat": now,
"nbf": now,
"exp": now + 300
}
return jwt.encode(payload, self.private_key, algorithm="RS384")
# Usage
token_manager = TokenManager(client_id, private_key, token_endpoint)
access_token = token_manager.get_access_token()Optionnel : utiliser DPoP pour une sécurité renforcée
L’API prend en charge DPoP (Demonstration of Proof-of-Possession) pour une sécurité renforcée. DPoP lie les jetons d’accès à une paire de clés spécifique, empêchant le vol de jetons.
Requête de jeton DPoP
Incluez une preuve JWT DPoP dans l’en-tête DPoP :
POST /connect/token HTTP/1.1
Host: auth-server.surescripts.net
Content-Type: application/x-www-form-urlencoded
DPoP: <dpop-proof-jwt>
grant_type=client_credentials
&client_id=your-client-id
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<your-signed-jwt>
&scope=DsaApi
&dpop_jkt=<jwk-thumbprint>Structure de la preuve DPoP
En-tête :
{
"typ": "dpop+jwt",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"n": "<base64url-modulus>",
"e": "<base64url-exponent>"
}
}Charge utile :
{
"htu": "ENVIRONMENT_AUTH_URL/connect/token",
"htm": "POST",
"iat": 1706572800,
"jti": "unique-id-here"
}Requête API DPoP
Lors de l’utilisation d’un jeton lié à DPoP, incluez la preuve DPoP dans les requêtes API :
GET /api/v0/odata/PrescribedMedicationData HTTP/1.1
Host: ENVIRONMENT_DATA_SOLUTIONS_URL
Authorization: DPoP <access-token>
DPoP: <dpop-proof-jwt>La preuve DPoP pour les requêtes de ressources doit inclure la revendication ath (hachage du jeton d’accès) :
{
"htu": "ENVIRONMENT_DATA_SOLUTIONS_URL/api/v0/odata/PrescribedMedicationData",
"htm": "GET",
"iat": 1706572800,
"jti": "unique-id-here",
"ath": "<base64url-sha256-of-access-token>"
}Pour une implémentation DPoP détaillée, consultez le README de la collection Postman.
Dépannage
Erreur "invalid_client"
Cause : ID client introuvable ou non-correspondance de clé publique
Solutions :
- Vérifiez que votre ID client est correct
- Assurez-vous que votre clé publique est enregistrée auprès du serveur d’authentification
- Confirmez que la clé privée correspond à la clé publique enregistrée
Erreur "invalid_grant"
Cause : Échec de la validation de l’assertion JWT
Solutions :
- Vérifiez l’expiration JWT (revendication exp) - assurez-vous qu’elle se trouve dans le futur
- Vérifiez que la revendication aud correspond exactement à l’URL du point de terminaison du jeton
- Assurez-vous que iss et sub contiennent tous deux votre ID client
- Confirmez que le JWT est signé avec l’algorithme RS384
- Vérifiez que le jti du JWT est unique
401 Non autorisé lors des requêtes API
Cause : Jeton d’accès invalide ou expiré
Solutions :
- Vérifiez que le jeton n’a pas expiré
- Vérifiez que vous utilisez le type de jeton Bearer
- Assurez-vous que le jeton a été demandé avec scope=DsaApi
- Confirmez le format de l’en-tête Autorisation : Bearer <token>
403 Interdit lors des requêtes API
Cause : Jeton valide, mais permissions insuffisantes
Solutions :
- Vérifiez que votre client a acheté le produit/le forfait
- Vérifiez si les colonnes que vous sélectionnez sont comprises dans votre forfait
- Assurez-vous d’inclure un filtre PARTITION_DAY valide
- Examinez les restrictions de filtre du forfait
Délai d’expiration de la demande de jeton
Cause : Problèmes de connectivité réseau ou de serveur
Solutions :
- Vérifiez la connectivité réseau vers le serveur d’authentification
- Vérifiez que l’URL du serveur d’authentification est correcte
- Vérifiez que les règles du pare-feu autorisent les connexions HTTPS sortantes
URL des environnements
Environnement | URL du serveur d’authentification | URL de Data Solutions API |
|---|---|---|
Production | https://auth-server.surescripts.net | https://data-solutions-api.surescripts.net |
Meilleures pratiques de sécurité
- Protégez les clés privées
- Ne validez jamais les clés privées dans le contrôle de source
- Stockez les clés de manière sécurisée (p. ex., variables d’environnement, coffres de clés)
- Utilisez des clés différentes pour différents environnements
- Stockage des jetons
- Stockez les jetons de manière sécurisée en mémoire ou dans un stockage chiffré
- N’enregistrez jamais et n’exposez jamais les jetons dans les messages d’erreur
- Supprimez les jetons lorsqu’ils expirent
- Réclamations JWT
- Utilisez toujours des valeurs jti uniques (UUID)
- Gardez des durées d’expiration courtes (5 minutes recommandées)
- Validez l’expiration du jeton avant utilisation
- HTTPS uniquement
- Utilisez toujours HTTPS pour les demandes de jetons et les appels API
- Vérifiez les certificats SSL/TLS
- Gestion des erreurs
- Implémentez une logique de nouvelle tentative pour les échecs temporaires
- Enregistrez les échecs d’authentification à des fins de surveillance
- N’exposez pas de détails sensibles dans les erreurs destinées aux clients
Étape 6 : Télécharger les fichiers de données (formats optionnels)
L’API Data Solutions prend en charge des formats optionnels de téléchargement de fichiers qui peuvent être activés pour votre package de données. Les formats disponibles dépendent de la configuration de votre package.
Formats pris en charge
- CSV – Format lisible par l’humain pour les téléchargements simples et la révision manuelle
- Parquet – Format binaire en colonnes optimisé pour l’analytique et le traitement à grande échelle
Remarque : La disponibilité des formats de fichier est contrôlée au niveau du package par Surescripts. Si un format n’est pas activé pour votre package, il n’est pas disponible au téléchargement.
Avant de commencer
Confirmez que :
- Votre Client ID est configuré avec un package prenant en charge le format de fichier souhaité
- Vous avez terminé l’authentification dans Étape 5
- Vous avez une valeur PARTITION_DAY valide
La sélection du format de fichier n’affecte pas la construction des requêtes ni l’authentification.
Télécharger des données CSV (uniquement pour les packages CSV activés)
Envoyez une requête au point de terminaison suivant pour télécharger des données CSV à l’aide d’une URL signée. L’URL signée est active pendant 5 minutes et n’est disponible que si les téléchargements CSV sont activés pour vous.
Données sur les médicaments prescrits :
/api/v0/customer/product/PrescribedMedicationData/csv/signedurls/{PARTITION_DAY}Télécharger des données Parquet (uniquement pour les packages Parquet activés)
Envoyez une requête au point de terminaison suivant pour télécharger des données Parquet à l’aide d’une URL signée. L’URL signée est active pendant 5 minutes et n’est disponible que si les téléchargements Parquet sont activés pour vous.
Données sur les médicaments prescrits :
/api/v0/customer/product/PrescribedMedicationData/parquet/signedurls/{PARTITION_DAY}