diff --git a/.changeset/two-worms-float.md b/.changeset/two-worms-float.md
new file mode 100644
index 000000000..0ef2731ed
--- /dev/null
+++ b/.changeset/two-worms-float.md
@@ -0,0 +1,5 @@
+---
+"@web5/credentials": patch
+---
+
+Replaced hardcoded `typ` value in JWT with an optional header override.
diff --git a/packages/credentials/src/jwt.ts b/packages/credentials/src/jwt.ts
index 125866196..37d9b6786 100644
--- a/packages/credentials/src/jwt.ts
+++ b/packages/credentials/src/jwt.ts
@@ -66,6 +66,12 @@ export type SignJwtOptions = {
   signerDid: BearerDid
   /** The payload to sign. */
   payload: JwtPayload
+
+  /** Overridable header parameters */
+  header?: {
+    /** Type Header Parameter */
+    typ: string
+  }
 }
 
 /**
@@ -108,9 +114,9 @@ export class Jwt {
     }
 
     const header: JwtHeaderParams = {
-      typ : 'JWT',
       alg : signer.algorithm,
       kid : vmId,
+      ...options.header,
     };
 
     const base64UrlEncodedHeader = Convert.object(header).toBase64Url();
@@ -210,10 +216,6 @@ export class Jwt {
       throw new Error('Verification failed: Malformed JWT. Invalid base64url encoding for JWT header');
     }
 
-    if (!jwtHeader.typ || jwtHeader.typ !== 'JWT') {
-      throw new Error('Verification failed: Expected JWT header to contain typ property set to JWT');
-    }
-
     if (!jwtHeader.alg || !jwtHeader.kid) { // ensure that JWT header has required properties
       throw new Error('Verification failed: Expected JWT header to contain alg and kid');
     }
diff --git a/packages/credentials/tests/jwt.spec.ts b/packages/credentials/tests/jwt.spec.ts
index 58f418eef..8e718a0e2 100644
--- a/packages/credentials/tests/jwt.spec.ts
+++ b/packages/credentials/tests/jwt.spec.ts
@@ -25,24 +25,6 @@ describe('Jwt', () => {
       ).to.throw('Invalid base64url encoding for JWT header');
     });
 
-    it('throws error if JWT header is missing typ property', async () => {
-      const header: JwtHeaderParams = { alg: 'ES256K', kid: 'whateva' };
-      const base64UrlEncodedHeader = Convert.object(header).toBase64Url();
-
-      expect(() =>
-        Jwt.parse({ jwt: `${base64UrlEncodedHeader}.efgh.hijk` })
-      ).to.throw('typ property set to JWT');
-    });
-
-    it('throws error if JWT header typ property is not set to JWT', async () => {
-      const header: JwtHeaderParams = { typ: 'hehe', alg: 'ES256K', kid: 'whateva' };
-      const base64UrlEncodedHeader = Convert.object(header).toBase64Url();
-
-      expect(() =>
-        Jwt.parse({ jwt: `${base64UrlEncodedHeader}.efgh.hijk` })
-      ).to.throw('typ property set to JWT');
-    });
-
     it('throws error if JWT header alg property is missing', async () => {
       // @ts-expect-error because alg is intentionally missing to trigger error.
       const header: JwtHeaderParams = { typ: 'JWT', kid: 'whateva' };
@@ -274,6 +256,20 @@ describe('Jwt', () => {
     });
   });
 
+  describe('sign()', () => {
+    it('allows typ to be set by caller', async () => {
+      const did = await DidJwk.create();
+      const signedJwt = await Jwt.sign({
+        signerDid : did,
+        payload   : {jti: 'hehe'},
+        header    : {typ: 'openid4vci-proof+jwt'}
+      });
+
+      const parsed = Jwt.parse({ jwt: signedJwt });
+      expect(parsed.decoded.header.typ).to.equal('openid4vci-proof+jwt');
+    });
+  });
+
   describe('Web5TestVectorsVcJwt', () => {
     it('decode', async () => {
       const vectors = JwtDecodeTestVector.vectors;