- Zmiana nazwy: "Norda Biznes Hub" → "Norda Biznes Partner" - Aktualizacja modelu AI: Gemini 2.0 Flash → Gemini 3 Flash - Zachowano historyczne odniesienia w timeline i dokumentacji Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
51 KiB
API Endpoints Reference
Document Version: 1.0 Last Updated: 2026-01-10 Application: Norda Biznes Partner Base URL: https://nordabiznes.pl
Table of Contents
- Overview
- Authentication
- Rate Limiting
- CSRF Protection
- Response Formats
- Public Endpoints
- Authentication Endpoints
- User Endpoints
- API Endpoints (JSON)
- Admin Endpoints
- Audit Endpoints
- Error Codes
- Examples
Overview
The Norda Biznes Partner provides 90+ HTTP endpoints across multiple functional areas:
- Public Pages: Company directory, search, profile viewing
- Authentication: Registration, login, password reset, email verification
- User Features: Dashboard, AI chat, forum, messaging, calendar, classifieds
- API (JSON): RESTful endpoints for programmatic access
- Admin: Content moderation, user management, audit tools, analytics
- Audit: Public audit reports (SEO, Social Media, GBP, IT)
Technology Stack
- Framework: Flask 3.0
- WSGI Server: Gunicorn (4 workers, 120s timeout)
- Session Management: Flask-Login (server-side sessions)
- CSRF Protection: Flask-WTF CSRFProtect
- Rate Limiting: Flask-Limiter (IP-based)
URL Structure
https://nordabiznes.pl/
├── / # Public pages
├── /api/ # JSON API endpoints
├── /admin/ # Admin-only pages
├── /audit/ # Public audit reports
└── /company/<slug> # Company profiles
Authentication
Authentication Methods
-
Session-based (Browser):
- Flask-Login sessions
- Cookie:
session(HttpOnly, Secure, SameSite=Lax) - Duration: 7 days with "Remember Me" checkbox
- Logout:
GET /logout
-
No API Key Authentication:
- Public API endpoints require no authentication
- Protected endpoints require active browser session
Authorization Levels
| Level | Description | Check Method |
|---|---|---|
| Public | No authentication required | None |
| Authenticated | Logged-in user | @login_required decorator |
| NORDA Member | User with verified company association | current_user.is_verified |
| Admin | Admin privileges | current_user.is_admin == True |
Access Control Pattern
# Public endpoint (no decorator)
@app.route('/search')
def search():
# Anyone can access
# Authenticated endpoint
@app.route('/dashboard')
@login_required
def dashboard():
# Requires login
# Admin endpoint
@app.route('/admin/users')
@login_required
def admin_users():
if not current_user.is_admin:
flash('Brak uprawnień administratora', 'danger')
return redirect(url_for('index'))
# Admin logic
Rate Limiting
Global Rate Limits
Configured via Flask-Limiter, applied by IP address:
- 200 requests per day
- 50 requests per hour
Per-Endpoint Limits
Some endpoints have additional rate limiting:
| Endpoint | Limit | Reason |
|---|---|---|
POST /login |
5 requests/hour | Brute force protection |
POST /register |
5 requests/hour | Abuse prevention |
POST /forgot-password |
5 requests/hour | Email spam prevention |
POST /api/seo/audit |
10 requests/hour | API quota protection |
POST /api/chat/*/message |
50 requests/hour | AI API cost control |
Rate Limit Headers
Responses include rate limit information:
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1704974400
Rate Limit Exceeded Response
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{
"error": "Rate limit exceeded",
"retry_after": 3600
}
CSRF Protection
Overview
All POST, PUT, DELETE requests require CSRF token validation (Flask-WTF CSRFProtect).
CSRF Token in Forms
HTML forms automatically include CSRF token:
<form method="POST" action="/forum/nowy">
{{ form.hidden_tag() }} <!-- Includes CSRF token -->
<!-- Form fields -->
</form>
CSRF Token in AJAX
For AJAX requests, include CSRF token in headers:
fetch('/api/chat/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken() // Get from meta tag or cookie
},
body: JSON.stringify({...})
});
CSRF Token Retrieval
Token available in HTML meta tag:
<meta name="csrf-token" content="{{ csrf_token() }}">
JavaScript helper:
function getCsrfToken() {
return document.querySelector('meta[name="csrf-token"]').content;
}
CSRF Exemptions
No endpoints are exempt from CSRF protection.
Response Formats
HTML Responses
Server-side rendered Jinja2 templates:
GET /company/pixlab-sp-z-o-o
→ HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<!DOCTYPE html>
<html>...
JSON Responses
API endpoints return JSON:
GET /api/companies
→ HTTP/1.1 200 OK
Content-Type: application/json
{
"companies": [...],
"total": 80
}
Flash Messages
User-facing messages use Flask flash messages:
flash('Rekomendacja dodana pomyślnie', 'success')
flash('Błąd: Nieprawidłowe dane', 'danger')
Categories: success, danger, warning, info
Redirects
Many POST endpoints redirect after success:
POST /login
→ HTTP/1.1 302 Found
Location: /dashboard
Public Endpoints
Homepage
GET /
Description: Company directory homepage with grid of all companies
Authentication: None
Query Parameters:
- None
Response:
- HTML page with company cards
- Displays all 80 member companies
- Filterable by category (client-side)
Example:
curl https://nordabiznes.pl/
Company Search
GET /search
Description: Search companies by keyword, NIP, REGON, or category
Authentication: None
Query Parameters:
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
q |
string | No | Search query (keyword, NIP, REGON) | strony www |
category |
integer | No | Category ID filter | 1 (IT) |
Search Strategies:
- NIP/REGON Direct Lookup (10 digits → NIP, 9/14 digits → REGON)
- Synonym Expansion (55+ keyword mappings)
- PostgreSQL FTS (full-text search with Polish stemming)
- Fuzzy Matching (pg_trgm for typos)
Response:
- HTML page with search results
- Results sorted by relevance score
- Empty state if no matches
Example:
curl "https://nordabiznes.pl/search?q=strony+www&category=1"
Company Profile
GET /company/<slug>
Description: Detailed company profile page
Authentication: None
Path Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
slug |
string | Company URL slug (kebab-case) | pixlab-sp-z-o-o |
Response Sections:
- Header (name, category, verification badge, short description)
- Contact bar (website, email, phone, location)
- About (company description)
- Services & Competencies (tags)
- Unique Selling Points
- Contact Details (full contact cards)
- Legal & Business Info (NIP, REGON, KRS, year established)
- Social Media (6 platforms)
- Website Analysis (SEO, performance scores)
Example:
curl https://nordabiznes.pl/company/pixlab-sp-z-o-o
404 Response:
HTTP/1.1 404 Not Found
Content-Type: text/html
<h1>Firma nie została znaleziona</h1>
Health Check
GET /health
Description: System health check endpoint for monitoring
Authentication: None
Response:
{
"status": "ok",
"database": "connected",
"timestamp": "2026-01-10T12:00:00Z"
}
Status Codes:
200 OK- System healthy500 Internal Server Error- Database connection failed
Example:
curl https://nordabiznes.pl/health
Use Case: Zabbix monitoring, uptime checks
Company Events/News
GET /aktualnosci
Description: Public feed of company events and news
Authentication: None
Response:
- HTML page with list of recent company events
- Sorted by date (newest first)
- Pagination (20 events per page)
Example:
curl https://nordabiznes.pl/aktualnosci
Release Notes
GET /release-notes
Description: Application changelog and version history
Authentication: None
Response:
- HTML page with release notes
- Grouped by version
- Change history from
app.py
Example:
curl https://nordabiznes.pl/release-notes
Authentication Endpoints
User Registration
POST /register
Description: Create new user account with email verification
Authentication: None
Rate Limit: 5 requests/hour
Request Body (Form):
| Field | Type | Required | Validation | Description |
|---|---|---|---|---|
email |
string | Yes | Email format, unique | User email address |
password |
string | Yes | 8+ chars, uppercase, lowercase, digit | Account password |
first_name |
string | Yes | 1-100 chars | User first name |
last_name |
string | Yes | 1-100 chars | User last name |
company_id |
integer | No | Valid company ID | Associated company (optional) |
Password Requirements:
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one digit
Workflow:
1. Validate input
2. Check email uniqueness
3. Hash password (PBKDF2:SHA256)
4. Create User (is_verified=False)
5. Generate verification token (32-byte URL-safe)
6. Send verification email (Microsoft Graph API)
7. Redirect to /login with flash message
Success Response:
HTTP/1.1 302 Found
Location: /login
Set-Cookie: session=...
Flash: "Konto utworzone. Sprawdź email w celu weryfikacji."
Error Response:
HTTP/1.1 200 OK
Content-Type: text/html
Flash: "Email już istnieje w systemie"
Example:
curl -X POST https://nordabiznes.pl/register \
-d "email=jan.kowalski@example.com" \
-d "password=SecurePass123" \
-d "first_name=Jan" \
-d "last_name=Kowalski"
Email Verification
GET /verify-email/<token>
Description: Verify user email address via token from email
Authentication: None
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
token |
string | Verification token (32-byte URL-safe) |
Token Properties:
- Length: 43 characters (base64-encoded 32 bytes)
- Storage:
users.verification_token - Expiry: No expiration (should be implemented)
Workflow:
1. Query User by verification_token
2. If found: Set is_verified=True, verification_token=NULL
3. If not found: Show error
4. Redirect to /login
Success Response:
HTTP/1.1 302 Found
Location: /login
Flash: "Email zweryfikowany pomyślnie!"
Error Response:
HTTP/1.1 302 Found
Location: /login
Flash: "Nieprawidłowy lub wygasły token weryfikacyjny"
Example:
curl https://nordabiznes.pl/verify-email/AbCdEf123456...
User Login
POST /login
Description: Authenticate user and create session
Authentication: None
Rate Limit: 5 requests/hour
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User email |
password |
string | Yes | User password |
remember |
boolean | No | Remember me (7 day session) |
Workflow:
1. Query User by email
2. Verify password (werkzeug.security.check_password_hash)
3. Check is_verified = True
4. Check is_active = True
5. Call login_user(user, remember=True/False)
6. Redirect to /dashboard or ?next URL
Success Response:
HTTP/1.1 302 Found
Location: /dashboard
Set-Cookie: session=...; HttpOnly; Secure; SameSite=Lax
Error Response:
HTTP/1.1 200 OK
Content-Type: text/html
Flash: "Nieprawidłowy email lub hasło"
Example:
curl -X POST https://nordabiznes.pl/login \
-d "email=jan.kowalski@example.com" \
-d "password=SecurePass123" \
-d "remember=on"
User Logout
GET /logout
Description: End user session
Authentication: Required
Response:
HTTP/1.1 302 Found
Location: /
Set-Cookie: session=; Expires=...
Flash: "Wylogowano pomyślnie"
Example:
curl https://nordabiznes.pl/logout \
-H "Cookie: session=..."
Password Reset Request
POST /forgot-password
Description: Request password reset email
Authentication: None
Rate Limit: 5 requests/hour
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User email address |
Workflow:
1. Query User by email
2. Generate reset_token (32-byte URL-safe)
3. Save to users.reset_token
4. Send reset email with link to /reset-password/<token>
5. Redirect to /login with flash message
Response:
HTTP/1.1 302 Found
Location: /login
Flash: "Email z linkiem do resetowania hasła został wysłany"
Note: Returns success message even if email not found (security best practice)
Password Reset
POST /reset-password/<token>
Description: Reset password using token from email
Authentication: None
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
token |
string | Reset token (32-byte URL-safe) |
Request Body (Form):
| Field | Type | Required | Validation |
|---|---|---|---|
password |
string | Yes | 8+ chars, uppercase, lowercase, digit |
password_confirm |
string | Yes | Must match password |
Workflow:
1. Query User by reset_token
2. Validate token exists
3. Validate password strength
4. Hash new password
5. Update user.password_hash
6. Clear reset_token
7. Redirect to /login
Success Response:
HTTP/1.1 302 Found
Location: /login
Flash: "Hasło zmienione pomyślnie"
Error Response:
HTTP/1.1 200 OK
Flash: "Nieprawidłowy lub wygasły token resetowania"
User Endpoints
User Dashboard
GET /dashboard
Description: Personalized user dashboard
Authentication: Required
Features:
- User profile summary
- Recent activity
- Quick actions (AI chat, forum, messages)
- Company profile link (if associated)
Response:
- HTML page with dashboard
Example:
curl https://nordabiznes.pl/dashboard \
-H "Cookie: session=..."
AI Chat Interface
GET /chat
Description: AI-powered company directory assistant
Authentication: Required
Features:
- Start new conversation
- View conversation history
- Interactive chat interface
- Cost tracking display
Response:
- HTML page with chat UI
Example:
curl https://nordabiznes.pl/chat \
-H "Cookie: session=..."
Forum - Topic List
GET /forum
Description: Community forum topic listing
Authentication: Required
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
page |
integer | Page number | 1 |
Response:
- HTML page with forum topics
- Pagination (20 topics per page)
- Pinned topics at top
- Topic metadata (author, replies, last post)
Forum - Create Topic
POST /forum/nowy
Description: Create new forum topic
Authentication: Required
Request Body (Form):
| Field | Type | Required | Max Length | Description |
|---|---|---|---|---|
title |
string | Yes | 200 chars | Topic title |
content |
string | Yes | 10,000 chars | Topic content (sanitized HTML) |
Input Sanitization:
- Strips dangerous HTML tags
- Allows basic formatting (b, i, u, br, p)
- Max length enforcement
Success Response:
HTTP/1.1 302 Found
Location: /forum/<topic_id>
Flash: "Temat utworzony pomyślnie"
Forum - View Topic
GET /forum/<topic_id>
Description: View forum topic with replies
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
topic_id |
integer | Forum topic ID |
Response:
- Topic details (title, content, author, timestamp)
- All replies (nested threading)
- Reply form
Forum - Reply to Topic
POST /forum/<topic_id>/odpowiedz
Description: Add reply to forum topic
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
topic_id |
integer | Forum topic ID |
Request Body (Form):
| Field | Type | Required | Max Length |
|---|---|---|---|
content |
string | Yes | 10,000 chars |
Error Handling:
- 404 if topic not found
- 403 if topic is locked
- Input sanitization applied
Success Response:
HTTP/1.1 302 Found
Location: /forum/<topic_id>
Flash: "Odpowiedź dodana"
Calendar - Event List
GET /kalendarz
Description: Association event calendar
Authentication: Required
Response:
- HTML page with upcoming events
- Event details (date, time, location, description)
- RSVP status for current user
Calendar - RSVP
POST /kalendarz/<event_id>/rsvp
Description: RSVP to event (attend/cancel)
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
event_id |
integer | Event ID |
Request Body (Form):
| Field | Type | Values | Description |
|---|---|---|---|
status |
string | attending, not_attending |
RSVP status |
Workflow:
1. Check if EventAttendee exists for user+event
2. If exists: Update status
3. If not: Create EventAttendee record
4. Redirect to /kalendarz/<event_id>
Response:
HTTP/1.1 302 Found
Location: /kalendarz/<event_id>
Flash: "RSVP zaktualizowane"
Messages - Inbox
GET /wiadomosci
Description: Private message inbox
Authentication: Required
Response:
- HTML page with received messages
- Unread count badge
- Message preview (sender, subject, timestamp)
- Pagination (20 messages per page)
Messages - Sent
GET /wiadomosci/wyslane
Description: Sent messages folder
Authentication: Required
Response:
- HTML page with sent messages
- Recipient, subject, timestamp
- Pagination (20 messages per page)
Messages - New Message
GET /wiadomosci/nowa
Description: Compose new message form
Authentication: Required
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
recipient |
integer | User ID to pre-fill recipient |
reply_to |
integer | Message ID to reply to |
Response:
- HTML form with recipient selector, subject, content
Messages - Send
POST /wiadomosci/wyslij
Description: Send private message to another user
Authentication: Required
Request Body (Form):
| Field | Type | Required | Max Length |
|---|---|---|---|
recipient_id |
integer | Yes | - |
subject |
string | Yes | 200 chars |
content |
string | Yes | 10,000 chars |
Validation:
- Recipient must exist and be active
- Cannot send to self
- Content sanitization
Success Response:
HTTP/1.1 302 Found
Location: /wiadomosci/wyslane
Flash: "Wiadomość wysłana"
Messages - View
GET /wiadomosci/<message_id>
Description: View message details
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
message_id |
integer | Message ID |
Authorization:
- User must be sender or recipient
- Returns 403 otherwise
Side Effects:
- Marks message as read (if current user is recipient)
Response:
- HTML page with full message content
- Reply button
Classifieds - List
GET /tablica
Description: Community classifieds board
Authentication: Required
Response:
- HTML page with active classifieds
- Filter by status (active, completed)
- Pagination (20 classifieds per page)
Classifieds - Post New
POST /tablica/nowe
Description: Post new classified ad
Authentication: Required
Request Body (Form):
| Field | Type | Required | Max Length |
|---|---|---|---|
title |
string | Yes | 200 chars |
description |
string | Yes | 10,000 chars |
price |
decimal | No | - |
category |
string | Yes | Enum |
Categories: offer, request, event, other
Success Response:
HTTP/1.1 302 Found
Location: /tablica/<classified_id>
Flash: "Ogłoszenie dodane"
Classifieds - Mark Completed
POST /tablica/<classified_id>/zakoncz
Description: Mark classified as completed/closed
Authentication: Required (must be author)
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
classified_id |
integer | Classified ID |
Authorization:
- Only author can mark as completed
Response:
HTTP/1.1 302 Found
Location: /tablica/<classified_id>
Flash: "Ogłoszenie zakończone"
API Endpoints (JSON)
Companies List (JSON Export)
GET /api/companies
Description: Export all companies as JSON
Authentication: None (public API)
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
category |
integer | Filter by category ID | All |
limit |
integer | Max companies to return | 100 |
Response:
{
"companies": [
{
"id": 26,
"name": "PIXLAB Sp. z o.o.",
"slug": "pixlab-sp-z-o-o",
"short_description": "Systemy informatyczne dla biznesu",
"category": "IT",
"nip": "5882436505",
"regon": "221912907",
"krs": "0000414920",
"website_url": "https://pixlab.pl",
"email": "kontakt@pixlab.pl",
"phone": "58 621 30 00",
"city": "Rumia",
"services": ["Oprogramowanie", "Systemy IT", "Hosting"],
"competencies": ["Python", "PostgreSQL", "DevOps"],
"founded_year": 2011
},
// ... more companies
],
"total": 80,
"category": null,
"timestamp": "2026-01-10T12:00:00Z"
}
Status Codes:
200 OK- Success400 Bad Request- Invalid parameters
Example:
curl https://nordabiznes.pl/api/companies
curl "https://nordabiznes.pl/api/companies?category=1&limit=10"
Chat - Start Conversation
POST /api/chat/start
Description: Initialize new AI chat conversation
Authentication: Required
Request Body:
{
"initial_message": "Szukam firm z obszaru IT"
}
Response:
{
"conversation_id": 123,
"created_at": "2026-01-10T12:00:00Z",
"message": "Witaj! W czym mogę pomóc?"
}
Status Codes:
201 Created- Conversation started401 Unauthorized- Not logged in429 Too Many Requests- Rate limit exceeded
Example:
curl -X POST https://nordabiznes.pl/api/chat/start \
-H "Cookie: session=..." \
-H "Content-Type: application/json" \
-H "X-CSRFToken: ..." \
-d '{"initial_message": "Szukam firm IT"}'
Chat - Send Message
POST /api/chat/<conversation_id>/message
Description: Send message to AI chat
Authentication: Required
Rate Limit: 50 requests/hour
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
conversation_id |
integer | Conversation ID |
Request Body:
{
"message": "Kto tworzy strony www?"
}
Response:
{
"response": "Znalazłem 5 firm zajmujących się tworzeniem stron www:\n\n1. **PIXLAB** - strony internetowe, sklepy online...",
"companies_found": 5,
"tokens_used": 12500,
"estimated_cost_usd": 0.00094,
"timestamp": "2026-01-10T12:00:05Z"
}
AI Chat Configuration:
- Model: gemini-2.5-flash
- Max companies in context: 8
- History: Last 10 messages
- Average latency: 250-350ms
- Cost tracking: Automatic
Status Codes:
200 OK- Success400 Bad Request- Empty message401 Unauthorized- Not logged in404 Not Found- Conversation not found429 Too Many Requests- Rate limit500 Internal Server Error- AI API error
Example:
curl -X POST https://nordabiznes.pl/api/chat/123/message \
-H "Cookie: session=..." \
-H "Content-Type: application/json" \
-H "X-CSRFToken: ..." \
-d '{"message": "Kto tworzy strony www?"}'
Chat - Get History
GET /api/chat/<conversation_id>/history
Description: Retrieve conversation history
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
conversation_id |
integer | Conversation ID |
Response:
{
"conversation_id": 123,
"created_at": "2026-01-10T12:00:00Z",
"messages": [
{
"id": 1,
"sender": "user",
"message": "Szukam firm IT",
"timestamp": "2026-01-10T12:00:00Z"
},
{
"id": 2,
"sender": "ai",
"message": "Znalazłem 12 firm IT...",
"timestamp": "2026-01-10T12:00:02Z",
"tokens_used": 8500,
"cost_usd": 0.00064
}
],
"total_messages": 2,
"total_cost_usd": 0.00064
}
Example:
curl https://nordabiznes.pl/api/chat/123/history \
-H "Cookie: session=..."
Chat - Submit Feedback
POST /api/chat/feedback
Description: Submit feedback on AI response
Authentication: Required
Request Body:
{
"message_id": 456,
"thumbs_up": true,
"thumbs_down": false,
"comment": "Bardzo pomocna odpowiedź!"
}
Response:
{
"status": "success",
"message": "Dziękujemy za feedback"
}
Verify NIP
GET /api/verify-nip
Description: Verify Polish NIP (tax identification number) via ALEO.com
Authentication: None
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
nip |
string | Yes | 10-digit NIP (no hyphens) |
Response:
{
"valid": true,
"nip": "5882436505",
"company_name": "PIXLAB SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ",
"status": "active",
"source": "aleo.com"
}
Invalid NIP:
{
"valid": false,
"nip": "1234567890",
"error": "NIP nie został znaleziony"
}
Example:
curl "https://nordabiznes.pl/api/verify-nip?nip=5882436505"
Check Email Availability
GET /api/check-email
Description: Check if email is available for registration
Authentication: None
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Email address to check |
Response:
{
"available": true,
"email": "jan.kowalski@example.com"
}
Email Taken:
{
"available": false,
"email": "existing@example.com"
}
Example:
curl "https://nordabiznes.pl/api/check-email?email=jan.kowalski@example.com"
Notifications - List
GET /api/notifications
Description: Get user notifications
Authentication: Required
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
unread_only |
boolean | Filter unread notifications | false |
limit |
integer | Max notifications to return | 20 |
Response:
{
"notifications": [
{
"id": 1,
"type": "new_message",
"message": "Nowa wiadomość od Jan Kowalski",
"url": "/wiadomosci/123",
"created_at": "2026-01-10T11:00:00Z",
"read": false
},
{
"id": 2,
"type": "new_recommendation",
"message": "Nowa rekomendacja dla Twojej firmy",
"url": "/admin/recommendations",
"created_at": "2026-01-09T15:30:00Z",
"read": true
}
],
"unread_count": 3,
"total": 15
}
Notification Types:
new_message- New private messagenew_recommendation- New recommendation receivedevent_reminder- Upcoming event remindernews_approved- Company news approved (future)news_rejected- Company news rejected (future)
Example:
curl "https://nordabiznes.pl/api/notifications?unread_only=true" \
-H "Cookie: session=..."
Notifications - Mark Read
POST /api/notifications/<notification_id>/read
Description: Mark notification as read
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
notification_id |
integer | Notification ID |
Response:
{
"status": "success",
"notification_id": 1,
"read": true
}
Example:
curl -X POST https://nordabiznes.pl/api/notifications/1/read \
-H "Cookie: session=..." \
-H "X-CSRFToken: ..."
Notifications - Mark All Read
POST /api/notifications/read-all
Description: Mark all user notifications as read
Authentication: Required
Response:
{
"status": "success",
"marked_read": 5
}
Example:
curl -X POST https://nordabiznes.pl/api/notifications/read-all \
-H "Cookie: session=..." \
-H "X-CSRFToken: ..."
Notifications - Unread Count
GET /api/notifications/unread-count
Description: Get count of unread notifications (for badge)
Authentication: Required
Response:
{
"unread_count": 3
}
Example:
curl https://nordabiznes.pl/api/notifications/unread-count \
-H "Cookie: session=..."
Messages - Unread Count
GET /api/messages/unread-count
Description: Get count of unread private messages
Authentication: Required
Response:
{
"unread_count": 2
}
Example:
curl https://nordabiznes.pl/api/messages/unread-count \
-H "Cookie: session=..."
Model Info (Gemini)
GET /api/model-info
Description: Get information about available AI models
Authentication: None
Response:
{
"models": [
{
"id": "flash",
"name": "gemini-2.5-flash",
"description": "Fast, cost-effective model for most tasks",
"pricing": {
"input_per_1m_tokens": 0.075,
"output_per_1m_tokens": 0.30
},
"default": true
},
{
"id": "pro",
"name": "gemini-2.5-pro",
"description": "High-quality model for complex tasks",
"pricing": {
"input_per_1m_tokens": 1.25,
"output_per_1m_tokens": 5.00
},
"default": false
}
]
}
Admin Endpoints
Admin - Users
GET /admin/users
Description: User management dashboard
Authentication: Admin only
Features:
- List all users
- Search by email/name
- Toggle admin status
- Toggle active status
- Delete users
Response:
- HTML page with user table
Admin - Toggle Admin Status
POST /admin/users/<user_id>/toggle-admin
Description: Grant/revoke admin privileges
Authentication: Admin only
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
user_id |
integer | User ID |
Response:
HTTP/1.1 302 Found
Location: /admin/users
Flash: "Status administratora zaktualizowany"
Admin - Recommendations
GET /admin/recommendations
Description: Moderation queue for company recommendations
Authentication: Admin only
Query Parameters:
| Parameter | Type | Values | Default |
|---|---|---|---|
status |
string | pending, approved, rejected |
pending |
Features:
- Filter by status
- Approve/reject with reason
- View recommendation details
Response:
- HTML page with recommendations table
Admin - Approve Recommendation
POST /admin/recommendations/<id>/approve
Description: Approve pending recommendation
Authentication: Admin only
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
integer | Recommendation ID |
Workflow:
1. Update status = 'approved'
2. Set moderated_by = current_user.id
3. Set moderated_at = now()
4. (Future) Send notification to recommender
5. Redirect to /admin/recommendations
Response:
HTTP/1.1 302 Found
Location: /admin/recommendations
Flash: "Rekomendacja zatwierdzona"
Admin - Reject Recommendation
POST /admin/recommendations/<id>/reject
Description: Reject pending recommendation
Authentication: Admin only
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
integer | Recommendation ID |
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
rejection_reason |
string | Yes | Reason for rejection |
Response:
HTTP/1.1 302 Found
Location: /admin/recommendations
Flash: "Rekomendacja odrzucona"
Admin - Forum Moderation
GET /admin/forum
Description: Forum moderation dashboard
Authentication: Admin only
Features:
- Pin/unpin topics
- Lock/unlock topics
- Delete topics
- Delete replies
- View all topics (including locked)
Admin - Pin Topic
POST /admin/forum/topic/<id>/pin
Description: Pin topic to top of forum
Authentication: Admin only
Response:
HTTP/1.1 302 Found
Location: /admin/forum
Flash: "Temat przypięty"
Admin - Lock Topic
POST /admin/forum/topic/<id>/lock
Description: Lock topic (prevent new replies)
Authentication: Admin only
Response:
HTTP/1.1 302 Found
Location: /admin/forum
Flash: "Temat zablokowany"
Admin - Delete Topic
POST /admin/forum/topic/<id>/delete
Description: Delete forum topic and all replies
Authentication: Admin only
Warning: Permanent deletion, cascade deletes all replies
Response:
HTTP/1.1 302 Found
Location: /admin/forum
Flash: "Temat usunięty"
Admin - Delete Reply
POST /admin/forum/reply/<id>/delete
Description: Delete individual forum reply
Authentication: Admin only
Response:
HTTP/1.1 302 Found
Location: /forum/<topic_id>
Flash: "Odpowiedź usunięta"
Admin - Membership Fees
GET /admin/fees
Description: Membership fee management dashboard
Authentication: Admin only
Features:
- View all fees by period
- Filter by status (pending, paid, overdue)
- Generate monthly fees
- Mark fees as paid (single or bulk)
- Export to Excel
Admin - Generate Monthly Fees
POST /admin/fees/generate
Description: Generate membership fees for all companies for a given month
Authentication: Admin only
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
period_start |
date | Yes | Start of period (YYYY-MM-DD) |
period_end |
date | Yes | End of period (YYYY-MM-DD) |
Workflow:
1. Get fee amount from membership_fee_config
2. Query all active companies
3. For each company:
- Check if fee exists for period
- If not: Create MembershipFee (status='pending')
4. Redirect to /admin/fees
Response:
HTTP/1.1 302 Found
Location: /admin/fees
Flash: "Wygenerowano składki dla 80 firm"
Admin - Mark Fee Paid
POST /admin/fees/<id>/mark-paid
Description: Mark single fee as paid
Authentication: Admin only
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
integer | Fee ID |
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
paid_at |
datetime | No | Payment date (default: now) |
payment_method |
string | No | przelew, gotówka, other |
Response:
HTTP/1.1 302 Found
Location: /admin/fees
Flash: "Składka oznaczona jako opłacona"
Admin - Bulk Mark Paid
POST /admin/fees/bulk-mark-paid
Description: Mark multiple fees as paid
Authentication: Admin only
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
fee_ids[] |
array[integer] | Yes | Array of fee IDs |
payment_method |
string | No | Payment method |
Response:
HTTP/1.1 302 Found
Location: /admin/fees
Flash: "Oznaczono 15 składek jako opłacone"
Admin - Export Fees
GET /admin/fees/export
Description: Export fees to Excel file
Authentication: Admin only
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
period_start |
date | Filter by period start |
period_end |
date | Filter by period end |
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="skladki_2026-01.xlsx"
[Excel file binary data]
Admin - Events
GET /admin/kalendarz
Description: Event management dashboard
Authentication: Admin only
Features:
- List all events
- Create new events
- Edit events
- Delete events
- View RSVP list
Admin - Create Event
POST /admin/kalendarz/nowy
Description: Create new association event
Authentication: Admin only
Request Body (Form):
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Event title |
description |
string | Yes | Event description |
event_date |
datetime | Yes | Event date and time |
location |
string | Yes | Event location |
max_attendees |
integer | No | Maximum attendees (null = unlimited) |
Response:
HTTP/1.1 302 Found
Location: /admin/kalendarz
Flash: "Wydarzenie utworzone"
Admin - Delete Event
POST /admin/kalendarz/<event_id>/delete
Description: Delete event
Authentication: Admin only
Warning: Cascade deletes all RSVPs
Response:
HTTP/1.1 302 Found
Location: /admin/kalendarz
Flash: "Wydarzenie usunięte"
Admin - SEO Dashboard
GET /admin/seo
Description: SEO audit management dashboard
Authentication: Admin only
Features:
- View all company SEO scores
- Filter by score range
- Sort by performance, SEO, accessibility
- Trigger audits
- View audit history
Response:
- HTML table with SEO metrics for all companies
Admin - GBP Audit Dashboard
GET /admin/gbp-audit
Description: Google Business Profile audit dashboard
Authentication: Admin only
Features:
- View GBP completeness scores
- Identify missing profiles
- Trigger audits
- View AI recommendations
Admin - Social Media Dashboard
GET /admin/social-media
Description: Social media profile audit dashboard
Authentication: Admin only
Features:
- Platform coverage statistics
- Missing profile identification
- Profile verification status
- Follower count tracking
Response:
- HTML dashboard with social media stats
Admin - IT Audit Dashboard
GET /admin/it-audit
Description: IT infrastructure audit overview
Authentication: Admin only
Features:
- IT maturity scores
- Security score distribution
- Collaboration readiness
- Potential collaboration matches
Admin - Chat Analytics
GET /admin/chat-analytics
Description: AI chat usage analytics
Authentication: Admin only
Metrics:
- Total conversations
- Total messages
- Total API cost
- Average cost per conversation
- Most active users
- Token usage trends
Response:
- HTML dashboard with charts and tables
Admin - Debug Panel
GET /admin/debug
Description: Real-time application log viewer
Authentication: Admin only
Features:
- Last 500 log entries
- In-memory log buffer
- Log level filtering
- Auto-refresh
Response:
- HTML page with log entries
Admin - Digital Maturity
GET /admin/digital-maturity
Description: Digital maturity overview for all companies
Authentication: Admin only
Features:
- Maturity score distribution
- Average scores by category
- Companies needing improvement
- Trends over time
API - SEO Audit (List)
GET /api/seo/audit
Description: Get SEO audit results
Authentication: Admin only
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
slug |
string | Filter by company slug |
Response:
{
"audits": [
{
"company_slug": "pixlab-sp-z-o-o",
"company_name": "PIXLAB Sp. z o.o.",
"overall_score": 85,
"seo_score": 90,
"performance_score": 80,
"accessibility_score": 88,
"best_practices_score": 85,
"audited_at": "2026-01-10T10:00:00Z"
}
],
"total": 45
}
API - SEO Audit (Get by Slug)
GET /api/seo/audit/<slug>
Description: Get latest SEO audit for company
Authentication: Admin only
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
slug |
string | Company slug |
Response:
{
"company_slug": "pixlab-sp-z-o-o",
"overall_score": 85,
"seo_score": 90,
"performance_score": 80,
"accessibility_score": 88,
"best_practices_score": 85,
"pagespeed_seo_score": 92,
"pagespeed_performance_score": 78,
"on_page_seo_score": 88,
"technical_seo_score": 90,
"audited_at": "2026-01-10T10:00:00Z",
"details": {
"meta_tags": {...},
"headings": {...},
"images": {...},
"links": {...}
}
}
API - SEO Audit (Trigger)
POST /api/seo/audit
Description: Trigger SEO audit for company
Authentication: Admin only
Rate Limit: 10 requests/hour
Request Body:
{
"slug": "pixlab-sp-z-o-o"
}
Workflow:
1. Get company by slug
2. Extract website URL
3. Call Google PageSpeed Insights API (~20s)
4. Perform on-page SEO analysis
5. Perform technical SEO checks
6. Calculate composite score
7. Save to company_website_analysis table
8. Return results
Response:
{
"status": "success",
"company_slug": "pixlab-sp-z-o-o",
"overall_score": 85,
"audit_id": 123,
"audited_at": "2026-01-10T10:00:22Z"
}
Error Response (Quota Exceeded):
{
"status": "error",
"error": "PageSpeed API quota exceeded",
"retry_after": 3600
}
Status Codes:
200 OK- Audit completed400 Bad Request- Invalid slug or missing URL429 Too Many Requests- Rate limit or API quota exceeded500 Internal Server Error- API error
API - GBP Audit (Trigger)
POST /api/gbp/audit
Description: Trigger Google Business Profile audit
Authentication: Admin only
Rate Limit: 10 requests/hour
Request Body:
{
"slug": "pixlab-sp-z-o-o"
}
Response:
{
"status": "success",
"company_slug": "pixlab-sp-z-o-o",
"completeness_score": 75,
"recommendations": [
"Dodaj więcej zdjęć (obecnie: 5, zalecane: 10)",
"Uzupełnij godziny otwarcia",
"Dodaj opis działalności"
],
"audited_at": "2026-01-10T10:00:15Z"
}
API - GBP Audit (Get by Slug)
GET /api/gbp/audit/<slug>
Description: Get latest GBP audit for company
Authentication: Admin only
Response:
{
"company_slug": "pixlab-sp-z-o-o",
"completeness_score": 75,
"place_id": "ChIJ...",
"has_name": true,
"has_address": true,
"has_phone": true,
"has_website": true,
"has_hours": false,
"has_description": true,
"photo_count": 5,
"review_count": 12,
"avg_rating": 4.5,
"recommendations": [...],
"audited_at": "2026-01-10T10:00:15Z"
}
API - Social Media Audit
POST /api/social/audit
Description: Trigger social media profile audit
Authentication: Admin only
Request Body:
{
"slug": "pixlab-sp-z-o-o"
}
Response:
{
"status": "success",
"company_slug": "pixlab-sp-z-o-o",
"platforms_found": {
"facebook": true,
"instagram": true,
"linkedin": true,
"youtube": false,
"tiktok": false,
"twitter": false
},
"coverage": 50,
"audited_at": "2026-01-10T10:00:30Z"
}
Audit Endpoints
SEO Audit Report (Public)
GET /audit/seo/<slug>
Description: Public SEO audit report for company
Authentication: None
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
slug |
string | Company slug |
Response:
- HTML page with SEO audit results
- Scores, recommendations, performance metrics
- Public-facing (no admin controls)
Example:
curl https://nordabiznes.pl/audit/seo/pixlab-sp-z-o-o
Social Media Audit Report (Public)
GET /audit/social/<slug>
Description: Public social media profile report
Authentication: None
Response:
- HTML page showing social media presence
- Platform coverage, verified profiles
- Links to social media pages
GBP Audit Report (Public)
GET /audit/gbp/<slug>
Description: Public Google Business Profile audit
Authentication: None
Response:
- HTML page with GBP completeness score
- Missing fields
- Public recommendations
IT Audit Report (Public)
GET /audit/it/<slug>
Description: Public IT infrastructure audit
Authentication: None
Response:
- HTML page with IT maturity score
- Security score (high-level)
- Collaboration readiness
- Potential collaboration matches (anonymized)
Error Codes
HTTP Status Codes
| Code | Meaning | Usage |
|---|---|---|
| 200 OK | Success | Successful GET requests |
| 201 Created | Resource created | POST /api/chat/start |
| 302 Found | Redirect | After POST form submissions |
| 400 Bad Request | Invalid input | Validation errors |
| 401 Unauthorized | Not logged in | @login_required endpoints |
| 403 Forbidden | Insufficient permissions | Admin-only or ownership check |
| 404 Not Found | Resource not found | Invalid company slug, message ID |
| 429 Too Many Requests | Rate limit exceeded | 5/hour on auth endpoints, 10/hour on audits |
| 500 Internal Server Error | Server error | Unhandled exceptions, API failures |
Error Response Format (JSON)
{
"error": "Error message",
"code": "ERROR_CODE",
"details": {...}
}
Common Error Responses
401 Unauthorized:
{
"error": "Authentication required",
"code": "UNAUTHORIZED",
"redirect": "/login"
}
403 Forbidden:
{
"error": "Insufficient permissions",
"code": "FORBIDDEN"
}
404 Not Found:
{
"error": "Resource not found",
"code": "NOT_FOUND",
"resource": "company",
"slug": "invalid-slug"
}
429 Rate Limit:
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 3600,
"limit": "50/hour"
}
500 Server Error:
{
"error": "Internal server error",
"code": "INTERNAL_ERROR",
"request_id": "abc123"
}
Examples
Complete AI Chat Flow
# 1. Login
curl -c cookies.txt -X POST https://nordabiznes.pl/login \
-d "email=test@nordabiznes.pl" \
-d "password=&Rc2LdbSw&jiGR0ek@Bz"
# 2. Start conversation
CONV_ID=$(curl -b cookies.txt -X POST https://nordabiznes.pl/api/chat/start \
-H "Content-Type: application/json" \
-H "X-CSRFToken: $(getCsrfToken)" \
-d '{"initial_message": "Szukam firm IT"}' | jq -r '.conversation_id')
# 3. Send message
curl -b cookies.txt -X POST https://nordabiznes.pl/api/chat/$CONV_ID/message \
-H "Content-Type: application/json" \
-H "X-CSRFToken: $(getCsrfToken)" \
-d '{"message": "Kto tworzy strony www?"}' | jq
# 4. Get history
curl -b cookies.txt https://nordabiznes.pl/api/chat/$CONV_ID/history | jq
Trigger SEO Audit
# 1. Login as admin
curl -c cookies.txt -X POST https://nordabiznes.pl/login \
-d "email=testadmin@nordabiznes.pl" \
-d "password=cSfQbbwegwv1v3Q2Dm0Q"
# 2. Trigger audit
curl -b cookies.txt -X POST https://nordabiznes.pl/api/seo/audit \
-H "Content-Type: application/json" \
-H "X-CSRFToken: $(getCsrfToken)" \
-d '{"slug": "pixlab-sp-z-o-o"}' | jq
# 3. View public report
curl https://nordabiznes.pl/audit/seo/pixlab-sp-z-o-o
Company Search with cURL
# Search by keyword
curl "https://nordabiznes.pl/search?q=strony+www"
# Search by NIP
curl "https://nordabiznes.pl/search?q=5882436505"
# Search with category filter
curl "https://nordabiznes.pl/search?q=budowa&category=2"
Export Companies JSON
# All companies
curl https://nordabiznes.pl/api/companies | jq
# IT companies only
curl "https://nordabiznes.pl/api/companies?category=1" | jq
# Limit to 10 companies
curl "https://nordabiznes.pl/api/companies?limit=10" | jq
Related Documentation
- Flask Components - Application architecture and route organization
- Authentication Flow - Detailed authentication and session management
- AI Chat Flow - Complete AI chat implementation
- SEO Audit Flow - SEO audit workflow and API integration
- Security Architecture - Security controls and best practices
Maintenance Notes
When to Update This Document
- New endpoints added: Add to appropriate section with full documentation
- Authentication changes: Update authentication section and affected endpoints
- Rate limiting changes: Update rate limiting section
- New query parameters: Add to endpoint documentation
- Response format changes: Update examples and schemas
What NOT to Update
- Business logic details: Keep this in flow documentation
- Database schema: Keep in database schema documentation
- Infrastructure details: Keep in deployment/network documentation
Review Frequency
- Quarterly: Review all endpoints for accuracy
- After major features: Update immediately
- After API changes: Update immediately
Glossary
| Term | Definition |
|---|---|
| Endpoint | HTTP route that accepts requests and returns responses |
| Slug | URL-friendly identifier (kebab-case, e.g., pixlab-sp-z-o-o) |
| CSRF | Cross-Site Request Forgery protection |
| Rate Limiting | Restriction on number of requests per time period |
| Flash Message | One-time user notification message |
| Session | Server-side user authentication state |
| JWT | JSON Web Token (not used in this application) |
| API Key | Authentication token for API access (not used in this application) |
| RBAC | Role-Based Access Control |
Document Status: Complete Coverage: 90+ endpoints documented Completion Date: 2026-01-10 Next Review: 2026-04-10
This document provides a comprehensive reference for all HTTP endpoints in the Norda Biznes Partner application. It serves as the authoritative guide for developers, integrators, and system administrators working with the API.