Fyndare API
Integrera dina företagssystem med Fyndare. Skapa, hantera och synka annonser programmatiskt.
Snabbstart
- Skapa ett företagskonto på fyndare.se/register (välj "Företag")
- Gå till Dashboard → API och begär API-åtkomst
- När din ansökan är godkänd skapar du en API-nyckel (nyckeln visas bara en gång — spara den!)
- Gör din första förfrågan:

curl -H "Authorization: Bearer YOUR_API_KEY" \
https://fyndare.se/api/v1/meBas-URL: https://fyndare.se/api/v1

Autentisering
Alla API-förfrågningar kräver en Bearer-token i Authorization-headern.
Authorization: Bearer fyn_live_abc123...Live-nycklar
fyn_live_*Skapar riktiga, publikt synliga annonser.
Test-nycklar
fyn_test_*Skapar utkastannonser. Inte synliga publikt. Säkra för tester.
API-nycklar hashas med SHA-256 och lagras aldrig i klartext. En nyckel visas bara en gång vid skapandet. Om du tappar bort den, återkalla den gamla nyckeln och skapa en ny.
Svarsformat
Alla svar använder ett konsekvent JSON-format:
{
"success": true,
"data": { ... },
"meta": {
"requestId": "req_a1b2c3d4e5f6",
"timestamp": "2026-02-15T14:30:00.000Z"
}
}{
"success": true,
"data": [ ... ],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"pages": 8,
"hasMore": true
},
"meta": { ... }
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Title must be at least 5 characters",
"details": [
{ "field": "title", "message": "Title must be at least 5 characters" }
]
},
"meta": { ... }
}Begränsningar
| Metod | Gräns | Fönster |
|---|---|---|
| GET | 300 förfrågningar | per minut |
| POST / PATCH / PUT / DELETE | 30 förfrågningar | per minut |
När gränsen överskrids får du ett 429-svar med felkoden RATE_LIMITED. Vänta och försök igen med exponentiell backoff.
Referensdata
Använd dessa endpoints för att hitta giltiga kategori- och platssluggar när du skapar annonser. Cachea dem lokalt — de ändras sällan.
/categoriesLista alla kategorier med underkategorier och deras attribut.
/locationsLista alla 21 svenska län med tillhörande kommuner.
Annonser
/listingsLista dina egna annonser. Stöder paginering, statusfilter och sortering.
page, limit (max 100), status, sort (newest|oldest|price_asc|price_desc), externalId/listingsSkapa en ny annons.
{
"title": "Volvo V60 2019",
"description": "Välskött familjebil med...",
"price": 259000,
"condition": "GOOD",
"categorySlug": "fordon-bilar",
"locationLan": "vastra-gotalands-lan",
"locationKommun": "goteborg",
"externalId": "INV-001",
"phone": "+46701234567",
"images": [
{ "url": "https://example.com/car1.jpg", "order": 0 },
{ "url": "https://example.com/car2.jpg", "order": 1 }
]
}Idempotency-Key-headern för att undvika dubbletter vid nätverksomförsök./listings/:idHämta en enskild annons via ID.
/listings/:idPartiell uppdatering. Skicka bara de fält du vill ändra.
/listings/:idSoft-delete av en annons (status sätts till REMOVED).
/listings/:id/soldMarkera en annons som såld. Fungerar bara på ACTIVE-annonser.
/listings/:id/renewFörnya en annons (+30 dagar). Fungerar på ACTIVE- eller EXPIRED-annonser.
Bilder
Bilder kan laddas upp på tre sätt: via URL, multipart-uppladdning eller base64-inbäddning. Max 30 bilder per annons.
/listings/:id/imagesLägg till en bild på en annons. Stöder URL, multipart eller base64.
/listings/:id/images/:imageIdTa bort en bild från en annons.
/listings/:id/images/reorderÄndra ordning på bilder genom att skicka en array med bild-ID i önskad ordning.
Externt ID / Upsert
Upsert-mönstret är det rekommenderade sättet att synka ditt lager. Använd ditt eget produkt-ID som externalId — Fyndare skapar eller uppdaterar automatiskt.
/listings/by-external-id/:externalIdOm en annons med detta externalId finns på ditt konto uppdateras den. Annars skapas en ny.
curl -X PUT https://fyndare.se/api/v1/listings/by-external-id/INV-001 \
-H "Authorization: Bearer fyn_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Volvo V60 2019",
"description": "Updated description...",
"price": 249000,
"condition": "GOOD",
"categorySlug": "fordon-bilar",
"locationLan": "vastra-gotalands-lan",
"locationKommun": "goteborg"
}'Bulk-operationer
Bearbeta upp till 50 poster per förfrågan. Partiell framgång stöds — varje post bearbetas oberoende.
/listings/bulkSkapa annonser i bulk (max 50).
/listings/bulkUppdatera annonser i bulk via ID eller externalId (max 50).
/listings/bulkTa bort annonser i bulk (max 50).
/listings/bulk/soldMarkera annonser som sålda i bulk (max 50).
{
"success": true,
"data": {
"total": 3,
"created": 2,
"failed": 1,
"results": [
{ "index": 0, "success": true, "data": { "id": "clxx..." } },
{ "index": 1, "success": true, "data": { "id": "clxy..." } },
{ "index": 2, "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Price is required" } }
]
}
}Webhooks
Ta emot HTTP-notiser när händelser inträffar. Max 5 webhook-endpoints per konto.
Händelser som stöds
| Händelse | Utlösare |
|---|---|
| listing.created | Annons skapad |
| listing.updated | Annons uppdaterad |
| listing.sold | Markerad som såld |
| listing.expired | Annons har gått ut |
| listing.removed | Admin tog bort annonsen |
| message.received | Nytt meddelande på din annons |
| listing.favorited | Någon favoritmarkerade din annons |
/webhooksSkapa en webhook-endpoint. Secret returneras bara en gång.
/webhooksLista dina webhook-endpoints.
/webhooks/:idUppdatera URL, händelser eller aktiv status.
/webhooks/:idTa bort en webhook-endpoint.
/webhooks/:id/testSkicka en test-leverans av webhook.
/webhooks/:id/deliveriesVisa leveranshistorik.
Webhook-payload
{
"event": "listing.sold",
"deliveryId": "del_abc123",
"timestamp": "2026-02-15T14:30:00.000Z",
"data": {
"id": "clxx123",
"externalId": "INV-001",
"soldAt": "2026-02-15T14:30:00.000Z"
}
}Headers som följer med varje leverans:
X-Fyndare-Event: listing.sold
X-Fyndare-Delivery: del_abc123
X-Fyndare-Signature: sha256=abc123...
X-Fyndare-Timestamp: 1708012345Verifiera signaturer
Verifiera X-Fyndare-Signature-headern med HMAC-SHA256 och din webhook-secret:
const crypto = require("crypto");
function verifyWebhook(secret, timestamp, body, signature) {
const expected = crypto
.createHmac("sha256", secret)
.update(timestamp + "." + body)
.digest("hex");
return signature === "sha256=" + expected;
}
// In your handler:
const sig = req.headers["x-fyndare-signature"];
const ts = req.headers["x-fyndare-timestamp"];
const isValid = verifyWebhook(WEBHOOK_SECRET, ts, JSON.stringify(req.body), sig);import hmac, hashlib
def verify_webhook(secret, timestamp, body, signature):
message = f"{timestamp}.{body}"
expected = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
return signature == f"sha256={expected}"Omförsökspolicy
- 1:a försöket: omedelbart
- Omförsök 1: efter 5 minuter
- Omförsök 2: efter 30 minuter
- Omförsök 3: efter 2 timmar
- Efter 10 misslyckade försök i rad: endpoint inaktiveras automatiskt
Återaktivera en inaktiverad endpoint genom att uppdatera den med isActive: true.
Felreferens
| Kod | HTTP | Beskrivning |
|---|---|---|
| UNAUTHORIZED | 401 | Saknad eller ogiltig API-nyckel |
| FORBIDDEN | 403 | Giltig nyckel men otillräckliga rättigheter |
| NOT_FOUND | 404 | Resursen hittades inte |
| VALIDATION_ERROR | 400 | Ogiltig indata (se details-arrayen) |
| RATE_LIMITED | 429 | Gräns överskriden — vänta och försök igen |
| SERVER_ERROR | 500 | Internt fel — försök igen eller kontakta supporten |
Kodexempel
cURL — Skapa en annons
curl -X POST https://fyndare.se/api/v1/listings \
-H "Authorization: Bearer fyn_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-key-123" \
-d '{
"title": "Volvo V60 2019",
"description": "Välskött familjebil med full servicehistorik...",
"price": 259000,
"condition": "GOOD",
"categorySlug": "fordon-bilar",
"locationLan": "vastra-gotalands-lan",
"locationKommun": "goteborg"
}'JavaScript / Node.js
const API_KEY = "fyn_live_...";
const BASE = "https://fyndare.se/api/v1";
async function createListing(data) {
const res = await fetch(`${BASE}/listings`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
return res.json();
}
// Create
const { data: listing } = await createListing({
title: "Volvo V60 2019",
description: "Välskött familjebil...",
price: 259000,
condition: "GOOD",
categorySlug: "fordon-bilar",
locationLan: "vastra-gotalands-lan",
locationKommun: "goteborg",
});
console.log("Created:", listing.id);
// List
const res = await fetch(`${BASE}/listings?page=1&limit=10`, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const { data: listings } = await res.json();
// Mark as sold
await fetch(`${BASE}/listings/${listing.id}/sold`, {
method: "POST",
headers: { "Authorization": `Bearer ${API_KEY}` },
});Python
import requests
API_KEY = "fyn_live_..."
BASE = "https://fyndare.se/api/v1"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
# Create listing
resp = requests.post(f"{BASE}/listings", headers=HEADERS, json={
"title": "Volvo V60 2019",
"description": "Välskött familjebil...",
"price": 259000,
"condition": "GOOD",
"categorySlug": "fordon-bilar",
"locationLan": "vastra-gotalands-lan",
"locationKommun": "goteborg",
})
listing = resp.json()["data"]
print(f"Created: {listing['id']}")
# List
resp = requests.get(f"{BASE}/listings", headers=HEADERS)
listings = resp.json()["data"]
# Mark as sold
requests.post(f"{BASE}/listings/{listing['id']}/sold", headers=HEADERS)Mönster för lager-synk
// Sync your full inventory using the upsert pattern
for (const item of inventory) {
await fetch(
`${BASE}/listings/by-external-id/${item.sku}`,
{
method: "PUT",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: item.name,
description: item.description,
price: item.price,
condition: "NEW",
categorySlug: item.category,
locationLan: "vastra-gotalands-lan",
locationKommun: "goteborg",
}),
}
);
}
// Mark sold items
const soldIds = inventory
.filter(i => i.sold)
.map(i => i.fyndareId);
if (soldIds.length > 0) {
await fetch(`${BASE}/listings/bulk/sold`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ ids: soldIds }),
});
}Konto
/meHämta dina kontouppgifter och detaljer om API-nyckeln.
/me/usageHämta användningsstatistik för den aktuella nyckeln.
days (1-90, standard 30)Behöver du hjälp? [email protected]
Förbyggda lösningar
Vill du slippa bygga integrationen från grunden? Vi har färdiga paket som kopplar vanliga plattformar till Fyndare med minimal konfiguration.
Fyndare Connector — WordPress / WooCommerce
Ett gratis WordPress-plugin som upptäcker om du har WooCommerce-produkter eller ett fordons-CPT och skickar dina annonser till Fyndare automatiskt. API-nyckel och webhook-nyckel skapas åt dig vid aktivering — ingen manuell konfiguration krävs.
- Funkar både med och utan WooCommerce (WP-fordons-CPT stöds)
- Realtidssynk via webhooks — ändringar i butiken speglas på Fyndare inom sekunder
- Publiceras open source under GPL-2.0
- Schemalagd polling var 15:e minut som säkerhetsnät