import {z} from 'zod' export type SourceType = 'Internal' | 'Credly' | 'Open_University' | 'Imported'; export type BodyBadgeAssertionPushExternalBadgeAssertion = {provider_id: number, badge_external_id: string, source: SourceType, external_id: string, external_url: string, recipient_email: string, recipient_firstname: string, recipient_lastname?: string | undefined, recipient_organisation?: string | undefined, issue_date?: string | undefined, end_date?: string | undefined, evidence_text?: string | undefined, evidence_url?: string | undefined}; export type CreateApiV1BadgeAssertionPushArgs = {'X-Access-Token'?: (string | null) | undefined, body: BodyBadgeAssertionPushExternalBadgeAssertion}; export type CreateApiV1BadgeAssertionPushOptions = {baseUrl: string, OAuth2PasswordBearer?: string | undefined, fetch?: typeof fetch | undefined}; export const sourceType = z.enum(["Internal", "Credly", "Open_University", "Imported"]); export const evidenceType = z.enum(["UrlEvidence", "PlainTextEvidence", "IdEvidence", "KeyValueGroupEvidence"]); export const badgeAssertionEvidenceValues = z.object({key: z.string().nullable().optional(), value: z.string().nullable().optional(), url: z.string().nullable().optional()}); export const badgeAssertionEvidence = z.object({name: z.string().nullable().optional(), description: z.string().nullable().optional(), type: evidenceType.nullable().optional(), narrative: z.string().nullable().optional(), genre: z.string().nullable().optional(), audience: z.string().nullable().optional(), value: z.string().nullable().optional(), external_id: z.string().nullable().optional(), id: z.number().int(), badge_assertion_id: z.number().int().optional(), values: z.array(badgeAssertionEvidenceValues).nullable()}); export const badgeAssertionStatus = z.enum(["Pending", "Claimed", "Expired", "Revoked", "Deleted", "Failed", "Complained"]); export const issuingMethod = z.enum(["Email", "Activity", "Autobadge", "Bulk", "API", "Pushed", "Migrated", "QR", "Library_Card", "Riddle", "Typeform", "Zoho_Forms", "Tally", "Imported", "Pathway"]); export const badgeGrade = z.enum(["Pass", "Merit", "Distinction", "Distinction*"]); export const userVisibility = z.enum(["Public", "Private"]); export const userDetailPublic = z.object({id: z.number().int().optional(), firstname: z.string().nullable(), lastname: z.string().nullable(), avatar_url: z.string().nullable().optional(), avatar_url_2x: z.string().nullable().optional(), avatar_url_original: z.string().nullable().optional(), interests: z.array(z.string()).nullable().optional(), noindex_enabled: z.boolean().nullable().optional(), visibility: userVisibility.optional(), time_created: z.string().optional(), time_updated: z.string().nullable().optional(), seo_keywords: z.array(z.string()).nullable().optional(), seo_title: z.string().nullable().optional(), seo_description: z.string().nullable().optional(), social_handle_linkedin: z.string().nullable().optional(), social_handle_twitter: z.string().nullable().optional(), social_handle_facebook: z.string().nullable().optional(), social_handle_instagram: z.string().nullable().optional()}); export const badgeIssuerType = z.enum(["Employer", "Learning_Provider", "Other"]); export const badgeIssuerStatus = z.enum(["Active", "Suspended", "Deleted"]); export const badgeIssuer = z.object({name: z.string().nullable().optional(), type: badgeIssuerType.nullable().optional(), description: z.string().nullable().optional(), address: z.string().nullable().optional(), source: sourceType.nullable().optional(), source_credly_id: z.number().int().nullable().optional(), external_id: z.string().nullable().optional(), external_url: z.string().nullable().optional(), email: z.string().nullable().optional(), image_url: z.string().nullable().optional(), banner_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), banner_url_2x: z.string().nullable().optional(), id: z.number().int().optional(), status: badgeIssuerStatus.optional(), created_by_id: z.number().int().nullable().optional(), updated_by_id: z.number().int().nullable().optional(), time_created: z.string().optional(), time_updated: z.string().nullable().optional()}); export const providerStatus = z.enum(["Active", "Suspended", "Deleted"]); export const providerType = z.enum(["Learning_Provider", "Training_Provider", "Awarding_Body", "Employer", "Local_Authority", "University", "College", "Charity", "Department", "Project", "Other"]); export const communityStatus = z.enum(["Active", "Suspended", "Deleted"]); export const communityType = z.enum(["City", "Region", "Local_Authority", "Membership_Organisation", "Awarding_Body", "Partnership", "Corporate", "Association", "University", "College", "Charity", "Other"]); export const communityPublic = z.object({id: z.number().int().optional(), status: communityStatus.optional(), type: communityType.nullable().optional(), name: z.string().nullable().optional(), short_name: z.string().max(12).nullable().optional(), description: z.string().nullable().optional(), external_url: z.string().nullable().optional(), address: z.string().nullable().optional(), latitude: z.number().nullable().optional(), longitude: z.number().nullable().optional(), is_verified: z.boolean().nullable().optional(), verification_text: z.string().nullable().optional(), verification_url: z.string().nullable().optional(), is_demo: z.boolean().nullable().optional(), colour: z.string().nullable().optional(), spydus_library_url: z.string().nullable().optional(), referral_code: z.string().nullable().optional(), image_url: z.string().nullable().optional(), banner_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), banner_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), banner_url_original: z.string().nullable().optional(), linkedin_organisation_id: z.number().int().nullable().optional(), social_handle_linkedin: z.string().nullable().optional(), social_handle_twitter: z.string().nullable().optional(), social_handle_facebook: z.string().nullable().optional(), social_handle_instagram: z.string().nullable().optional(), seo_title: z.string().nullable().optional(), seo_description: z.string().nullable().optional(), seo_keywords: z.array(z.string()).nullable().optional(), url: z.string().nullable().optional()}); export const providerPublic = z.object({id: z.number().int().optional(), status: providerStatus.optional(), type: providerType.nullable().optional(), name: z.string().nullable().optional(), short_name: z.string().max(12).nullable().optional(), description: z.string().nullable().optional(), email: z.string().nullable().optional(), external_url: z.string().nullable().optional(), is_verified: z.boolean().nullable().optional(), verification_text: z.string().nullable().optional(), verification_url: z.string().nullable().optional(), is_demo: z.boolean().nullable().optional(), open_access: z.boolean().optional(), enable_analytics: z.boolean().nullable().optional(), community_id: z.number().int().nullable().optional(), community: communityPublic.nullable(), latitude: z.number().nullable().optional(), longitude: z.number().nullable().optional(), image_url: z.string().nullable().optional(), banner_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), banner_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), banner_url_original: z.string().nullable().optional(), brand_colours: z.array(z.string()).nullable().optional(), qa_community_id: z.number().int().nullable().optional(), linkedin_organisation_id: z.number().int().nullable().optional(), social_handle_linkedin: z.string().nullable().optional(), social_handle_twitter: z.string().nullable().optional(), social_handle_facebook: z.string().nullable().optional(), social_handle_instagram: z.string().nullable().optional(), seo_title: z.string().nullable().optional(), seo_description: z.string().nullable().optional(), seo_keywords: z.array(z.string()).nullable().optional(), url: z.string().nullable().optional()}); export const designStandard = z.enum(["Generic", "Navigatr"]); export const badgeType = z.enum(["Experience", "Learning", "Validation", "Certification", "Attendance", "Work_Experience", "Volunteering", "Job", "Apprenticeship", "Course", "Internship", "Workshop", "Campaigning", "Activism", "Other", "Informal_Learning", "Training", "Certified", "Qualification", "Membership"]); export const language = z.enum(["Arabic_Modern_Standard", "Bengali", "Bulgarian", "Chinese_Cantonese", "Chinese_Mandarin", "Chinese_Simplified", "Chinese_Traditional", "Croatian", "Czech", "Dutch", "English", "French", "German", "Greek", "Hungarian", "Irish_Gaeilge", "Italian", "Kurdish_Kurmanji", "Kurdish_Sorani", "Latvian", "Lithuanian", "Pashto", "Persian", "Polish", "Portuguese", "Punjabi", "Romanian", "Scottish_Gaelic_Gaidhlig", "Slovak", "Somali", "Spanish", "Tigrinya", "Turkish", "Ukrainian", "Urdu", "Welsh_Cymraeg"]); export const recipientType = z.enum(["User", "Organisation"]); export const badgeCost = z.enum(["Free", "Paid", "Other"]); export const badgeLevel = z.enum(["Foundational", "Intermediate", "Advanced", "Other", "Explore", "Deepen", "Apply", "Teach", "Lead"]); export const timeToEarn = z.enum(["Hours", "Days", "Weeks", "Months", "Years", "Other"]); export const participationType = z.enum(["Online", "Hybrid", "In_Person"]); export const qualificationType = z.enum(["Award", "Certificate", "Diploma"]); export const qualificationFramework = z.enum(["RQF", "CQFW", "SCQF", "EQF", "QFEmirates"]); export const badgeStatus = z.enum(["Initialising", "Draft", "Awaiting_Approval", "Published", "Deleted", "Expired"]); export const badgeIssuerPublic = z.object({id: z.number().int().optional(), name: z.string().nullable().optional(), type: badgeIssuerType.nullable().optional(), status: badgeIssuerStatus.optional(), external_url: z.string().nullable().optional(), email: z.string().nullable().optional(), image_url: z.string().nullable().optional(), banner_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), banner_url_2x: z.string().nullable().optional()}); export const address = z.object({full_address: z.string().nullable().optional(), name: z.string().nullable().optional(), number: z.string().nullable().optional(), street: z.string().nullable().optional(), postcode: z.string().nullable().optional(), locality: z.string().nullable().optional(), city: z.string().nullable().optional(), district: z.string().nullable().optional(), region: z.string().nullable().optional(), country: z.string().nullable().optional()}); export const badgeCriteriaType = z.enum(["Application", "Assessment", "Award", "Badge", "Course", "Credential", "Education_Experience", "Leadership", "Member", "Participant", "Pathway", "Payment", "Portfolio", "Presenter", "Project", "Professional_Experience", "Schedule_Registration", "Volunteer", "Other"]); export const badgeCriteria = z.object({external_id: z.string().nullable().optional(), description: z.string().nullable().optional(), type: badgeCriteriaType.nullable().optional(), external_url: z.string().nullable().optional(), badge_id: z.number().int().nullable().optional(), id: z.number().int().nullable().optional()}); export const badgeTag = z.object({name: z.string().nullable().optional(), external_id: z.string().nullable().optional(), type: z.string().nullable().optional(), source: z.string().nullable().optional()}); export const badgeAlignment = z.object({external_id: z.string().nullable().optional(), name: z.string().nullable().optional(), description: z.string().nullable().optional(), url: z.string().nullable().optional(), framework: z.string().nullable().optional(), code: z.string().nullable().optional(), id: z.number().int().nullable().optional(), badge_id: z.number().int().nullable().optional()}); export const badgeEndorsement = z.object({external_id: z.string().nullable().optional(), name: z.string().nullable().optional(), description: z.string().nullable().optional(), url: z.string().nullable().optional(), image_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), id: z.number().int().nullable().optional(), badge_id: z.number().int().nullable().optional()}); export const collectionLight = z.object({id: z.number().int(), name: z.string().nullable().optional(), badge_issuer_id: z.number().int().nullable().optional()}); export const communityLight = z.object({id: z.number().int(), status: communityStatus.optional(), type: communityType.nullable().optional(), name: z.string().nullable().optional(), short_name: z.string().max(12).nullable().optional(), is_verified: z.boolean().nullable().optional(), image_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), linkedin_organisation_id: z.number().int().nullable().optional(), social_handle_linkedin: z.string().nullable().optional(), social_handle_twitter: z.string().nullable().optional(), social_handle_facebook: z.string().nullable().optional(), social_handle_instagram: z.string().nullable().optional(), url: z.string().nullable().optional()}); export const providerLight = z.object({id: z.number().int(), status: providerStatus.optional(), type: providerType.nullable().optional(), name: z.string().nullable().optional(), short_name: z.string().max(12).nullable().optional(), external_url: z.string().nullable().optional(), is_verified: z.boolean().nullable().optional(), verification_text: z.string().nullable().optional(), verification_url: z.string().nullable().optional(), is_demo: z.boolean().nullable().optional(), open_access: z.boolean().optional(), community_id: z.number().int().nullable().optional(), community: communityLight.nullable(), image_url: z.string().nullable().optional(), banner_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), banner_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), banner_url_original: z.string().nullable().optional(), qa_community_id: z.number().int().nullable().optional(), linkedin_organisation_id: z.number().int().nullable().optional(), social_handle_linkedin: z.string().nullable().optional(), social_handle_twitter: z.string().nullable().optional(), social_handle_facebook: z.string().nullable().optional(), social_handle_instagram: z.string().nullable().optional(), url: z.string().nullable().optional()}); export const sectorSubjectAreaEmbedded = z.object({id: z.number().int(), code: z.string(), name: z.string(), tier_1_name: z.string().nullable().optional(), image_label: z.string().nullable().optional()}); export const badge = z.object({name: z.string().nullable().optional(), design_standard: designStandard.nullable().optional(), type: badgeType.nullable().optional(), language: language.nullable().optional(), provider_ids: z.array(z.number().int()).nullable().optional(), community_ids: z.array(z.number().int()).nullable().optional(), recipient_type: recipientType.nullable().optional(), description: z.string().nullable().optional(), issuer_id: z.number().int().nullable().optional(), image_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), design_parameters: z.unknown(), source: sourceType.nullable().optional(), earn_url: z.string().nullable().optional(), external_url: z.string().nullable().optional(), information_url: z.string().nullable().optional(), embed: z.string().nullable().optional(), external_id: z.string().nullable().optional(), latitude: z.number().nullable().optional(), longitude: z.number().nullable().optional(), city: z.string().nullable().optional(), country: z.string().nullable().optional(), config: z.unknown(), address: z.string().nullable().optional(), available_to_all: z.boolean().nullable().optional(), availability: z.string().nullable().optional(), end_date: z.string().nullable().optional(), cost: badgeCost.nullable().optional(), level: badgeLevel.nullable().optional(), time_to_earn: timeToEarn.nullable().optional(), participation_type: participationType.nullable().optional(), qa_locked: z.boolean().nullable().optional(), job_titles: z.array(z.string()).nullable().optional(), specialized_occupations: z.array(z.string()).nullable().optional(), title_names: z.array(z.string()).nullable().optional(), is_demo: z.boolean().nullable().optional(), certificates_enabled: z.boolean().optional(), industries: z.array(z.string()).nullable().optional(), occupation_groups: z.array(z.string()).nullable().optional(), skill_category_names: z.array(z.string()).nullable().optional(), edu_levels: z.array(z.string()).nullable().optional(), qualification_code: z.string().max(100).nullable().optional(), credits_available: z.number().gte(0).nullable().optional(), credits_unit: z.string().max(20).nullable().optional(), qualification_type: qualificationType.nullable().optional(), qualification_framework: qualificationFramework.nullable().optional(), qualification_level: z.string().max(50).nullable().optional(), grade: badgeGrade.nullable().optional(), field_of_study_id: z.number().int().nullable().optional(), id: z.number().int().optional(), status: badgeStatus.optional(), created_by: userDetailPublic.nullable().optional(), submitted_by: userDetailPublic.nullable().optional(), published_by: userDetailPublic.nullable().optional(), updated_by: userDetailPublic.nullable().optional(), issuer: badgeIssuerPublic.nullable().optional(), ranking: z.number().int().nullable().optional(), time_created: z.string().optional(), time_updated: z.string().nullable().optional(), time_submitted: z.string().nullable().optional(), time_published: z.string().nullable().optional(), quality_assured_at: z.string().nullable().optional(), time_issued: z.string().nullable().optional(), postal_address: address.nullable().optional(), created_by_id: z.number().int().nullable().optional(), submitted_by_id: z.number().int().nullable().optional(), published_by_id: z.number().int().nullable().optional(), updated_by_id: z.number().int().nullable().optional(), criteria: z.array(badgeCriteria).nullable().optional(), tags: z.array(badgeTag).nullable().optional(), alignments: z.array(badgeAlignment).nullable().optional(), endorsements: z.array(badgeEndorsement).nullable().optional(), collections: z.array(collectionLight).nullable().optional(), providers: z.array(providerLight).nullable().optional(), interacted_with: z.boolean().nullable().optional(), featured: z.boolean().optional(), ai_generated: z.boolean().optional(), url: z.string().optional(), seo_keywords: z.array(z.string()).nullable().optional(), seo_title: z.string().nullable().optional(), seo_description: z.string().nullable().optional(), field_of_study: sectorSubjectAreaEmbedded.nullable().optional(), display_level: z.string().nullable()}); export const changeRequestField = z.enum(["recipient_firstname", "recipient_lastname", "recipient_organisation", "extend_expiry"]); export const changeRequestStatus = z.enum(["requested", "approved", "rejected"]); export const badgeAssertionChangeRequestItem = z.object({field: changeRequestField, value: z.string().nullable().optional(), status: changeRequestStatus.optional(), reason: z.string().nullable().optional()}); export const badgeAssertionChangeRequest = z.object({id: z.string(), changes: z.array(badgeAssertionChangeRequestItem), note: z.string().nullable().optional(), time_created: z.string(), last_reminded_at: z.string().nullable().optional(), reminder_count: z.number().int().nullable().optional()}); export const badgeAssertion = z.object({recipient_email: z.string().nullable().optional(), recipient_firstname: z.string().nullable().optional(), recipient_lastname: z.string().nullable().optional(), recipient_organisation: z.string().nullable().optional(), recipient_id: z.number().int().nullable().optional(), end_date: z.string().nullable().optional(), image_url: z.string().nullable().optional(), image_url_2x: z.string().nullable().optional(), image_url_original: z.string().nullable().optional(), narrative: z.string().nullable().optional(), source: sourceType.nullable().optional(), external_id: z.string().nullable().optional(), external_url: z.string().nullable().optional(), badge_issuer_id: z.number().int().nullable().optional(), provider_id: z.number().int().nullable().optional(), evidence: z.array(badgeAssertionEvidence).nullable(), issue_date: z.string().nullable().optional(), time_verified: z.string().nullable().optional(), id: z.number().int().optional(), status: badgeAssertionStatus.optional(), issuing_method: issuingMethod.optional(), seo_keywords: z.array(z.string()).nullable().optional(), seo_title: z.string().nullable().optional(), seo_description: z.string().nullable().optional(), grade: badgeGrade.nullable().optional(), credits_earned: z.number().nullable().optional(), recipient: userDetailPublic.nullable().optional(), issuer: badgeIssuer.nullable().optional(), provider: providerPublic.nullable().optional(), badge: badge.nullable().optional(), time_created: z.string().optional(), time_updated: z.string().nullable().optional(), created_by_id: z.number().int().nullable().optional(), updated_by_id: z.number().int().nullable().optional(), reject_code: z.string().nullable(), revocation_reason: z.string().nullable().optional(), url: z.string().nullable().optional(), badge_id: z.number().int().nullable().optional(), reminder_emails_sent: z.number().int().nullable().optional(), time_claimed: z.string().nullable().optional(), change_request: z.array(badgeAssertionChangeRequest).nullable().optional(), restorable_until: z.string().nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Push External Badge Assertion * * POST /v1/badge_assertion/push */ export const createApiV1BadgeAssertionPush = async (args: CreateApiV1BadgeAssertionPushArgs, options: CreateApiV1BadgeAssertionPushOptions) => { const {baseUrl, fetch: fetchFn = fetch, OAuth2PasswordBearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (args['X-Access-Token'] != null) headers.set("X-Access-Token", String(args['X-Access-Token'])) if (OAuth2PasswordBearer !== undefined) headers.set('authorization', `Bearer ${OAuth2PasswordBearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/v1/badge_assertion/push${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(badgeAssertion, await res.json()) };