AIMERICAAPI · Développeurs

Authentification

Une clé pour votre propre entreprise ; OAuth 2.0 pour une app que d'autres entreprises utilisent.

Deux façons

Clé APIOAuth 2.0
PourVotre propre logiciel, votre propre entrepriseUne app tierce qu'un client autorise
ObtenueDans l'application, Développeur → Clés APIPar le flux d'autorisation ci-dessous
Jetonaim_live_…, pas d'expirationaim_at_… 60 minutes, renouvelé avec aim_rt_… 30 jours
Permissions sensiblesAccordées à la créationApprobation d'AIMERICA requise pour les apps tierces
Agit commeLa personne qui a créé la cléLa personne qui a cliqué Autoriser (ou l'entreprise, en client_credentials)

Dans les deux cas le jeton voyage dans l'en-tête Authorization: Bearer …. Un jeton absent, inconnu, expiré ou révoqué répond 401 unauthorized ; un jeton valide sans la permission voulue répond 403 insufficient_scope avec l'en-tête WWW-Authenticate qui nomme la permission manquante.

OAuth 2.0 : code d'autorisation + PKCE

AIMERICA est le serveur d'autorisation. Enregistrez votre app dans l'application (Développeur → Apps) : vous obtenez un client_id (aim_app_…), pour une app confidentielle un client_secret affiché une fois, et vous déclarez vos adresses de retour exactes et les permissions que l'app peut demander. Une app publique (mobile, navigateur) n'a pas de secret et doit utiliser PKCE.

Your app                    The person's browser              AIMERICA
  ───────                     ────────────────────              ────────
  1. make code_verifier,
     code_challenge = S256(verifier)
  2. send them to /oauth/authorize ─────────►  a1merica.ai/voip/authorize
                                               (sign in if needed, read the scopes,
                                                Allow or Deny)
  3.                  ◄──── 302 redirect_uri?code=…&state=… ────────────
  4. POST /oauth/token (code + code_verifier) ─────────────────────────►
  5.                  ◄──── access_token (60 min) + refresh_token (30 d)
  6. Authorization: Bearer aim_at_…  on every /v1 request
  7. POST /oauth/token grant_type=refresh_token when expires_in runs out

1. Envoyer la personne s'autoriser

# Python: build the PKCE pair
import base64, hashlib, secrets
verifier  = base64.urlsafe_b64encode(secrets.token_bytes(32)).rstrip(b"=").decode()
challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b"=").decode()
GET https://api.a1merica.ai/oauth/authorize
    ?response_type=code
    &client_id=aim_app_1a2b3c4d5e6f
    &redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
    &scope=users%3Aread%20calls%3Aread
    &state=xyz
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256

redirect_uri doit correspondre exactement à l'une des adresses enregistrées ; les scope demandés doivent faire partie de ceux de l'app ; state revient tel quel. La personne se connecte si nécessaire, voit l'app, ses permissions en phrases simples et l'entreprise concernée, puis Autoriser ou Refuser. En cas de refus : redirect_uri?error=access_denied&state=….

2. Échanger le code

Le code vaut 10 minutes et une seule fois. Le corps est encodé en formulaire (RFC 6749).

POST https://api.a1merica.ai/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=…
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&client_id=aim_app_1a2b3c4d5e6f
&code_verifier=…                      # public apps: PKCE instead of a secret
# confidential apps add client_secret=… (or HTTP Basic client_id:client_secret)
{
  "access_token": "aim_at_…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "aim_rt_…",
  "refresh_token_expires_in": 2592000,
  "scope": "users:read calls:read",
  "org_id": "a1b2…",
  "user_id": "9d8c…"
}

3. Renouveler

POST https://api.a1merica.ai/oauth/token
grant_type=refresh_token&refresh_token=aim_rt_…&client_id=aim_app_…

Le renouvellement fait tourner la paire : nouveau jeton d'accès, nouveau jeton de renouvellement. L'ancien jeton de renouvellement meurt dès que le nouveau jeton d'accès est utilisé une première fois, ou 60 secondes après — de quoi survivre à un réseau qui coupe entre la réponse et son enregistrement.

Identifiants client (sans personne)

Une app confidentielle peut agir pour l'entreprise qui l'a enregistrée, sans personne derrière : grant_type=client_credentials. Le jeton n'a pas de user_id ; les routes qui parlent de « moi » répondent 403.

POST https://api.a1merica.ai/oauth/token
grant_type=client_credentials&scope=calls%3Aread&client_id=aim_app_…&client_secret=…

Durées et révocation

JetonPréfixeDuréeComment il meurt
Clé APIaim_live_Sans limiteRévoquée dans l'application (effet immédiat)
Code d'autorisation—10 minutes, usage uniqueUtilisé, ou expiré
Jeton d'accèsaim_at_60 minutesExpire ; POST /oauth/revoke ; la personne retire l'app ; l'app est suspendue
Jeton de renouvellementaim_rt_30 joursRotation à l'usage ; POST /oauth/revoke ; la personne retire l'app
POST https://api.a1merica.ai/oauth/revoke
token=aim_rt_…&client_id=aim_app_…

POST /oauth/revoke (RFC 7009) accepte un jeton d'accès ou de renouvellement et répond 200 même s'il est déjà mort. POST /v1/oauth/introspect (authentifié par le client) dit si un jeton est actif, ses permissions, son entreprise et sa personne. Quand une personne retire une app dans l'application (Développeur → Apps → autorisations), tous ses jetons pour cette app cessent à l'instant : la prochaine requête répond 401.

Le point de terminaison /oauth/token répond aux erreurs à la façon de la RFC — {"error": "invalid_grant", "error_description": "…"} — parce que les bibliothèques OAuth s'y attendent ; partout ailleurs, c'est l'enveloppe AIMERICA.

HTTP/1.1 400 Bad Request
{"error": "invalid_grant", "error_description": "The code has expired or was already used"}

Ne stockez jamais un jeton ou une clé en clair dans un dépôt ou un journal. Nous ne gardons que des empreintes SHA-256 : une clé perdue ne peut pas être retrouvée, seulement remplacée.