A smart REST API that links customer identities across multiple emails and phone numbers
Live Demo • API Docs • Setup • How It Works
Imagine a customer named Doc who buys from FluxKart.com using different emails and phone numbers for each purchase to stay anonymous. How do you recognize it's the same person and give them a personalized experience?
That's exactly what this service solves - Identity Reconciliation.
Base URL:
https://bitespeed-identity-mzu1.onrender.com
POST https://bitespeed-identity-mzu1.onrender.com/identify
| Layer | Technology |
|---|---|
| Runtime | Node.js |
| Language | TypeScript |
| Framework | Express.js |
| Database | PostgreSQL |
| ORM | Prisma |
| Hosting | Render.com |
The service maintains a Contact table where each customer can have multiple entries - one primary and many secondary contacts, all linked together.
New request comes in
│
▼
No match found? ──► Create new PRIMARY contact
│
▼
Match found with existing contact?
│
├── Same info already exists ──► Return existing cluster as-is
│
├── New info + partial match ──► Create SECONDARY contact linked to primary
│
└── Two separate primaries match? ──► Older one stays PRIMARY
Newer one becomes SECONDARY
All its secondaries re-linked
model Contact {
id Int @id @default(autoincrement())
phoneNumber String?
email String?
linkedId Int?
linkPrecedence String // "primary" | "secondary"
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
}Identifies and consolidates a customer's contact information.
Request Body
{
"email": "string (optional)",
"phoneNumber": "string (optional)"
}At least one of
phoneNumberis required.
Response
{
"contact": {
"primaryContatctId": 1,
"emails": ["primary@email.com", "secondary@email.com"],
"phoneNumbers": ["123456", "999999"],
"secondaryContactIds": [2, 3]
}
}Scenario 1 - New Customer
Request:
{ "email": "doc@hillvalley.edu", "phoneNumber": "123456" }Response:
{
"contact": {
"primaryContatctId": 1,
"emails": ["doc@hillvalley.edu"],
"phoneNumbers": ["123456"],
"secondaryContactIds": []
}
}Scenario 2 - Same customer, new email
Request:
{ "email": "emmett@hillvalley.edu", "phoneNumber": "123456" }Response:
{
"contact": {
"primaryContatctId": 1,
"emails": ["doc@hillvalley.edu", "emmett@hillvalley.edu"],
"phoneNumbers": ["123456"],
"secondaryContactIds": [2]
}
}Scenario 3 - Two clusters merging
When a request links two previously separate primary contacts, the older one becomes the true primary and the newer one is demoted to secondary along with all its linked contacts.
- Node.js v18+
- PostgreSQL database
- npm
# 1. Clone the repository
git clone https://github.com/binnisha/bitespeed-identity.git
cd bitespeed-identity
# 2. Install dependencies
npm install
# 3. Set up environment variables
cp .env.example .env
# Add your DATABASE_URL in .env
# 4. Run database migrations
npx prisma migrate dev
# 5. Start the development server
npm run devDATABASE_URL="postgresql://user:password@host:5432/dbname"
PORT=3000bitespeed-identity/
├── src/
│ ├── index.ts # Express app entry point
│ └── identify.ts # Core identity reconciliation logic
├── prisma/
│ ├── schema.prisma # Database schema
│ └── migrations/ # Database migrations
├── .env # Environment variables
├── package.json
└── tsconfig.json
This project follows meaningful, incremental commits:
feat:for new featuresfix:for bug fixesrefactor:for code improvementsdocs:for documentation updates
🛠️ Engineered by Binisha Thakur: Turning business logic into clean, scalable backend systems.