API
Integrate with Discko programmatically using our REST API.
Getting Started
Step 1: Create an API key
- Log in to your Discko dashboard.
- Go to Mise en place > CRM.
- Expand “REST API”.
- Create a new key and copy it somewhere safe. You will use it to authenticate every request.
Step 2: Make an authenticated request
Send your API key in the X-Discko-Key header.
curl -X GET "https://app.discko.io/api/v1/leads" -H "X-Discko-Key: <YOUR_API_KEY>"// Example in Node.js / browser
const API_URL = "https://app.discko.io/api/v1";
async function listLeads() {
const response = await fetch(`${API_URL}/leads`, {
headers: {
"X-Discko-Key": process.env.DISCKO_API_KEY
}
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
return response.json();
}How it works
- Base URL:
https://app.discko.io/api/v1 - Authentication:
X-Discko-Key: <YOUR_API_KEY>on every request - Dates: All timestamps use ISO 8601 (UTC), for example
2024-01-15T10:30:00Z
Breaking Changes
2025-12-22 - Finished Leads Only (FT05)
Type: Breaking change mineur
Behavior: All API endpoints now return only completed leads (where the user has seen the Discko-generated summary). Leads that are still in progress (not yet finished) are no longer accessible via the API.
Affected endpoints:
GET /api/v1/leads- Only returns finished leadsGET /api/v1/leads/{id}- Returns 404 if the lead is not finishedPUT /api/v1/leads/{id}- Returns 404 if the lead is not finishedPOST /api/make-webhook- Returns 404 if the lead is not finished
Impact: Clients that were retrieving all leads (including incomplete ones) will no longer receive them. This change improves the quality of data received.
Migration: No client-side action required. All leads returned by the API are guaranteed to be complete with full analysis and summary data.
2025-12-18 - Standardized Error Format
All API endpoints now return a standardized response format for both success and error cases.
Success Response Format:
{
"success": true,
"data": [...]
}Error Response Format:
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "API key is missing or invalid.",
"details": null
},
"timestamp": "2025-12-18T10:30:00Z"
}Available Error Codes:
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | API key is missing or invalid. |
FORBIDDEN | 403 | Access denied to this resource. |
LEAD_NOT_FOUND | 404 | The requested lead does not exist or is not yet finished. |
VALIDATION_ERROR | 400 | Request validation failed. |
INVALID_JSON | 400 | Request body is not valid JSON. |
INVALID_STATUS | 400 | Status must be one of: NEW, IN_PROGRESS, WON, LOST. |
INTERNAL_ERROR | 500 | An unexpected error occurred. |
Migration Guide:
Existing integrations must update their error parsing:
- Before:
response.error(string) - After:
response.error.code(string) +response.error.message(string)
The success boolean field allows you to quickly distinguish success from error responses.
Endpoints
Leads
GET /api/v1/leads
Returns the list of leads collected from your forms.
Note importante : L’API ne retourne que les leads ayant complété le formulaire Discko. Les leads en cours de complétion ne sont pas accessibles via l’API. Un lead est considéré comme “terminé” lorsque l’utilisateur a vu la synthèse générée par Discko.
curl -H "X-Discko-Key: <YOUR_API_KEY>" "https://app.discko.io/api/v1/leads"{
"success": true,
"data": [
{
"id": "req_abc123",
"locked": false,
"url": "https://app.discko.io/acme/leads/req_abc123",
"date": "2025-08-05T08:30:00.000Z",
"status": "NEW",
"completion": 100,
"category": "Web Development",
"contact": {
"type": "COMPANY",
"firstName": "Jane",
"lastName": "Smith",
"email": "user@example.com",
"phone": "+1234567890",
"linkedin": "https://linkedin.com/in/janesmith",
"jobTitle": "CEO",
"discProfile": "Dominant",
"discProfileExplanation": "The communication style is direct, concise, and assertive. The prospect doesn’t elaborate, gets straight to the point, and delivers their message clearly and without ambiguity"
},
"company": {
"name": "Example Corp",
"address": "123 Business St, New York, NY",
"website": "https://example.com"
},
"analysis": {
"fitScore": 2,
"fitScoreExplanation": "The prospect wants to purchase a service that perfectly matches your offer. The answers are consistent, and no blocking constraints have been identified. → Score 2.",
"intentScore": 2,
"intentScoreExplanation": "The prospect expresses a clear and mature intention, has defined a budget, faces no technical obstacles, and provides precise answers. They are therefore genuinely in the purchasing stage and looking to move forward. → Score 2",
"budget": "10000-15000",
"budgetExplanation": "Budget aligns well with scope",
"deadline": "2025-09-15T00:00:00.000Z",
"deadlineExplanation": "Project needs to be completed before Q4",
"score": 7
},
"summary": {
"abstract": "High-value lead with strong fit and intent",
"needs": "Modern website with e-commerce",
"comment": "Looking for quick turnaround",
"categories": [
{
"name": "Technical Requirements",
"description": "Core technical specifications for the project",
"summary": [
"E-commerce platform integration",
"Mobile-responsive design",
"Payment gateway setup"
]
},
{
"name": "Business Goals",
"description": "Key business objectives",
"summary": [
"Increase online sales",
"Improve customer experience",
"Launch before Q4"
]
}
]
}
}
]
}GET /api/v1/leads/:id
Returns a single lead by ID with full details.
Note importante : L’API ne retourne que les leads ayant complété le formulaire Discko. Les leads en cours de complétion ne sont pas accessibles via l’API. Un lead est considéré comme “terminé” lorsque l’utilisateur a vu la synthèse générée par Discko.
curl -H "X-Discko-Key: <YOUR_API_KEY>" "https://app.discko.io/api/v1/leads/req_abc123"{
"success": true,
"data": {
"id": "req_abc123",
"locked": false,
"url": "https://app.discko.io/acme/leads/req_abc123",
"date": "2025-08-27T12:44:38.712Z",
"status": "NEW",
"completion": 100,
"category": "Digital Marketing",
"contact": {
"type": "PERSON",
"firstName": "Alex",
"lastName": "Doe",
"email": "alex.doe@email.com",
"phone": "+1234567890",
"address": "456 Main St, Los Angeles, CA",
"discProfile": "Steady",
"discProfileExplanation": "The communication style is direct, concise, and assertive. The prospect doesn’t elaborate, gets straight to the point, and delivers their message clearly and without ambiguity"
},
"company": null,
"analysis": {
"fitScore": 1,
"fitScoreExplanation": "The prospect wants to purchase a service that perfectly matches your offer. The answers are consistent, and no blocking constraints have been identified. → Score 2.",
"intentScore": 2,
"intentScoreExplanation": "The prospect expresses a clear and mature intention, has defined a budget, faces no technical obstacles, and provides precise answers. They are therefore genuinely in the purchasing stage and looking to move forward. → Score 2",
"budget": "5000-10000",
"budgetExplanation": "Budget is appropriate for the scope of work",
"deadline": "2025-09-27T00:00:00.000Z",
"deadlineExplanation": "Needs to start within 30 days",
"score": 5
},
"summary": {
"abstract": "Qualified lead with clear needs and realistic timeline",
"needs": "Comprehensive digital marketing strategy including SEO and content marketing",
"comment": "Previous experience with digital marketing agencies",
"categories": [
{
"name": "SEO Strategy",
"description": "Search engine optimization requirements",
"summary": [
"Keyword research and optimization",
"Technical SEO improvements",
"Local SEO focus"
]
},
{
"name": "Content Marketing",
"description": "Content creation and distribution needs",
"summary": [
"Blog content strategy",
"Social media content calendar",
"Email marketing campaigns"
]
}
]
}
}
}Error Response Example
{
"success": false,
"error": {
"code": "LEAD_NOT_FOUND",
"message": "Lead not found",
"details": {
"lead_id": "req_abc123"
}
},
"timestamp": "2025-12-18T10:30:00Z"
}Error Codes
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | API key is missing or invalid. |
LEAD_NOT_FOUND | 404 | The requested lead does not exist or is not yet finished. |
PUT /api/v1/leads/:id
Update a lead’s status.
Note importante : L’API ne retourne que les leads ayant complété le formulaire Discko. Les leads en cours de complétion ne sont pas accessibles via l’API. Un lead est considéré comme “terminé” lorsque l’utilisateur a vu la synthèse générée par Discko.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status | String | Yes | Lead status: "NEW", "IN_PROGRESS", "WON", or "LOST" |
Example Request
curl -X PUT "https://app.discko.io/api/v1/leads/req_abc123" \
-H "X-Discko-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"status": "IN_PROGRESS"}'const API_URL = "https://app.discko.io/api/v1";
async function updateLeadStatus(leadId, status) {
const response = await fetch(`${API_URL}/leads/${leadId}`, {
method: 'PUT',
headers: {
"X-Discko-Key": process.env.DISCKO_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({ status })
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
return response.json();
}
// Usage
await updateLeadStatus('req_abc123', 'IN_PROGRESS');Response
Returns the updated lead object with the same structure as GET /api/v1/leads/:id.
{
"success": true,
"data": {
"id": "req_abc123",
"locked": false,
"url": "https://app.discko.io/acme/leads/req_abc123",
"date": "2025-08-27T12:44:38.712Z",
"status": "IN_PROGRESS",
"completion": 100,
"category": "Digital Marketing",
"contact": {
"type": "PERSON",
"firstName": "Alex",
"lastName": "Doe",
"email": "alex.doe@email.com",
"phone": "+1234567890",
"address": "456 Main St, Los Angeles, CA",
"discProfile": "Steady",
"discProfileExplanation": "The communication style is direct, concise, and assertive. The prospect doesn't elaborate, gets straight to the point, and delivers their message clearly and without ambiguity"
},
"company": null,
"analysis": {
"fitScore": 1,
"fitScoreExplanation": "The prospect wants to purchase a service that perfectly matches your offer. The answers are consistent, and no blocking constraints have been identified. → Score 2.",
"intentScore": 2,
"intentScoreExplanation": "The prospect expresses a clear and mature intention, has defined a budget, faces no technical obstacles, and provides precise answers. They are therefore genuinely in the purchasing stage and looking to move forward. → Score 2",
"budget": "5000-10000",
"budgetExplanation": "Budget is appropriate for the scope of work",
"deadline": "2025-09-27T00:00:00.000Z",
"deadlineExplanation": "Needs to start within 30 days",
"score": 5
},
"summary": {
"abstract": "Qualified lead with clear needs and realistic timeline",
"needs": "Comprehensive digital marketing strategy including SEO and content marketing",
"comment": "Previous experience with digital marketing agencies",
"categories": [
{
"name": "SEO Strategy",
"description": "Search engine optimization requirements",
"summary": [
"Keyword research and optimization",
"Technical SEO improvements",
"Local SEO focus"
]
},
{
"name": "Content Marketing",
"description": "Content creation and distribution needs",
"summary": [
"Blog content strategy",
"Social media content calendar",
"Email marketing campaigns"
]
}
]
}
}
}Error Response Examples
Invalid status value:
{
"success": false,
"error": {
"code": "INVALID_STATUS",
"message": "Status must be one of: NEW, IN_PROGRESS, WON, LOST.",
"details": {
"provided": "INVALID_VALUE",
"allowed": ["NEW", "IN_PROGRESS", "WON", "LOST"]
}
},
"timestamp": "2025-12-18T10:30:00Z"
}Invalid JSON:
{
"success": false,
"error": {
"code": "INVALID_JSON",
"message": "Request body is not valid JSON.",
"details": null
},
"timestamp": "2025-12-18T10:30:00Z"
}Error Codes
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | API key is missing or invalid. |
LEAD_NOT_FOUND | 404 | The requested lead does not exist or is not yet finished. |
INVALID_JSON | 400 | Request body is not valid JSON. |
INVALID_STATUS | 400 | Status must be one of: NEW, IN_PROGRESS, WON, LOST. |
VALIDATION_ERROR | 400 | Request validation failed. |
Format de réponse (LeadExternal)
Le format de réponse pour les endpoints GET /api/v1/leads, GET /api/v1/leads/:id et PUT /api/v1/leads/:id retourne un objet data suivant le schéma ci-dessous.
{
"success": true,
"data": {
"id": "uuid",
"locked": false,
"url": "https://app.discko.io/{organizationSlug}/leads/{leadId}",
"contact": {
"type": "PERSON | COMPANY",
"firstName": "string",
"lastName": "string",
"email": "string",
"phone": "string",
"address": "string (si PERSON)",
"linkedin": "string (si COMPANY)",
"jobTitle": "string (si COMPANY)",
"discProfile": "string | null",
"discProfileExplanation": "string | null"
},
"company": {
"name": "string",
"address": "string",
"website": "string"
},
"analysis": {
"fitScore": 0,
"fitScoreExplanation": "string",
"intentScore": 0,
"intentScoreExplanation": "string",
"budget": "string | null",
"budgetExplanation": "string | null",
"deadline": "string | null",
"deadlineExplanation": "string | null",
"score": 0
},
"summary": {
"abstract": "string",
"categories": [{ "name": "string", "description": "string", "summary": ["string"] }],
"needs": "string",
"comment": "string | null"
},
"date": "ISO timestamp",
"status": "NEW | IN_PROGRESS | WON | LOST",
"completion": 0,
"category": "string"
}
}