The problem
When small and mid-sized brands look for influencers, the process is usually chaotic. Stats arrive as screenshots and can’t be verified, negotiations happen in Instagram DMs, and payment is made on trust. If the brand pays upfront, it risks not getting the content. If the creator works before being paid, they risk not getting the money. The Bulgarian market has almost no localized platform that covers the whole process — from finding a creator to payment.
The solution
Influ-Link is a two-sided marketplace that brings the whole process between brand and creator into one place:
- 1Discovery: the brand searches for creators by niche, location, language, platform and content type.
- 2Trust: stats come directly from Instagram through the official API, not from screenshots.
- 3Communication: real-time chat and notifications, campaigns and offers that can be accepted or declined.
- 4Secure payment: the money is held and transferred to the creator only after the brand approves the work.
The platform is fully available in Bulgarian and English and is publicly accessible.
Key features
Creator profiles and search
Every creator has a public profile with a portfolio, followers, likes and fixed-price packages. Packages are an entry point to a chat conversation, not a direct payment. Search combines many filters over data stored as JSON columns in MySQL. Queries are built dynamically from the selected filters and are parameterized, so there is no SQL injection.
Instagram Graph API integration
The creator connects their Instagram account through Facebook Login for Business. The short-lived token is exchanged for a long-lived one (about 60 days) and stored AES-encrypted. Stats for followers, reach and engagement sync automatically. A nightly cron job renews tokens expiring within the next 10 days, so stats never silently stop. We also built the deauthorization and data-deletion callbacks Meta requires, which verify the request signature (signed_request) with HMAC-SHA256.
Campaigns, offers and real-time chat
Brands create campaigns, invite creators and send offers. The platform keeps a campaign history and tracks impressions. Chat and notifications run on Socket.IO with a Redis adapter, so the server can scale horizontally without losing messages between instances. Old notifications are cleaned up automatically.
Escrow-style payments (Stripe Connect)
The brand pays upfront and the platform holds the amount. The creator marks the work as done, the brand reviews and approves it, and only then is the money transferred to the creator’s Stripe Connect account. Releasing the funds runs in a database transaction with a row lock, so concurrent requests can’t cause a double payout. Creators onboard for payouts directly in Stripe.
Brand subscriptions (Stripe Subscriptions)
We built a five-tier subscription system with Checkout, the Customer Portal and plan changes with proration. Feature access depends on the plan: on an insufficient plan the server returns HTTP 402 and the UI shows an upgrade dialog. Subscription state is driven entirely by Stripe webhook events. The logic is covered by 50+ unit tests and verified end-to-end in the Stripe sandbox. It is currently behind a feature flag, because we launched with creators first.
Authentication and onboarding
Users sign in with email and password or with Google OAuth. New accounts must verify their email before they can log in. Verification tokens are stored only as a SHA-256 hash and expire after 24 hours. Resending the email doesn’t reveal whether an address is registered. New creators go through an onboarding dialog and an interactive profile tour that highlights the real buttons in the UI.
Technical challenges
1. Meta approval
Releasing the Instagram integration to the public required business verification, a separate verification as a Tech Provider (because the app reads data from other people’s business accounts), App Review for five advanced permissions and a video walkthrough of the flow. Even after everything was approved, real users saw a “Feature Unavailable” error. The cause turned out to be that Facebook Login for Business requires the public_profile permission at Advanced access — something Meta doesn’t mention anywhere. We also found that Meta now automatically adds every Page–Instagram connection to a business portfolio, so without the business_management permission creators’ pages don’t show up in the API at all.
2. Payment correctness
With money, mistakes are unacceptable. We removed a race condition where two concurrent requests could create two Stripe customers for the same brand, leaving a paid subscription unlinked from the account. The fix is a transaction that locks the row with SELECT … FOR UPDATE. If processing a webhook event fails, the server now returns 500 so Stripe retries it, and reprocessing is idempotent. The price is always calculated on the server, so the client can’t submit its own amount.
3. Failed subscription payments
Instead of cutting off access immediately on a failed payment, we introduced a 15-day grace period. It is deliberately longer than Stripe’s 14-day automatic retry schedule, so a customer with a temporarily failing card doesn’t lose access while Stripe is still trying to collect. On every state change the user gets an in-app notification. During review we also found a hidden bug: in newer Stripe API versions the current_period_end field moved to the subscription item level, and renewal dates were being saved as empty.
4. Zero-downtime database changes
The database schema migrates automatically on server start through idempotent functions. When we introduced mandatory email verification, the migration automatically marked all existing users as verified so nobody got locked out.
5. Security
We did a full hardening of the backend: security headers with Helmet, separate rate limits for authentication, the API, payments and the contact form, JWT in httpOnly cookies, bcrypt for passwords, CORS limited to explicitly allowed domains, an IDOR check on every endpoint and an automatic daily security report.
6. Infrastructure and deployment
The frontend is a static Vite build on shared hosting, and the backend runs on DigitalOcean under pm2. We migrated production from a subdomain to the main domain without service interruption. This included updating the OAuth URLs, Stripe return URLs, CORS settings and the Meta app registration.
Results
- The platform is publicly available at influ-link.com and open for creator sign-ups.
- The Instagram integration is approved by Meta and works for real users.
- Escrow payments and creator payouts are built on Stripe Connect, and brand subscriptions are verified end-to-end in the Stripe sandbox.
- The app is fully bilingual (BG/EN), responsive and SEO-optimized.


