Referencia
Ver como Markdownandco-sdk · Python
Cliente confidencial, OAuth y API de recursos para backends de Python.
uv add andco-sdkpip install andco-sdkpoetry add andco-sdkRequiere Python 3.11 o superior. Es un SDK de backend: cliente confidencial, sin navegador y sin presentaciones.
Sigue el mismo vocabulario que el SDK de JavaScript pero es idiomático en Python: lanza excepciones en vez de devolver resultados, usa snake_case y es asíncrono sobre httpx.
AndcoClient
AndcoClient(
*,
client_id: str,
client_secret: str | None = None,
auth_endpoint: str = "https://auth.andco.cl",
api_endpoint: str = "https://api.andco.cl",
api_version: str = "_",
resource: str = "https://api.andco.cl",
transport: TransportMode = "auto",
http_transport: httpx.AsyncBaseTransport | None = None,
)Un valor: configuración más capacidad, construido de forma síncrona y sin sesión. Una instancia de módulo es segura entre peticiones concurrentes precisamente porque no existe el campo donde el token de una persona podría filtrarse a la respuesta de otra.
http_transport existe para los tests: permite inyectar un transporte de httpx sin tocar la red.
with_session
with_session(credentials: AndcoSession | str | Credentials) -> BoundAndcoClientAcepta una sesión, un token suelto o cualquier cosa que resuelva uno. El token suelto está aceptado porque es de lejos la forma más común en un servidor, y exigir un envoltorio ponía las mismas tres líneas al inicio de cada manejador.
BoundAndcoClient tiene rest y la configuración de su dueño.
AndcoOAuth
Disponible como client.oauth.
async create_authorization_request(
*,
redirect_to: str,
scopes: list[str] | None = None,
resource: str | None = None,
org_id: str | None = None,
authorization_details: list[dict] | None = None,
login_hint: str | None = None,
state: str | None = None,
) -> AndcoAuthorizationRequest
async exchange_callback(*, callback_url: str, request: AndcoAuthorizationRequest) -> AndcoSession
async refresh(refresh_token: str) -> AndcoSession
def endpoint(name: str) -> str
property is_confidential: boolLa decisión entre petición directa y PAR ocurre dentro de create_authorization_request, así que quien llama nunca la toma. Se usa PAR cuando la petición lleva login_hint o authorization_details, o cuando la URL quedaría demasiado larga.
exchange_callback valida el callback contra la transacción —origen, state, antigüedad— antes de intercambiar nada.
AndcoSession
@dataclass(frozen=True, slots=True)
class AndcoSession:
access_token: str
refresh_token: str | None
expires_at: float # segundos desde la época Unix
scopes: tuple[str, ...] = ()
token_type: str = "bearer"
user: AndcoUser | None = None
@property
def is_expired(self) -> bool: ...is_expired incluye un margen, de modo que un token a punto de vencer se renueva antes de salir a la red.
AndcoAuthorizationRequest
@dataclass(frozen=True, slots=True)
class AndcoAuthorizationRequest:
authorization_url: str
code_verifier: str
state: str
redirect_to: strEs lo que hay que guardar entre la redirección y la vuelta. El code_verifier no puede viajar en la URL y no se puede reconstruir.
AndcoRest
async get(path: str, *, model: type[Model] | None = None, **params) -> Any
async post(path: str, body: Any = None, *, model: type[Model] | None = None) -> Any
async request(...) -> Anymodel valida y tipa la respuesta cuando quieres un objeto en vez de un diccionario.
Errores
class AndcoError(Exception):
code: str
status_code: int | None
details: dict | None
class AndcoAuthorizationError(AndcoError): ...Excepciones y no resultados: es lo que se espera de una biblioteca de Python, y try / except ya es el mecanismo del lenguaje para esto.
Webhooks
from andco_sdk import (
ANDCO_WEBHOOK_EVENT_ID_HEADER,
ANDCO_WEBHOOK_SIGNATURE_HEADER,
ANDCO_WEBHOOK_TIMESTAMP_HEADER,
verify_webhook,
)
trusted = verify_webhook(
body=raw,
signature=headers.get(ANDCO_WEBHOOK_SIGNATURE_HEADER),
event_id=headers.get(ANDCO_WEBHOOK_EVENT_ID_HEADER),
timestamp=headers.get(ANDCO_WEBHOOK_TIMESTAMP_HEADER),
secret=settings.ANDCO_WEBHOOK_SECRET,
)La comparación es de tiempo constante y una entrega fuera de la ventana de tolerancia se rechaza aunque su firma sea válida. body tiene que ser los bytes crudos.
Modelos
from andco_sdk import (
ANDCO_RESOURCE,
AndcoCompanyAddress,
AndcoCompanyIdentity,
AndcoGrantAuthorization,
)Tipos de los recursos de empresa y de las contribuciones de autorización, para que no los redeclares.
Qué no hace
No presenta autorizaciones, no abre ventanas, no guarda sesión y no tiene almacenamiento. Todo eso es del lado del navegador, y un backend de Python no está ahí.
