eduvoför utvecklareTill Eduvo ↗

KOPPLA IHOP ERA SYSTEM

Ett API.
Fler möjligheter.

Koppla ert HR-system, medlemsregister eller CRM till Eduvo. Skapa deltagare, tilldela kurser och hämta resultat med REST eller GraphQL.

OAuth 2.0REST + GraphQLOrganisationsbunden åtkomst

STEG 1

Kom igång med ett läsanrop

Du behöver API-adress, klient-ID och klienthemlighet. En organisationsadministratör hanterar API-klienter under Inställningar → Integrationer när funktionen är tillgänglig i miljön. Hemligheten visas när klienten skapas.

  1. Skapa en klient med courses:read.
  2. Hämta en åtkomsttoken med klientens uppgifter.
  3. Använd token för att läsa organisationens publicerade kurser.

Exemplet körs på en server eller i en lokal terminal med Bash, curl och jq. Ersätt exempeladressen och klient-ID:t. Ange hemligheten när terminalen frågar.

Terminal · OAuth och första anropet
API_BASE_URL='https://er-api-adress.example'
CLIENT_ID='ert-klient-id'
printf 'Klienthemlighet: '
read -r -s CLIENT_SECRET
printf '\n'
TOKEN_RESPONSE=$(curl --fail-with-body --silent --show-error \
  "$API_BASE_URL/oauth/token" \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "client_secret=$CLIENT_SECRET" \
  --data-urlencode 'scope=courses:read')
ACCESS_TOKEN=$(printf '%s' "$TOKEN_RESPONSE" | jq -er '.access_token')
unset CLIENT_SECRET TOKEN_RESPONSE
curl --fail-with-body --silent --show-error \
  "$API_BASE_URL/v1/courses?limit=25" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Token gäller i 3 600 sekunder. Hämta en ny före utgången. Begär bara scopes som klienten redan har tilldelats. Organisationen bestäms av klienten; ett anrop kan inte välja en annan organisation.

Vilka behörigheter behövs?
Uppgift Scope
Läsa / skriva deltagare users:read / users:write
Läsa kurser courses:read
Läsa / skriva kurstilldelningar enrollments:read / enrollments:write
Läsa slutföranden completions:read
Läsa intyg certificates:read
Hantera webhooks webhooks:manage

STEG 2

Välj hur deltagare identifieras

Organisationen kan välja e-post, anställnings-ID eller externt ID med egen benämning, exempelvis medlemsnummer. Valet används för register och matchning. Inloggningen fungerar som tidigare.

Fält Betydelse Exempel
id / userId Eduvos stabila interna deltagar-ID. Använd det i kurstilldelningar. usr_…
identifierType + identifierValue Organisationens identifierare: email, employeeId eller customId. employeeId + 00123
externalId Separat koppling till ert källsystem. Behåller sin betydelse när organisationen byter typ. hr-987

E-post trimmas och omvandlas till gemener. Övriga ID:n trimmas, bevarar inledande nollor och skiljer på stora och små bokstäver. Skicka alltid ID:n som strängar. Identifieraren måste vara unik inom organisationen.

Aktivera eller byt identifierartyp för befintliga deltagare
  1. Välj typ under Inställningar → Unik deltagaridentifierare och gör en förhandskontroll.
  2. Komplettera saknade värden och rätta dubbletter i deltagardetaljer eller via CSV/XLSX med userId och email, employeeId eller customId. Högst 100 deltagare per kompletteringsimport.
  3. Aktivera när alla berörda deltagare har giltiga, unika värden. Kontrollen görs på nytt vid aktivering.

Kurstilldelningar och resultat behålls. Nya deltagare behöver den valda identifieraren. E-post kan fortfarande användas för kontakt och inbjudningar. Befintliga organisationer behåller tidigare beteende tills valet aktiveras.

STEG 3

Skapa deltagare och tilldela en kurs med REST

REST använder JSON under /v1. Hämta en token med users:write, courses:read och enrollments:write för exemplen nedan. Ersätt scope-värdet i tokenanropet ovan med dessa tre scopes separerade med mellanslag.

Skapa eller uppdatera via ert källsystems ID

PUT /v1/users/external/{externalId} matchar på integrationsnyckeln. Använd samma nyckel för samma person och URL-koda den vid behov. Exemplet förutsätter att anställnings-ID är organisationens aktiva val.

Terminal · deltagare
USER_RESPONSE=$(curl --fail-with-body --silent --show-error \
  -X PUT "$API_BASE_URL/v1/users/external/hr-987" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: hr-987-sync-v1' \
  --data '{"displayName":"Exempeldeltagare","email":"person@example.test","employeeId":"00123"}')
USER_ID=$(printf '%s' "$USER_RESPONSE" | jq -er '.id')

Tilldela en publicerad kurs

Hämta ett courseId från GET /v1/courses. Tilldelningen kopplas till kursens publicerade version. Byt exempelvärdet nedan till ert kurs-ID.

Terminal · kurstilldelning
COURSE_ID='ert-publicerade-kurs-id'
ENROLLMENT_RESPONSE=$(curl --fail-with-body --silent --show-error \
  "$API_BASE_URL/v1/enrollments" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: hr-987-kurs-tilldelning-v1' \
  --data "$(jq -n --arg userId "$USER_ID" --arg courseId "$COURSE_ID" \
    '{userId:$userId,courseId:$courseId}')")
ENROLLMENT_ID=$(printf '%s' "$ENROLLMENT_RESPONSE" | jq -er '.id')

En tilldelning skapar kopplingen till kursen. Anropet är inte i sig ett mejlutskick eller bevis på att deltagaren har öppnat kursen.

Andra vanliga REST-anrop
  • GET /v1/users?identifier=00123 – uppslag via organisationens aktiva identifierare. Kräver users:read.
  • PATCH /v1/users/{id} – uppdatera en känd deltagare.
  • DELETE /v1/enrollments/{id} – avbryt en tilldelning.
  • DELETE /v1/users/{id} – köa ett raderingsjobb. HTTP 204 betyder mottagen begäran, inte färdig radering.

STEG 4

Välj dina fält med GraphQL

Skicka POST /graphql med samma OAuth-token och scopes som för REST. JSON-kroppen innehåller query, valfria variables och vid behov operationName. Skicka Content-Type: application/json och Authorization: Bearer ….

JSON · läs deltagare, kräver users:read
{
  "query": "query Participants($cursor: String) { users(limit: 25, cursor: $cursor) { data { id displayName identifierType identifierValue } nextCursor } }",
  "variables": { "cursor": null }
}

Matcha på organisationens identifierare

upsertUser skapar deltagaren om identifieraren saknas, annars uppdateras samma deltagare. Exemplet kräver users:write och anställnings-ID eller externt ID som aktiv typ.

JSON · skapa eller uppdatera deltagare
{
  "query": "mutation Sync($key: String!, $person: UserInput!) { upsertUser(identifier: $key, input: $person) { id identifierValue } }",
  "variables": {
    "key": "00123",
    "person": { "displayName": "Exempeldeltagare", "email": "person@example.test" }
  }
}

Skicka en stabil Idempotency-Key för mutationer och en mutation per begäran. En upsert får inte samtidigt ändra värdet den matchar på; använd updateUser(id: …) för sådana ändringar.

Frågor, mutationer och gränser

Frågor: users, user, courses, course, enrollments, enrollment, progress, progresses, completions och completion.

Mutationer: createUser, updateUser, upsertUser, createEnrollment och cancelEnrollment.

Högst 100 poster per sida, frågedjup 8, 20 rotfält och viktad komplexitet 2000. Dokument begränsas till 32 KiB och 5000 token. Introspektion är avstängd: använd det nedladdningsbara schemat.

STEG 5

Följ framsteg och slutföranden

Läs framsteg med GET /v1/enrollments/{id}/progress eller GraphQL progress(id: …). Det kräver enrollments:read.

Terminal · framsteg
curl --fail-with-body --silent --show-error \
  "$API_BASE_URL/v1/enrollments/$ENROLLMENT_ID/progress" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Svaret innehåller state, percentComplete och completedAt. Null betyder att uppgiften inte är registrerad. Tilldelningens status: active betyder inte i sig att kursen är slutförd.

Slutföranden läses via GET /v1/completions eller GraphQL completions med completions:read. Intyg läses via REST /v1/certificates med certificates:read.

Läs alla sidor

Listor returnerar data och nextCursor. Börja med limit=25 och fortsätt med nästa cursor tills den är null. En tom sida kan fortfarande ha en nästa cursor. URL-koda cursorvärdet i REST.

STEG 6

Låt Eduvo meddela när något händer

Skapa en HTTPS-mottagare och registrera den under Inställningar → Integrationer eller med POST /v1/webhooks. Det kräver webhooks:manage.

JSON · prenumerera på slutföranden
{
  "url": "https://ert-system.example/hooks/eduvo",
  "events": ["course.completed"]
}
  1. Spara signeringshemligheten när prenumerationen skapas. Den visas bara då.
  2. Beräkna HMAC-SHA256 över den råa, oförändrade HTTP-kroppen. Jämför med X-Eduvo-Signature, i formatet sha256=<hex>, med en jämförelse som tar konstant tid.
  3. Kontrollera X-Eduvo-Timestamp och avvisa gamla leveranser enligt er tidsgräns. Deduplicera med X-Eduvo-Delivery. Svara 2xx när händelsen säkert tagits emot.

API-prenumerationer stöder user.created, user.updated, enrollment.created, enrollment.cancelled, course.started, course.completed och certificate.issued.

Leveranser kan komma flera gånger. Efter ett misslyckat försök görs återförsök efter 5 minuter, 30 minuter, 2 timmar, 12 timmar och 24 timmar. Ping med HTTP 202 betyder att leveransen köats, inte att den nått mottagaren. Webhook-dispatchern måste vara konfigurerad i er miljö.

Anslut andra plattformar

HR och medlemsregister

Matcha på vald identifierare, spara Eduvos interna ID och tilldela rätt publicerad kurs. Synka ändringar när de sker i källsystemet.

Power Automate

Använd skyddade HTTP-anrop för token, deltagare och kurstilldelning. Förvara hemligheter i en godkänd anslutning eller hemlighetslagring.

CRM och egna system

Välj REST för resurser eller GraphQL för att styra svarens fält. Kör kopplingen på serversidan; klienthemligheter hör inte hemma i webbläsarkod.

Återförsök och felsökning

Använd samma Idempotency-Key för samma logiska skrivning med samma indata. Byt nyckel för en ny ändring. Stödet gäller deltagarskrivningar samt skapande och avbrytande av tilldelningar; anta inte att webhook-administrationsanrop dedupliceras av headern.

Fel Åtgärd
401 · unauthorized Kontrollera token, utgångstid och om klienten har återkallats.
403 · insufficient_scope Tilldela och begär rätt scope för operationen.
identifier_required Skicka organisationens valda identifierare.
409 · identifier_conflict Kontrollera vilken deltagare som redan har värdet. Slå inte ihop personer automatiskt.
409 · idempotency_conflict Nyckeln har använts med andra indata. Kontrollera om det är en ny ändring.
429 eller tillfälligt 5xx Försök igen med ökande väntetid och slumpmässig spridning. Behåll nyckeln för samma skrivning.
query_too_complex Minska GraphQL-frågans fält, sidstorlek eller antal rotfält.

Hastighetsgränsen är 120 begäranden per minut per klient och en separat gräns för IP-adressen. REST-fel har error.code och requestId. GraphQL använder errors[].extensions.code och kan returnera fel även med HTTP 200. Kontrollera alltid både HTTP-status och svarskropp.

Spara begärans-ID från X-Request-Id, tidpunkt, status och felkod vid felsökning. Undvik token, klienthemligheter och personuppgifter i loggar.

API-referens och schema

Ladda ned kontraktet för att kontrollera tillgängliga fält. API-adressen i OpenAPI är en platshållare som ska ersättas med er miljös adress.

REST-endpoints

Läser API-referensen…