Workera · AsyncAPI Specification

Workera Webhooks

Version 1.0

Workera delivers HTTP POST webhooks to a customer-configured endpoint when assessment, program and appeal events occur. Endpoints, event-type subscriptions and the shared signing secret are provisioned per company through the customer's Workera CSM; there is no self-serve webhook management API. Every request carries an `X-Workera-Signature` header containing `sha256=`, an HMAC-SHA256 digest of the raw request body keyed with the shared secret. Consumers are told to verify it. Delivery is at-least-once. A non-2xx response is retried immediately, then after 1 minute, 5 minutes, 15 minutes and 1 hour; after 5 failed attempts delivery stops and a notification email is sent to the configured contact. Consumers are directed to deduplicate on the payload `identifier`. Enterprise employee association is required for delivery: events for users with no resolvable enterprise employee record are silently skipped, as are addresses on the company's webhook exclusion list.

View Spec View on GitHub Skills IntelligenceSkills AssessmentHuman ResourcesLearning and DevelopmentTalent ManagementWorkforce AnalyticsArtificial IntelligenceBenchmarkingEnterprise SoftwareMCPCompanyAsyncAPIEventsWebhooks

Channels

scoreUpdated
assessmentStarted
assessmentCompleted
programCompleted
selfScoreCompleted
appealApproved

Messages

scoreUpdated
Score updated
Sent when a user completes an assessment that generates a new proficiency score, covering both baseline assessments and skill boost sessions. Superseded by assessment_completed, which uses a flat payload; no retirement date is published for score_updated.
assessmentStarted
Assessment started
Sent once when a learner begins an assessment. Fires for a baseline assessment, a mini assessment (scoring-v2) and a full reassessment. Does NOT fire on resume of an in-progress assessment, or for non-enterprise learners.
assessmentCompleted
Assessment completed
The v2 replacement for score_updated, using a flat payload with topic-level skill ratings and behaviors. Fires for baseline, mini and full reassessments regardless of initiative_type.
programCompleted
Program completed
Sent once per learner per program when the learner's latest score satisfies the completion threshold (total_required) for the program's required, non-elective capabilities.
selfScoreCompleted
Self score completed
Sent when a learner submits a self-assessment score through the contextualized self-assessment flow. Distinct from the objective assessment events.
appealApproved
Appeal approved
Sent when a scoring appeal is approved and the learner's capability score has been updated as a result. Not sent when an appeal is rejected, because no score change occurs.

Servers

https
consumer
The subscriber's own HTTPS endpoint. Workera is the publisher; the URL is set per company by the Workera CSM.

AsyncAPI Specification

Raw ↑
generated: '2026-09-04'
method: derived
source: https://skills.workera.ai/api/docs
x-provenance: >-
  Workera publishes no AsyncAPI document. This 3.0.0 document was DERIVED by API Evangelist from the
  webhook catalog Workera documents in prose and JSON payload examples inside the OpenAPI
  info.description at https://skills.workera.ai/api/docs. Every event name, field, enum and retry value
  below is quoted from that source; nothing was invented. It is our artifact, not Workera's — see
  conformance/workera-conformance.yml (id asyncapi, conforms false).
asyncapi: 3.0.0
info:
  title: Workera Webhooks
  version: '1.0'
  description: |
    Workera delivers HTTP POST webhooks to a customer-configured endpoint when assessment, program and
    appeal events occur. Endpoints, event-type subscriptions and the shared signing secret are
    provisioned per company through the customer's Workera CSM; there is no self-serve webhook
    management API.

    Every request carries an `X-Workera-Signature` header containing `sha256=<hex>`, an HMAC-SHA256
    digest of the raw request body keyed with the shared secret. Consumers are told to verify it.

    Delivery is at-least-once. A non-2xx response is retried immediately, then after 1 minute, 5
    minutes, 15 minutes and 1 hour; after 5 failed attempts delivery stops and a notification email is
    sent to the configured contact. Consumers are directed to deduplicate on the payload `identifier`.

    Enterprise employee association is required for delivery: events for users with no resolvable
    enterprise employee record are silently skipped, as are addresses on the company's webhook
    exclusion list.
  contact:
    name: Workera
    url: https://skills.workera.ai/api/docs
defaultContentType: application/json
servers:
  consumer:
    host: customer-configured
    protocol: https
    description: >-
      The subscriber's own HTTPS endpoint. Workera is the publisher; the URL is set per company by the
      Workera CSM.
channels:
  scoreUpdated:
    address: (subscriber endpoint)
    messages:
      scoreUpdated:
        $ref: '#/components/messages/scoreUpdated'
  assessmentStarted:
    address: (subscriber endpoint)
    messages:
      assessmentStarted:
        $ref: '#/components/messages/assessmentStarted'
  assessmentCompleted:
    address: (subscriber endpoint)
    messages:
      assessmentCompleted:
        $ref: '#/components/messages/assessmentCompleted'
  programCompleted:
    address: (subscriber endpoint)
    messages:
      programCompleted:
        $ref: '#/components/messages/programCompleted'
  selfScoreCompleted:
    address: (subscriber endpoint)
    messages:
      selfScoreCompleted:
        $ref: '#/components/messages/selfScoreCompleted'
  appealApproved:
    address: (subscriber endpoint)
    messages:
      appealApproved:
        $ref: '#/components/messages/appealApproved'
operations:
  sendScoreUpdated:
    action: send
    channel:
      $ref: '#/channels/scoreUpdated'
  sendAssessmentStarted:
    action: send
    channel:
      $ref: '#/channels/assessmentStarted'
  sendAssessmentCompleted:
    action: send
    channel:
      $ref: '#/channels/assessmentCompleted'
  sendProgramCompleted:
    action: send
    channel:
      $ref: '#/channels/programCompleted'
  sendSelfScoreCompleted:
    action: send
    channel:
      $ref: '#/channels/selfScoreCompleted'
  sendAppealApproved:
    action: send
    channel:
      $ref: '#/channels/appealApproved'
components:
  messages:
    scoreUpdated:
      name: score_updated
      title: Score updated
      summary: >-
        Sent when a user completes an assessment that generates a new proficiency score, covering both
        baseline assessments and skill boost sessions. Superseded by assessment_completed, which uses a
        flat payload; no retirement date is published for score_updated.
      contentType: application/json
      headers:
        type: object
        properties:
          X-Workera-Signature:
            type: string
            description: sha256=<HMAC-SHA256 hex digest of the raw body>
      payload:
        type: object
        properties:
          identifier:
            type: string
            description: Unique identifier for the capability score; use it to deduplicate.
          source:
            type: string
            enum: [baseline, skill_boost]
          user:
            type: object
            properties:
              identifier: { type: string }
              email: { type: string }
              first_name: { type: string }
              last_name: { type: string }
          employee:
            type: object
            properties:
              identifier: { type: string, description: Enterprise employee ID; required for delivery }
          assessment:
            type: object
            properties:
              domain:
                type: object
                properties:
                  identifier: { type: string }
                  name: { type: string }
              program_identifiers:
                type: array
                items: { type: string }
              completed_at: { type: string, format: date-time }
          results:
            type: object
            properties:
              domain_score:
                type: object
                properties:
                  identifier: { type: string }
                  score: { type: integer, description: 0-300 }
                  proficiency_level:
                    type: string
                    enum: [beginner, developing, accomplished, expert]
              skill_ratings:
                type: array
                items:
                  type: object
                  properties:
                    identifier: { type: string }
                    name: { type: string }
                    proficiency_level: { type: string }
                    is_verified: { type: boolean }
    assessmentStarted:
      name: assessment_started
      title: Assessment started
      summary: >-
        Sent once when a learner begins an assessment. Fires for a baseline assessment, a mini
        assessment (scoring-v2) and a full reassessment. Does NOT fire on resume of an in-progress
        assessment, or for non-enterprise learners.
      contentType: application/json
      payload:
        type: object
        properties:
          event_type: { type: string, const: assessment_started }
          assessment_identifier:
            type: string
            description: >-
              Assessment identifier. A different ID space from the `identifier` on
              assessment_completed (which is the domain score); the two do not correlate.
          source:
            type: string
            enum: [baseline_assessment, mini_assessment, full_reassessment]
          started_at: { type: string, format: date-time }
          domain:
            type: object
            properties:
              identifier: { type: string }
              name: { type: string }
              program_identifiers: { type: array, items: { type: string } }
          user:
            type: object
            properties:
              identifier: { type: string }
              email: { type: string }
              employee:
                type: object
                properties:
                  identifier: { type: string }
      x-extensibility: >-
        Workera states the field set is intentionally open, not frozen; additional fields may be added
        non-breakingly, so consumers must tolerate unknown fields.
    assessmentCompleted:
      name: assessment_completed
      title: Assessment completed
      summary: >-
        The v2 replacement for score_updated, using a flat payload with topic-level skill ratings and
        behaviors. Fires for baseline, mini and full reassessments regardless of initiative_type.
      contentType: application/json
      payload:
        type: object
        properties:
          event_type: { type: string, const: assessment_completed }
          identifier: { type: string, description: Unique domain-score identifier }
          source:
            type: string
            enum: [baseline_assessment, mini_assessment, full_reassessment]
          initiative_type:
            type: string
            nullable: true
            enum: [skills_evaluation, skills_growth, limited_disclosure, benchmark]
            description: >-
              Initiative type of the program the assessment ran under, or null for standalone
              assessments. skills_evaluation is the canonical high-stakes type; consumers decide which
              types they treat as high-stakes.
          completed_at: { type: string, format: date-time }
          score: { type: integer, description: 0-300 }
          proficiency_level:
            type: string
            enum: [beginner, developing, accomplished, expert]
          domain:
            type: object
            properties:
              identifier: { type: string }
              name: { type: string }
              program_identifiers: { type: array, items: { type: string } }
          skill_ratings:
            type: array
            items:
              type: object
              properties:
                identifier: { type: string }
                name: { type: string }
                rating: { type: integer, description: 1-4 }
                behaviors:
                  type: array
                  items:
                    type: object
                    properties:
                      identifier: { type: string }
                      name: { type: string }
          user:
            type: object
            properties:
              identifier: { type: string }
              email: { type: string }
              employee:
                type: object
                properties:
                  identifier: { type: string }
    programCompleted:
      name: program_completed
      title: Program completed
      summary: >-
        Sent once per learner per program when the learner's latest score satisfies the completion
        threshold (total_required) for the program's required, non-elective capabilities.
      contentType: application/json
      payload:
        type: object
        properties:
          event_type: { type: string, const: program_completed }
          user:
            type: object
            properties:
              identifier: { type: string }
              email: { type: string }
              employee:
                type: object
                properties:
                  identifier: { type: string }
          program:
            type: object
            properties:
              identifier: { type: string }
              name: { type: string }
              initiative_type:
                type: string
                enum: [skills_evaluation, skills_growth, limited_disclosure, benchmark]
                description: Always present.
          completed_at: { type: string, format: date-time }
    selfScoreCompleted:
      name: self_score_completed
      title: Self score completed
      summary: >-
        Sent when a learner submits a self-assessment score through the contextualized self-assessment
        flow. Distinct from the objective assessment events.
      contentType: application/json
      payload:
        type: object
        properties:
          event_type: { type: string, const: self_score_completed }
          identifier: { type: string }
          score: { type: integer, description: 1-300 }
          domain:
            type: object
            properties:
              identifier: { type: string }
              name: { type: string }
          user:
            type: object
            properties:
              identifier: { type: string }
              email: { type: string }
              employee:
                type: object
                properties:
                  identifier: { type: string }
          completed_at: { type: string, format: date-time }
    appealApproved:
      name: appeal_approved
      title: Appeal approved
      summary: >-
        Sent when a scoring appeal is approved and the learner's capability score has been updated as a
        result. Not sent when an appeal is rejected, because no score change occurs.
      contentType: application/json
      payload:
        type: object
        properties:
          event_type: { type: string, const: appeal_approved }
          appeal:
            type: object
            properties:
              identifier: { type: string }
              decision:
                type: string
                enum: [correct, partially_correct, mostly_incorrect]
              reasoning: { type: string }
              user_appeal_reason: { type: string }
              resolved_at: { type: string, format: date-time }
          assessment_identifier: { type: string }
          score_before_appeal: { type: integer, description: 0-300 }
          score_after_appeal:
            type: integer
            description: >-
              0-300. Represents the delta from this appeal, not necessarily the user's current best
              score.
          domain:
            type: object
            properties:
              identifier: { type: string }
              name: { type: string }
              program_identifiers: { type: array, items: { type: string } }
          user:
            type: object
            properties:
              identifier: { type: string }
              email: { type: string }
              employee:
                type: object
                properties:
                  identifier: { type: string }
x-delivery:
  transport: HTTPS POST
  signature_header: X-Workera-Signature
  signature_algorithm: HMAC-SHA256 over the raw request body
  signature_format: sha256=<hex>
  retries:
  - immediate
  - 1 minute
  - 5 minutes
  - 15 minutes
  - 1 hour
  max_attempts: 5
  on_exhaustion: delivery stops; a notification email is sent to the configured contact
  deduplication_key: identifier
  configuration: per company, through the Workera CSM (no self-serve webhook API)
  replay_or_backfill:
    supported: partial
    method: >-
      Missed events can be recovered by reading GET /api/v2/scores/{score_identifier}, which returns
      the same flat, topic-level shape as the assessment_completed payload. There is no webhook
      delivery-log or replay endpoint.

Work with this as data

Every AsyncAPI spec here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for asyncapi

4 MCP tools reach this
  • find_asyncapisBrowse and filter every AsyncAPI spec in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This AsyncAPI spec
curl "https://apis.io/api/v1/asyncapis/workera-events-asyncapi"
All asyncapi
curl "https://apis.io/api/v1/asyncapis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.