Försäkringskassan
List, read and update a company's Fritidskortet data. The /fk endpoints expose the
whole company register (minimal data), plus a single company's enrollment status
(fk_status), its basic organization data (name, address, contact info), and every
grant that is activated on the company.
There are three endpoints:
| Method | Path | Purpose |
|---|---|---|
GET | /api/v3/company/fk | List the entire register — minimal data (name, org_number, parent) for every company |
GET | /api/v3/company/{company_id}/fk | Fetch name, address, contact info, fk_status and activated grants for one company |
PUT | /api/v3/company/{company_id}/fk | Update fk_status — and only fk_status |
Related endpoints (not covered in detail here):
GET /api/v3/company/fk/status/{company_id}— check the company's utförarstatus against the external Fritidskortet system.GET/POST/DELETE /api/v3/grant/...— manage grant types and grant activations (what populatescompany_grantsbelow).
OpenAPI specification
A machine-readable OpenAPI 3.0 spec for these endpoints is available at
company-fk.yaml. Import it into Swagger UI,
Postman or a client generator.
Authentication
Both endpoints require an OAuth 2.0 access token. Obtain one with your
client_id and client_secret using HTTP Basic auth:
curl -X POST https://<instance>.memlist.se/api/v3/access/user/basic \
-H "Authorization: Basic $(echo -n 'your-client-id:your-client-secret' | base64)"
The response contains an access_token. Send it on every request:
Authorization: Bearer <access_token>
See Authentication for the full flow, including token refresh, rate limits and error handling.
Permissions
The access token carries the permissions of its credentials' access group:
GETrequires an access group that includes thecompanymodule.PUTadditionally requires theCOMPANY.U(company update) permission. Without it the call returns403.
GET /api/v3/company/fk
Lists every company in the register as a minimal record. This returns the whole register in a single response — there is no pagination and no filtering.
Use it to enumerate all organizations (for example to sync the register to an external
system). When you need the full Fritidskortet detail for one company — fk_status,
contact info, activated grants — use the single-company endpoint below.
Parameters
None. The endpoint takes no path or query parameters.
Response — 200 OK
An array with one entry per non-deleted company. Each entry carries only the company's
name and organization number, plus its parent company (null for a top-level
organization):
[
{
"name": "IFK Exempelstad",
"org_number": "802481-1234",
"parent": {
"org_number": "802000-0001",
"name": "Exempelförbundet"
}
},
{
"name": "Exempelförbundet",
"org_number": "802000-0001",
"parent": null
}
]
Field notes:
parent— the company's parent organization in the hierarchy, ornullfor a top-level company.- Deleted companies are excluded.
- The response is intentionally minimal: it carries no
company_id,fk_status, contact details or grants. Fetch a single company's/fkview for that data.
Example
curl -s "https://<instance>.memlist.se/api/v3/company/fk" \
-H "Authorization: Bearer $TOKEN" | jq
Errors
| Status | Body | When |
|---|---|---|
401 | – | Missing or expired token |
500 | – | Unexpected server error |
GET /api/v3/company/{company_id}/fk
Returns the Fritidskortet-relevant view of a single company.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
company_id | path | string | Yes | The company's id (a 36-char string id, not the numeric uuid-less legacy id) |
Response — 200 OK
{
"company_id": "5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1",
"uuid": "9c1b2f4e-77aa-4f0c-9a41-2f8d0c3e5b21",
"name": "IFK Exempelstad",
"shortname": "IFK EX",
"org_number": "802481-1234",
"fk_status": "ACTIVE",
"street": "Föreningsgatan 12",
"co": null,
"zipcode": "41255",
"post": "Göteborg",
"country": "Sverige",
"email": "kansli@ifkexempelstad.se",
"phone": "031-123456",
"landline": null,
"web": "https://ifkexempelstad.se",
"c_name": "Anna Andersson",
"c_email": "anna@ifkexempelstad.se",
"c_phone": "0701-234567",
"company_grants": [
{
"id": 3,
"created_at": "2026-08-14T13:02:11",
"grant": {
"id": 1,
"uuid": "d5a8e9c2-1b3f-4a6d-8e2c-9f1b0a7c4d3e",
"name": "Projektbidrag",
"descr": "Bidrag för tidsbegränsade projekt"
}
},
{
"id": 8,
"created_at": "2026-08-14T13:05:40",
"grant": {
"id": 2,
"uuid": "f2c1d0b9-8a7e-4c5d-b3a2-1e0f9d8c7b6a",
"name": "Verksamhetsbidrag",
"descr": "Löpande bidrag för ordinarie verksamhet"
}
}
]
}
Field notes:
c_name/c_email/c_phone— the company's contact person;email/phoneare the organization's general contact details.company_grants— one entry per grant activated on the company. An empty array means no grants are activated.- Fields that are unset in the database are returned as
null(seecoandlandlineabove).
Errors
| Status | Body | When |
|---|---|---|
400 | { "reason": "company_id: ...", "code": "validation_error", ... } | Malformed path parameter |
401 | – | Missing or expired token |
404 | { "reason": "company not found" } | No company with that id, or the company is deleted |
500 | – | Unexpected server error |
PUT /api/v3/company/{company_id}/fk
Updates the company's Fritidskortet enrollment status. This endpoint updates
only fk_status. Any other field present in the request body is ignored —
it is not possible to change the company's name, address or anything else here.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
company_id | path | string | Yes | The company's id |
fk_status | body | string | Yes | One of the values below |
fk_status values
The enum describes how far along the company is in the Fritidskortet enrollment flow:
| Value | Meaning |
|---|---|
NONE | Not enrolled (the default for every company) |
ML_ADDED | Added as an utförare on the Memlist side |
FK_ADDED | Registered in the external Fritidskortet system |
ACTIVE | Enrollment complete — the company is an active utförare |
REJECTED | The enrollment was rejected |
Request
PUT /api/v3/company/5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1/fk
Content-Type: application/json
Authorization: Bearer <token>
{ "fk_status": "ACTIVE" }
Response — 200 OK
{
"company_id": "5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1",
"fk_status": "ACTIVE"
}
Errors
| Status | Body | When |
|---|---|---|
400 | see below | fk_status missing or not a valid enum value |
401 | – | Missing or expired token |
403 | – | The user's access group lacks the COMPANY.U permission |
404 | { "reason": "company not found" } | No company with that id, or the company is deleted |
500 | – | Unexpected server error |
Validation failures (400) return a structured payload — errors maps each failing
field to its messages so clients can render inline errors:
{
"reason": "fk_status: Invalid enum value. Expected 'NONE' | 'ML_ADDED' | 'FK_ADDED' | 'ACTIVE' | 'REJECTED', received 'ACTIV'",
"code": "validation_error",
"errors": {
"fk_status": [
"Invalid enum value. Expected 'NONE' | 'ML_ADDED' | 'FK_ADDED' | 'ACTIVE' | 'REJECTED', received 'ACTIV'"
]
},
"form_errors": []
}
Quick reference: curl
HOST="https://<instance>.memlist.se"
# Authenticate (client_id:client_secret via HTTP Basic)
TOKEN=$(curl -s -X POST "$HOST/api/v3/access/user/basic" \
-H "Authorization: Basic $(echo -n 'your-client-id:your-client-secret' | base64)" \
| jq -r '.access_token')
# Get FK data for a company
curl -s "$HOST/api/v3/company/5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1/fk" \
-H "Authorization: Bearer $TOKEN" | jq
# Set fk_status
curl -s -X PUT "$HOST/api/v3/company/5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1/fk" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"fk_status":"ACTIVE"}' | jq
Working examples
- JavaScript
- Python
Node 18+, no dependencies.
const HOST = 'https://<instance>.memlist.se';
const CLIENT_ID = process.env.MEMLIST_CLIENT_ID;
const CLIENT_SECRET = process.env.MEMLIST_CLIENT_SECRET;
async function login() {
const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
const res = await fetch(`${HOST}/api/v3/access/user/basic`, {
method: 'POST',
headers: { Authorization: `Basic ${credentials}` }
});
if (!res.ok) {
throw new Error(`login failed: ${res.status}`);
}
const data = await res.json();
return data.access_token;
}
async function get_company_fk(token, company_id) {
const res = await fetch(`${HOST}/api/v3/company/${company_id}/fk`, {
headers: { Authorization: `Bearer ${token}` }
});
if (res.status === 404) {
return null; // company not found (or deleted)
}
if (!res.ok) {
throw new Error(`get fk failed: ${res.status} ${await res.text()}`);
}
return res.json();
}
async function set_fk_status(token, company_id, fk_status) {
const res = await fetch(`${HOST}/api/v3/company/${company_id}/fk`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ fk_status })
});
if (res.status === 400) {
const err = await res.json();
throw new Error(`invalid fk_status: ${err.reason}`);
}
if (!res.ok) {
throw new Error(`put fk failed: ${res.status} ${await res.text()}`);
}
return res.json(); // { company_id, fk_status }
}
async function main() {
const company_id = '5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1';
const token = await login();
const company = await get_company_fk(token, company_id);
if (!company) {
console.log('company not found');
return;
}
console.log(`${company.name} (${company.org_number})`);
console.log(`fk_status: ${company.fk_status}`);
console.log(`contact: ${company.c_name} <${company.c_email}>`);
console.log('activated grants:');
for (const row of company.company_grants) {
console.log(` - ${row.grant.name} (since ${row.created_at})`);
}
// Promote the company to ACTIVE
const updated = await set_fk_status(token, company_id, 'ACTIVE');
console.log(`updated fk_status -> ${updated.fk_status}`);
}
main().catch(err => {
console.error(err);
process.exit(1);
});
Run with:
MEMLIST_CLIENT_ID=your-client-id MEMLIST_CLIENT_SECRET=your-client-secret node fk_example.js
Python 3 with the requests library.
import base64
import os
import sys
import requests
HOST = 'https://<instance>.memlist.se'
CLIENT_ID = os.environ['MEMLIST_CLIENT_ID']
CLIENT_SECRET = os.environ['MEMLIST_CLIENT_SECRET']
VALID_FK_STATUSES = {'NONE', 'ML_ADDED', 'FK_ADDED', 'ACTIVE', 'REJECTED'}
def login() -> str:
credentials = base64.b64encode(
f'{CLIENT_ID}:{CLIENT_SECRET}'.encode()
).decode()
res = requests.post(
f'{HOST}/api/v3/access/user/basic',
headers={'Authorization': f'Basic {credentials}'},
timeout=10,
)
res.raise_for_status()
return res.json()['access_token']
def get_company_fk(token: str, company_id: str) -> dict | None:
res = requests.get(
f'{HOST}/api/v3/company/{company_id}/fk',
headers={'Authorization': f'Bearer {token}'},
timeout=10,
)
if res.status_code == 404:
return None # company not found (or deleted)
res.raise_for_status()
return res.json()
def set_fk_status(token: str, company_id: str, fk_status: str) -> dict:
if fk_status not in VALID_FK_STATUSES:
raise ValueError(f'invalid fk_status: {fk_status}')
res = requests.put(
f'{HOST}/api/v3/company/{company_id}/fk',
headers={'Authorization': f'Bearer {token}'},
json={'fk_status': fk_status},
timeout=10,
)
if res.status_code == 400:
raise ValueError(f'rejected by server: {res.json()["reason"]}')
res.raise_for_status()
return res.json() # { company_id, fk_status }
def main() -> None:
company_id = '5cf693b1-8a20-4bd4-b3b0-5d2f45f2b6a1'
token = login()
company = get_company_fk(token, company_id)
if company is None:
print('company not found')
sys.exit(1)
print(f"{company['name']} ({company['org_number']})")
print(f"fk_status: {company['fk_status']}")
print(f"contact: {company['c_name']} <{company['c_email']}>")
print('activated grants:')
for row in company['company_grants']:
print(f" - {row['grant']['name']} (since {row['created_at']})")
# Promote the company to ACTIVE
updated = set_fk_status(token, company_id, 'ACTIVE')
print(f"updated fk_status -> {updated['fk_status']}")
if __name__ == '__main__':
main()
Run with:
MEMLIST_CLIENT_ID=your-client-id MEMLIST_CLIENT_SECRET=your-client-secret python3 fk_example.py