# Certificate Issuance Module

:::note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](/sdk-reference/web-sdk-reference).  Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade. <br /><br />Full rollout to all clients still TBD.
:::

The Certificate Issuance module issues a digital certificate at the end of a verification flow. The user sets a password that protects the certificate, the backend issues it, and the SDK offers the resulting file for download.

> Follows the [backend-process pattern](/sdk-reference/web-sdk-2-module-patterns/#3-backend-process-modules) with a short form step for the password. See that page for the shared manager lifecycle; the rest of this page covers what's specific to certificate issuance.

## Tag

`<incode-certificate-issuance>` is a standard Web Component. Importing the UI subpath registers the custom element; importing the CSS applies the module's styles.

```ts
import '@incodetech/web/certificate-issuance';
import '@incodetech/web/certificate-issuance/styles.css';
```

## Properties

Set these as JavaScript properties on the element (not as HTML attributes):

| Property   | Type                        | Required | Description                      |
| ---------- | --------------------------- | -------- | -------------------------------- |
| `config`   | `CertificateIssuanceConfig` | ✅        | Configuration options            |
| `onFinish` | `() => void`                | ❌        | Called when the module completes |
| `onError`  | `(error: string) => void`   | ❌        | Called when an error occurs      |

## Usage

### Vanilla HTML / TypeScript

```html
<incode-certificate-issuance></incode-certificate-issuance>

<script type="module">
  import { setup } from '@incodetech/core';
  import '@incodetech/web/certificate-issuance';
  import '@incodetech/web/certificate-issuance/styles.css';

  await setup({
    apiURL: 'https://demo-api.incodesmile.com',
    token: 'your-session-token',
  });

  const el = document.querySelector('incode-certificate-issuance');
  el.config = {
    region: 'MX',
    type: 'LONG_TERM',
  };
  el.onFinish = () => console.log('Certificate issued!');
  el.onError = (err) => console.error('Certificate error:', err);
</script>
```

### React

> **React 18 or earlier:** add the one-time JSX augmentation from [Framework Integration → TypeScript: JSX support for `incode-*` tags](/sdk-reference/web-sdk-2-framework-integration/#typescript-jsx-support-for-incode--tags). React 19+ doesn't need it.

```typescript TSX
import { useEffect, useRef } from 'react';
import { setup } from '@incodetech/core';
import type { CertificateIssuanceConfig } from '@incodetech/core/certificate-issuance';
import '@incodetech/web/certificate-issuance';
import '@incodetech/web/certificate-issuance/styles.css';

type CertificateElement = HTMLElement & {
  config: CertificateIssuanceConfig;
  onFinish: () => void;
  onError: (error: string) => void;
};

await setup({
  apiURL: 'https://demo-api.incodesmile.com',
  token: 'your-session-token',
});

export function CertificateIssuance() {
  const ref = useRef<CertificateElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.config = { region: 'MX', type: 'LONG_TERM' };
    el.onFinish = () => console.log('Certificate issued!');
    el.onError = (err) => console.error('Certificate error:', err);
  }, []);

  return <incode-certificate-issuance ref={ref} />;
}
```

For Angular (`CUSTOM_ELEMENTS_SCHEMA`) and Vue (`compilerOptions.isCustomElement`) setup, see [Framework Integration](/sdk-reference/web-sdk-2-framework-integration/).

***

## Headless Mode

For complete UI control, use `createCertificateIssuanceManager` from `@incodetech/core/certificate-issuance`.

### Quick Start

```typescript TSX
import { setup } from '@incodetech/core';
import { createCertificateIssuanceManager } from '@incodetech/core/certificate-issuance';

await setup({
  apiURL: 'https://demo-api.incodesmile.com',
  token: 'your-session-token',
});

const manager = createCertificateIssuanceManager({
  config: { region: 'MX', type: 'LONG_TERM' },
});

manager.subscribe((state) => {
  console.log('Status:', state.status);

  if (state.status === 'success') {
    // Offer state.blob for download, then report the outcome.
    triggerDownload(state.blob);
    manager.markDownloaded();
    manager.finish();
  }

  if (state.status === 'finished') {
    manager.stop();
  }
});

// Start the flow
manager.load();

// When state is 'password', collect input and submit once canSubmit is true.
manager.setPassword('Str0ngPass');
manager.submitPassword();
```

### State Machine Flow

```mermaid
flowchart LR
    idle -->|load| password
    password -->|submitPassword| processing
    processing -->|issued| success
    processing -->|failure| error
    success -->|markDownloaded| downloaded
    success -->|finish| finished
    success -.->|reportDownloadError| error
    downloaded -->|finish| finished
    error -.->|after 3s| finished
```

### States Reference

| Status       | Description                                                              | Key Properties                                 |
| ------------ | ------------------------------------------------------------------------ | ---------------------------------------------- |
| `idle`       | Initial state, waiting for `load()`                                      | –                                              |
| `password`   | Waiting for the user to set a valid certificate password                 | `password`, `passwordValidations`, `canSubmit` |
| `processing` | Issuing the certificate on the backend                                   | –                                              |
| `success`    | Certificate issued and ready to download                                 | `blob`                                         |
| `downloaded` | The certificate file has been downloaded                                 | –                                              |
| `error`      | Issuance or download failed; auto-advances to `finished` after 3 seconds | –                                              |
| `finished`   | Terminal state                                                           | –                                              |

### State Properties

**When&#x20;**`status === 'password'`**:**

| Property              | Type                  | Description                                                                           |
| --------------------- | --------------------- | ------------------------------------------------------------------------------------- |
| `password`            | `string`              | The password entered so far (controlled-input value)                                  |
| `passwordValidations` | `PasswordValidations` | Per-requirement pass/fail flags (see [Password requirements](#password-requirements)) |
| `canSubmit`           | `boolean`             | `true` when every password requirement passes                                         |

**When&#x20;**`status === 'success'`**:**

| Property | Type   | Description                                              |
| -------- | ------ | -------------------------------------------------------- |
| `blob`   | `Blob` | The issued certificate file, ready to offer for download |

### API Methods

| Method                  | Description                                            | When to Use                        |
| ----------------------- | ------------------------------------------------------ | ---------------------------------- |
| `load()`                | Starts the flow (moves `idle` → `password`)            | Always call first                  |
| `setPassword(password)` | Sets the password and recomputes `passwordValidations` | When `password` (controlled input) |
| `submitPassword()`      | Submits the password to issue the certificate          | When `canSubmit` is `true`         |
| `markDownloaded()`      | Reports that the certificate file was downloaded       | After downloading `blob`           |
| `reportDownloadError()` | Reports a failed download                              | When a download attempt fails      |
| `finish()`              | Completes the module                                   | From `success` or `downloaded`     |
| `getState()`            | Returns the current state synchronously                | Anytime                            |
| `subscribe(callback)`   | Subscribes to state changes                            | Returns an unsubscribe function    |
| `stop()`                | Releases resources                                     | When unmounting                    |

## Password requirements

The password the user sets must satisfy every requirement below. `passwordValidations` reports each one so you can render a live checklist, and `canSubmit` is `true` only when all pass.

| Requirement | Rule                          |
| ----------- | ----------------------------- |
| `length`    | At least 8 characters         |
| `uppercase` | At least one uppercase letter |
| `lowercase` | At least one lowercase letter |
| `number`    | At least one digit            |

## Configuration Options

`CertificateIssuanceConfig` shape:

| Option   | Type                                        | Required | Description                                                    |
| -------- | ------------------------------------------- | -------- | -------------------------------------------------------------- |
| `region` | `string`                                    | ✅        | Issuance region, supplied by the dashboard flow configuration. |
| `type`   | `'ONE_TIME' \| 'SHORT_TERM' \| 'LONG_TERM'` | ✅        | Certificate validity period.                                   |

Both values come from the dashboard flow configuration. When the module runs inside `<incode-flow>` or `createOrchestratedFlowManager`, the orchestrator passes them automatically.

***

## See Also

- [Headless Mode](/sdk-reference/web-sdk-2-headless-mode/): Headless API patterns
- [Individual Modules](/sdk-reference/web-sdk-2-individual-modules/): Overview of all modules
- [Module Patterns → backend-process](/sdk-reference/web-sdk-2-module-patterns/#3-backend-process-modules)

<br />
