Skip to main content

Official Python SDK for the AfiniTwin B2B API.

Project description

afini-twin-sdk

Official Python SDK for the AfiniTwin B2B API.

The AfiniTwin is a portable cognitive profile (Big Five + 5 supplementary layers) built on the Afini.ai platform. This SDK gives you typed access to a user's snapshot from your own systems — CRMs, custom assistants, internal pipelines.

Installation

pip install afini-twin-sdk

Requires Python ≥ 3.10. Built on httpx and pydantic v2.

Get an API key

Active users with a Professional plan on Afini.ai can generate keys at afini.ai/dashboard/twin/api. The key is shown once — store it securely.

Quick start

Async

import asyncio
import os
from afini_twin import AfiniTwinClient

async def main():
    async with AfiniTwinClient(api_key=os.environ["AFINITWIN_KEY"]) as client:
        me = await client.me()
        print(f"User has {me['twins']['ready']} ready snapshots; quota {me['quota']['remaining']}/{me['quota']['monthlyLimit']}")

        snapshots = await client.historic()
        for s in snapshots["snapshots"]:
            print(s["id"], s["snapshotDate"])

        # Download standard preset as Markdown
        md = await client.preset("estandar", format="md", lang="es")
        print(md[:200], "…")

asyncio.run(main())

Sync

from afini_twin import AfiniTwinSyncClient

with AfiniTwinSyncClient(api_key=os.environ["AFINITWIN_KEY"]) as client:
    me = client.me()

Sending data into the user's profile (twin:write scope)

If your API key has the twin:write scope, you can seed life-facts and annotations. They go to the user's review queue at /dashboard/discoveries; nothing is injected into the profile until the user approves.

from afini_twin import AfiniTwinClient, LifeFactInput

async with AfiniTwinClient(api_key=os.environ["AFINITWIN_KEY"]) as client:
    result = await client.life_facts_create([
        LifeFactInput(
            category="professional",
            value="Trabaja en una startup de IA en Bilbao desde 2023",
            valence="positive",
            consent=True,
            external_ref="crm-12345",
        )
    ])
    print(result["accepted"], "candidates queued ->", result["inboxUrl"])

For free-form notes:

from afini_twin import AnnotationInput

await client.annotations_create([
    AnnotationInput(tag="observation", text="Mostró interés por escalar a Pro", consent=True)
])

The pydantic models reject consent != True at validation time — you can't accidentally submit without an explicit confirmation.

Verifying webhook signatures

Every webhook POST carries an X-AfiniTwin-Signature: sha256=<hmac> header. Verify before trusting the payload:

FastAPI

from fastapi import FastAPI, Request, HTTPException
from afini_twin import verify_webhook_signature

app = FastAPI()
SECRET = os.environ["AFINITWIN_WEBHOOK_SECRET"]

@app.post("/webhooks/afinitwin")
async def afinitwin_hook(request: Request):
    raw = await request.body()
    sig = request.headers.get("x-afinitwin-signature")
    if not verify_webhook_signature(raw, sig, SECRET):
        raise HTTPException(403)
    payload = await request.json()
    if payload["event"] == "twin.snapshot.ready":
        # … pull the new snapshot
        pass
    elif payload["event"] == "twin.quota.exceeded":
        # … alert your billing
        pass
    return {"ok": True}

Django / Flask

The function is framework-agnostic: pass the raw body (bytes or str) plus the header value plus the secret.

Error handling

from afini_twin import AfiniTwinClient, AfiniTwinApiError

try:
    async with AfiniTwinClient(api_key=key) as client:
        await client.me()
except AfiniTwinApiError as e:
    if e.status == 429 and e.body and e.body.get("code") == "TIER_QUOTA_EXCEEDED":
        # upgrade your B2B tier
        ...
    raise

Rate limits

Endpoint group Per minute Per month
/health 120 unlimited
/me, /historic, /snapshots/*, /preset/* 60 per tier
/life-facts, /annotations 30 per tier

The monthly cap is enforced per user across all keys based on the B2B tier (Included = 10k, Starter = 100k, Pro = 1M, Enterprise = custom).

License

MIT © Bilbao AI S.L.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

afini_twin_sdk-0.1.0.tar.gz (7.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

afini_twin_sdk-0.1.0-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

File details

Details for the file afini_twin_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: afini_twin_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 7.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for afini_twin_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 09fb43a17e1afd5b74b94f91ead7d614d3d1b09d616e0eaf1e22f961a5b4bcc5
MD5 611c8457311e913ad355add0f52fbf89
BLAKE2b-256 ffb413f0bc8eac420a03179e41607a1a9912ade37333f5f050455d0109786950

See more details on using hashes here.

File details

Details for the file afini_twin_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: afini_twin_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for afini_twin_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6f051c8be9c77beb9f2554a0c75a7168ca883e64fb666e2acc3f83a4fb373636
MD5 ebcd216b254d84786623b2227e04565d
BLAKE2b-256 9d1707aec4f9f4f4757cd44f39b61587096102b36f1221bc40686c980d090f10

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page