Theme
Open the portal

Build on allus

Your company connects to people's allme profiles through services, asks for exactly the fields you need, and receives auto-updating, end-to-end-encrypted data — pulled from a change feed or pushed to a webhook, decrypted for you by an SDK in one of six languages.

Live in 5 minutes — Getting started →

What allus is

allme.fyi is the consumer side: people keep one privacy-first profile (phone, email, address, documents…) and decide who sees what. allus.fyi is the business side. A company signs up in the portal, creates one or more services, and connects to its clients' allme profiles. From then on, when a connected person updates a field they shared, your records update too — no re-collection, no stale data, no copy-paste.

Every value a person shares with your service is encrypted to that service's public key on their device. The platform stores only ciphertext; your SDK decrypts it locally with the service private key. allus never sees the plaintext. (A photo or document from a field the person did not mark private is the one exception: no encrypted copy of it exists, and you receive the file itself. Data a company shares back — its own business-card details — is plaintext by design.) See the zero-knowledge model for the full picture.

The big picture

Three actors, one direction of data flow:

   COMPANY (you)                  allus platform                    PERSON (allme user)
 ┌───────────────────┐         ┌────────────────────┐          ┌────────────────────────┐
 │  Service "CRM"    │         │                    │          │  allme profile         │
 │  request fields:  │ ──ask──▶│   COMPANYCODE/     │◀─connect─│  picks a field per     │
 │   • work_email    │         │   SERVICECODE      │          │  request slot, then    │
 │   • mobile        │         │                    │          │  encrypts the value    │
 │   • home_address  │         │  stores CIPHERTEXT  │◀─encrypt─│  to your service key   │
 └─────────┬─────────┘         │  only (zero-know.) │          └────────────────────────┘
           │                   └──────────┬─────────┘
           │  pull: GET /api/company-data/changes  (drain-on-fetch feed)
           │  push: webhook POST  (X-Allus-Signature)
           ▼                              │
 ┌───────────────────┐                    │   your SDK decrypts with the
 │  SDK (6 langs)    │◀───────────────────┘   service private key — your code
 │  → typed values   │                        only ever sees plaintext conclusions
 └───────────────────┘

You configure what to ask for once (in the portal or via the portal API). People connect on their own and choose which of their fields answers each request. Your code then reads a steady stream of typed, decrypted values keyed by your slugs — it never touches OAuth tokens, the field catalog, id plumbing, or the crypto.

Why build on allus

The shape of your integration

A complete integration is small. After you create a service and register an API client in the portal, your whole codebase is roughly this:

from allus_company_data import Client

client = Client.from_config("config.json")

def handle(change):
    # one update at a time: event, person, slug, value, live, at
    if change.event == "field_updated":
        store(change.person_id, change.slug, change.value, live=change.live)
    elif change.event in ("connection_deleted", "field_deleted"):
        remove(change.person_id, change.slug)

client.process_changes(handle)   # returns when the feed is empty; schedule re-runs
import { Client } from '@allus-fyi/company-data';

const client = Client.fromConfig('config.json');

await client.processChanges((change) => {
  if (change.event === 'field_updated') {
    store(change.personId, change.slug, change.value, change.live);
  } else if (change.event === 'connection_deleted' || change.event === 'field_deleted') {
    remove(change.personId, change.slug);
  }
});
client, err := companydata.FromConfig("config.json")
if err != nil {
    log.Fatal(err)
}

err = client.ProcessChanges(func(c companydata.Change) error {
    switch c.Event {
    case "field_updated":
        store(c.PersonID, c.Slug, c.Value, c.Live)
    case "connection_deleted", "field_deleted":
        remove(c.PersonID, c.Slug)
    }
    return nil // nil ACKS; an error RETRIES → then dead-letters
}, companydata.PumpOptions{})
using Allus.CompanyData;

using var client = Client.FromConfig("config.json");

await client.ProcessChangesAsync(async change =>
{
    if (change.Event == "field_updated")
        Store(change.PersonId, change.Slug, change.ValueObj, change.Live);
    else if (change.Event is "connection_deleted" or "field_deleted")
        Remove(change.PersonId, change.Slug);
    await Task.CompletedTask;
});
import fyi.allme.allus.companydata.Client;

Client client = Client.fromConfig("config.json");

client.processChanges(change -> {
    switch (change.event()) {
        case "field_updated" ->
            store(change.personId(), change.slug(), change.value(), change.live());
        case "connection_deleted", "field_deleted" ->
            remove(change.personId(), change.slug());
        default -> { }
    }
});
<?php
require 'vendor/autoload.php';

use Allus\CompanyData\Client;
use Allus\CompanyData\Model\Change;

$client = Client::fromConfig('config.json');

$client->processChanges(function (Change $change): void {
    if ($change->event === 'field_updated') {
        store($change->personId, $change->slug, $change->value, $change->live);
    } elseif (in_array($change->event, ['connection_deleted', 'field_deleted'], true)) {
        remove($change->personId, $change->slug);
    }
});
The language you pick in the tabs above is remembered across every code block on every page. The full consumption model — exactly-once on your side, the crash-safe buffer, dead-lettering — is covered on the SDKs page.

Start here

Ready to build?

Create your first service and register an API client in the business portal, then follow the quickstart.

Get started →   Open the portal · Live API explorer ↗