USPTO Filing Bot

Callback Documentation v1

How Callbacks Work

The USPTO Filing Bot sends webhook notifications (HTTP POST) to your registered callback URLs whenever an applicant's status changes or a filing progresses. This allows your system to react in real-time without polling.

Key Concepts

💡 Callback URLs are per-company
When you register a company, you configure one or more webhook URLs with HTTP method, max retries, retry backoff, and timeout. All callback events for applicants belonging to that company are delivered to those URLs.

Delivery Flow

Bot Status Change / API Action │ ▼ ┌───────────────────────────────────────┐ │ 1. Enqueue │ │ → Build JSON payload │ │ → Insert CallbackDelivery row │ │ (one row per active URL) │ │ → Status: PENDING │ └───────────────────────────────────────┘ │ (background dispatcher — every 10s) ▼ ┌───────────────────────────────────────┐ │ 2. Dispatch │ │ → HTTP POST to your URL │ │ → Timeout: per-URL config │ │ │ │ ✅ 2xx response → DELIVERED (done) │ │ ❌ non-2xx/error: │ │ → attempts < MaxRetries │ │ → FAILED_WILL_RETRY │ │ → NextRetryAt = now + backoff │ │ → attempts >= MaxRetries │ │ → GIVEN_UP (terminal) │ └───────────────────────────────────────┘

Lifecycle & Callback Flow

Every callback maps to a specific moment in the applicant's lifecycle. This diagram shows when each event fires:

API: POST /create-applicant │ ├─ Email provisioned ✅ ──► EMAIL_PROVISIONED ├─ Email failed ❌ ────────► ACCOUNT_FAILED │ ▼ PHASE 1 — Account Creation (Bot) │ ├─ PENDING → EMAIL_CREATED ──────────► APPLICANT_STATUS_CHANGED ├─ EMAIL_CREATED → FORM_FILLING ─────► APPLICANT_STATUS_CHANGED ├─ FORM_FILLING → FORM_SUBMITTED ────► APPLICANT_STATUS_CHANGED ├─ FORM_SUBMITTED → EMAIL_VERIF_PEND ► APPLICANT_STATUS_CHANGED ├─ EMAIL_VERIF_PEND → EMAIL_VERIFIED ► APPLICANT_STATUS_CHANGED ├─ EMAIL_VERIFIED → PASSWORD_SETUP ──► APPLICANT_STATUS_CHANGED ├─ PASSWORD_SETUP → SECURITY_SETUP ──► APPLICANT_STATUS_CHANGED ├─ SECURITY_SETUP → ACCOUNT_CREATED ─► APPLICANT_STATUS_CHANGED + 🎬 signup video │ ├─ Any → ACCOUNT_FAILED ─────────────► APPLICANT_STATUS_CHANGED │ + ACCOUNT_FAILED + 🎬 signup video │ ▼ PHASE 2 — ID.me Verification (Bot) │ ├─ ACCOUNT_CREATED → IDME_VERIFIED ──► APPLICANT_STATUS_CHANGED │ + IDME_VERIFIED + 🎬 idme video │ ├─ 48h exceeded → IDME_VERIF_FAILED ─► APPLICANT_STATUS_CHANGED │ + IDME_VERIFICATION_FAILED + 🎬 idme video │ ▼ PHASE 3 — Trademark Filing (Bot) │ ├─ PENDING → UNDER_PROCESS ──────────► FILING_STATUS_CHANGED ├─ UNDER_PROCESS → DONE ─────────────► FILING_STATUS_CHANGED │ + SUBMISSION_COMPLETED + 🎬 filing video │ ├─ UNDER_PROCESS → ERROR ────────────► FILING_STATUS_CHANGED │ + SUBMISSION_FAILED + 🎬 filing video
⚠️ Multiple events per transition
Some transitions fire two callbacks simultaneously. For example, ACCOUNT_CREATED fires both APPLICANT_STATUS_CHANGED and the specific milestone event. Your system should handle both — they share the same correlationId only when emitted from the same action, but are separate delivery rows.

Payload Structure

All callbacks share a stable payload envelope. Fields are only added, never removed (backward-compatible).

Envelope

{
  "event":         "APPLICANT_STATUS_CHANGED",
  "eventId":       2,
  "occurredAt":    "2026-06-04T15:30:00.000Z",
  "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "applicant":     { ... },
  "application":   { ... },       // only for filing-scoped events
  "transition":    { ... },       // only when a status transition occurred
  "video":         { ... },       // only when a bot recording exists
  "error":         { ... }        // only on failure events
}

Envelope Fields

FieldTypeAlways PresentDescription
eventstringYesEvent code string (e.g. "APPLICANT_STATUS_CHANGED").
eventIdintegerYesNumeric event ID from CallbackEvent table.
occurredAtISO 8601YesUTC timestamp when the event was generated.
correlationIdUUIDYesUnique per-event. Use for idempotency / dedup.
applicantobjectYesApplicant snapshot. See below.
applicationobjectNoPresent only for filing-scoped events (3, 5, 6).
transitionobjectNoPresent when a status transition triggered the event.
videoobjectNoPresent when a bot video recording exists for this phase.
errorobjectNoPresent on failure events (ACCOUNT_FAILED, SUBMISSION_FAILED, etc.).

applicant Object

Included in every callback. Represents the applicant's state at the moment the event fired.

FieldTypeDescription
idintegerApplicant's database ID.
customerIdintegerYour external customer reference ID.
companyIdintegerTenant company ID.
firstNamestringApplicant's first name.
lastNamestringApplicant's last name.
emailAddressstringYour contact email (NOT the USPTO account email).
usptoAccountEmailstring | nullAuto-generated USPTO mailbox. null before provisioning.
usptoAccountPasswordstring | nullUSPTO account password. Generated at applicant creation.
mfaSecretstring | nullTOTP MFA secret for USPTO login. null until Phase 1 MFA enrollment completes.
applicantLifeCycleStatusIdintegerCurrent lifecycle status ID.
applicantLifeCycleStatusstringHuman-readable lifecycle status title.
usptoAccountEmailStatusIdintegerEmail provisioning status (1=Pending, 2=Created, 3=Verified, 4=Failed).

Example applicant Object

{
  "id": 42,
  "customerId": 1001,
  "companyId": 5,
  "firstName": "Mike",
  "lastName": "Jacob",
  "emailAddress": "[email protected]",
  "usptoAccountEmail": "[email protected]",
  "usptoAccountPassword": "xY9!kP2m@LqR7n",
  "mfaSecret": "JBSWY3DPEHPK3PXP",
  "applicantLifeCycleStatusId": 9,
  "applicantLifeCycleStatus": "Account Created",
  "usptoAccountEmailStatusId": 2
}
⚠️ Sensitive Fields
usptoAccountPassword and mfaSecret are included in every callback payload. Ensure your webhook endpoint uses HTTPS and stores these securely. mfaSecret will be null in callbacks that fire before MFA enrollment (e.g. EMAIL_PROVISIONED, FORM_FILLING).

application Object

Only present for filing-scoped events: FILING_STATUS_CHANGED, SUBMISSION_COMPLETED, SUBMISSION_FAILED.

FieldTypeDescription
idintegerApplication's database ID.
applicantIdintegerParent applicant ID.
filingStatusIdintegerCurrent filing status ID.
filingStatusstringHuman-readable filing status title.

transition Object

Present when an event represents a status change (applicant lifecycle or filing status).

FieldTypeDescription
frominteger | nullPrevious status ID. null for the first transition.
tointegerNew status ID.
fromTitlestring | nullHuman-readable previous status.
toTitlestringHuman-readable new status.

video Object

Present when a bot video recording is associated with this event's phase.

FieldTypeDescription
typestringRecording type: "Signup", "USPTO Verification", or "Filing".
typeIdintegerVideo type ID (1=Signup, 2=Verification, 3=Filing).
pathstringServer-side file path of the recording.
durationSecondsnumberRecording duration in seconds.
recordedAtISO 8601When the recording was created.

error Object

Present on failure events.

FieldTypeDescription
messagestringHuman-readable error description.

EMAIL_PROVISIONED

EVENT ID: 10   V1 API

Fired immediately after the third-party email provider successfully creates the USPTO mailbox. This is the first callback you receive for a new applicant.

When it fires

Key payload fields at this point

Example payload

{
  "event": "EMAIL_PROVISIONED",
  "eventId": 10,
  "occurredAt": "2026-06-04T15:00:01.000Z",
  "correlationId": "c9d1e2f3-a4b5-6789-cdef-012345678901",
  "applicant": {
    "id": 42,
    "customerId": 1001,
    "companyId": 5,
    "firstName": "Mike",
    "lastName": "Jacob",
    "emailAddress": "[email protected]",
    "usptoAccountEmail": "[email protected]",
    "usptoAccountPassword": "xY9!kP2m@LqR7n",
    "mfaSecret": null,
    "applicantLifeCycleStatusId": 2,
    "applicantLifeCycleStatus": "Email Created",
    "usptoAccountEmailStatusId": 2
  }
}
💡 No video attachment
This event fires from the API layer — the bot has not started yet, so no video recording is attached.

APPLICANT_STATUS_CHANGED

EVENT ID: 2   PHASE 1 PHASE 2

The universal lifecycle event. Fired on every applicant lifecycle status transition performed by the bot. This is the most frequent callback — you can build a complete audit trail from this event alone.

When it fires

Every call to the bot's internal setLifecycleStatus() function fires this event. That includes all of these transitions:

FromToPhaseVideo Attached
PENDING (1)EMAIL_CREATED (2)APINo
EMAIL_CREATED (2)FORM_FILLING (3)Phase 1No
FORM_FILLING (3)FORM_SUBMITTED (4)Phase 1No
FORM_SUBMITTED (4)EMAIL_VERIFICATION_PENDING (5)Phase 1No
EMAIL_VERIFICATION_PENDING (5)EMAIL_VERIFIED (6)Phase 1No
EMAIL_VERIFIED (6)PASSWORD_SETUP (7)Phase 1No
PASSWORD_SETUP (7)SECURITY_METHOD_SETUP (8)Phase 1No
SECURITY_METHOD_SETUP (8)ACCOUNT_CREATED (9)Phase 1🎬 Signup
AnyACCOUNT_FAILED (10)Phase 1🎬 Signup
ACCOUNT_CREATED (9)IDME_VERIFIED (11)Phase 2No
ACCOUNT_CREATED (9)IDME_VERIF_FAILED (12)Phase 2No

Example payload

{
  "event": "APPLICANT_STATUS_CHANGED",
  "eventId": 2,
  "occurredAt": "2026-06-04T15:05:30.000Z",
  "correlationId": "d1e2f3a4-b5c6-7890-abcd-ef0123456789",
  "applicant": {
    "id": 42,
    "customerId": 1001,
    "companyId": 5,
    "firstName": "Mike",
    "lastName": "Jacob",
    "emailAddress": "[email protected]",
    "usptoAccountEmail": "[email protected]",
    "usptoAccountPassword": "xY9!kP2m@LqR7n",
    "mfaSecret": null,
    "applicantLifeCycleStatusId": 4,
    "applicantLifeCycleStatus": "Form Submitted",
    "usptoAccountEmailStatusId": 2
  },
  "transition": {
    "from": 3,
    "to": 4,
    "fromTitle": "Form Filling",
    "toTitle": "Form Submitted"
  }
}

ACCOUNT_FAILED

EVENT ID: 7   V1 API PHASE 1

Fired when account creation fails. This is a terminal failure — the applicant cannot proceed further without manual intervention.

When it fires

⛔ Two sources, same event
ACCOUNT_FAILED fires from both the API layer (email provisioning) and the bot processor (automation failure). Check applicant.applicantLifeCycleStatusId to distinguish: if it's 1 (PENDING), the email never provisioned. If it's 10 (ACCOUNT_FAILED), bot automation failed.

Example payload (email provisioning failure)

{
  "event": "ACCOUNT_FAILED",
  "eventId": 7,
  "occurredAt": "2026-06-04T15:00:02.000Z",
  "correlationId": "e2f3a4b5-c6d7-8901-bcde-f01234567890",
  "applicant": {
    "id": 43,
    "customerId": 1002,
    "companyId": 5,
    "firstName": "Jane",
    "lastName": "Smith",
    "emailAddress": "[email protected]",
    "usptoAccountEmail": null,
    "usptoAccountPassword": "aB3!mN8x@QwR5z",
    "mfaSecret": null,
    "applicantLifeCycleStatusId": 1,
    "applicantLifeCycleStatus": "Pending",
    "usptoAccountEmailStatusId": 4
  },
  "error": {
    "message": "Email provisioning failed: Mailbox creation limit exceeded"
  }
}

Example payload (bot automation failure)

{
  "event": "ACCOUNT_FAILED",
  "eventId": 7,
  "occurredAt": "2026-06-04T15:12:45.000Z",
  "correlationId": "f3a4b5c6-d7e8-9012-cdef-012345678901",
  "applicant": {
    "id": 42,
    ...
    "applicantLifeCycleStatusId": 10,
    "applicantLifeCycleStatus": "Account Failed",
    "usptoAccountEmailStatusId": 2
  },
  "error": {
    "message": "Captcha solve timeout — extension did not solve within 120 seconds"
  },
  "video": {
    "type": "Signup",
    "typeId": 1,
    "path": "videos/signup_applicant_42_1717513965000.mp4",
    "durationSeconds": 125.4,
    "recordedAt": "2026-06-04T15:10:00.000Z"
  }
}

IDME_VERIFIED

EVENT ID: 8   PHASE 2

Fired when the bot confirms that the applicant has completed ID.me identity verification on USPTO. This is a critical milestone — the applicant is now eligible for trademark filing.

When it fires

Also fires alongside: APPLICANT_STATUS_CHANGED (transition 9 → 11)

Example payload

{
  "event": "IDME_VERIFIED",
  "eventId": 8,
  "occurredAt": "2026-06-05T10:30:00.000Z",
  "correlationId": "a4b5c6d7-e8f9-0123-abcd-ef4567890123",
  "applicant": {
    "id": 42,
    "customerId": 1001,
    "companyId": 5,
    "firstName": "Mike",
    "lastName": "Jacob",
    "emailAddress": "[email protected]",
    "usptoAccountEmail": "[email protected]",
    "usptoAccountPassword": "xY9!kP2m@LqR7n",
    "mfaSecret": "JBSWY3DPEHPK3PXP",
    "applicantLifeCycleStatusId": 11,
    "applicantLifeCycleStatus": "IDME Verified",
    "usptoAccountEmailStatusId": 2
  },
  "video": {
    "type": "USPTO Verification",
    "typeId": 2,
    "path": "videos/idme_applicant_42_1717578600000.mp4",
    "durationSeconds": 45.2,
    "recordedAt": "2026-06-05T10:29:15.000Z"
  }
}

IDME_VERIFICATION_FAILED

EVENT ID: 9   PHASE 2

Fired when an applicant exceeds the maximum waiting time for ID.me verification. This is a terminal failure — the applicant will not be re-processed.

When it fires

Also fires alongside: APPLICANT_STATUS_CHANGED (transition 9 → 12)

Example payload

{
  "event": "IDME_VERIFICATION_FAILED",
  "eventId": 9,
  "occurredAt": "2026-06-06T15:00:00.000Z",
  "correlationId": "b5c6d7e8-f9a0-1234-bcde-f56789012345",
  "applicant": {
    "id": 42,
    ...
    "applicantLifeCycleStatusId": 12,
    "applicantLifeCycleStatus": "Idme Verification Failed Waiting Limit Exceed",
    "usptoAccountEmailStatusId": 2
  },
  "video": {
    "type": "USPTO Verification",
    "typeId": 2,
    "path": "videos/idme_applicant_42_1717686000000.mp4",
    "durationSeconds": 30.1,
    "recordedAt": "2026-06-06T14:59:30.000Z"
  }
}

FILING_STATUS_CHANGED

EVENT ID: 3   PHASE 3

Fired on every filing status transition. Includes the application object and a filing-status transition.

When it fires

FromToMeaning
PENDING (1)UNDER_PROCESS (2)Bot picked up the application and started filing.
UNDER_PROCESS (2)DONE (3)Filing completed successfully (draft saved).
UNDER_PROCESS (2)ERROR (4)Filing failed at some wizard step.

Example payload

{
  "event": "FILING_STATUS_CHANGED",
  "eventId": 3,
  "occurredAt": "2026-06-06T16:00:00.000Z",
  "correlationId": "c6d7e8f9-a0b1-2345-cdef-678901234567",
  "applicant": {
    "id": 42,
    ...
    "applicantLifeCycleStatusId": 11,
    "applicantLifeCycleStatus": "IDME Verified"
  },
  "application": {
    "id": 101,
    "applicantId": 42,
    "filingStatusId": 3,
    "filingStatus": "Done"
  },
  "transition": {
    "from": 2,
    "to": 3,
    "fromTitle": "Under Process",
    "toTitle": "Done"
  },
  "video": {
    "type": "Filing",
    "typeId": 3,
    "path": "videos/filing_applicant_42_1717689600000.mp4",
    "durationSeconds": 340.5,
    "recordedAt": "2026-06-06T15:54:20.000Z"
  }
}

SUBMISSION_COMPLETED

EVENT ID: 5   PHASE 3

Fired when a trademark filing is saved as a draft on USPTO successfully. This is the final success event in the entire flow.

When it fires

Example payload

{
  "event": "SUBMISSION_COMPLETED",
  "eventId": 5,
  "occurredAt": "2026-06-06T16:00:01.000Z",
  "correlationId": "d7e8f9a0-b1c2-3456-defg-789012345678",
  "applicant": { ... },
  "application": {
    "id": 101,
    "applicantId": 42,
    "filingStatusId": 3,
    "filingStatus": "Done"
  },
  "video": {
    "type": "Filing",
    "typeId": 3,
    "path": "videos/filing_applicant_42_1717689600000.mp4",
    "durationSeconds": 340.5,
    "recordedAt": "2026-06-06T15:54:20.000Z"
  }
}

SUBMISSION_FAILED

EVENT ID: 6   PHASE 3

Fired when a trademark filing fails at any point during the wizard automation.

When it fires

Example payload

{
  "event": "SUBMISSION_FAILED",
  "eventId": 6,
  "occurredAt": "2026-06-06T16:05:00.000Z",
  "correlationId": "e8f9a0b1-c2d3-4567-efgh-890123456789",
  "applicant": { ... },
  "application": {
    "id": 102,
    "applicantId": 42,
    "filingStatusId": 4,
    "filingStatus": "Error"
  },
  "error": {
    "message": "Failed at step 'goods-services': Validation error — class 045 not found in ID Manual"
  },
  "video": {
    "type": "Filing",
    "typeId": 3,
    "path": "videos/filing_applicant_42_1717689900000.mp4",
    "durationSeconds": 180.2,
    "recordedAt": "2026-06-06T16:02:00.000Z"
  }
}

Complete Event Matrix

This table shows every callback event, when it fires, what triggers it, and what extra payload fields are included.

Event Code ID Source Trigger application transition video error
EMAIL_PROVISIONED 10 v1 API Email mailbox created successfully
APPLICANT_STATUS_CHANGED 2 Bot Any lifecycle status transition 🎬 on ACCOUNT_CREATED / ACCOUNT_FAILED only
ACCOUNT_FAILED 7 API + Bot Email provision failed OR bot automation failed 🎬 Signup
IDME_VERIFIED 8 Bot ID.me verification confirmed 🎬 Verification
IDME_VERIFICATION_FAILED 9 Bot ID.me wait limit exceeded (48h default) 🎬 Verification
FILING_STATUS_CHANGED 3 Bot Filing status transition (PENDING→UNDER_PROCESS→DONE/ERROR) (filing status) 🎬 Filing
SUBMISSION_COMPLETED 5 Bot Filing saved as draft successfully 🎬 Filing
SUBMISSION_FAILED 6 Bot Filing terminated with error 🎬 Filing

Lookup Tables

Applicant Lifecycle Statuses

IDTitlePhaseTerminal?
1PendingAPINo
2Email CreatedAPINo
3Form FillingPhase 1No
4Form SubmittedPhase 1No
5Email Verification PendingPhase 1No
6Email VerifiedPhase 1No
7Password SetupPhase 1No
8Security Method SetupPhase 1No
9Account CreatedPhase 1 ✅No
10Account FailedPhase 1 ❌Yes
11IDME VerifiedPhase 2 ✅No
12IDME Verification Failed - Waiting Limit ExceededPhase 2 ❌Yes

Filing Statuses

IDTitleTerminal?
1PendingNo
2Under ProcessNo
3DoneYes (success)
4ErrorYes (failure)

Callback Event IDs

IDCodeTitle
1ALLWildcard — matches all events (for URL subscription filtering)
2APPLICANT_STATUS_CHANGEDGeneric lifecycle transition
3FILING_STATUS_CHANGEDFiling pipeline transition
4FILING_STEP_ADVANCEDFiling wizard page advanced (reserved)
5SUBMISSION_COMPLETEDFiling draft saved successfully
6SUBMISSION_FAILEDFiling terminated with error
7ACCOUNT_FAILEDAccount creation failed
8IDME_VERIFIEDID.me verification completed
9IDME_VERIFICATION_FAILEDID.me wait limit exceeded
10EMAIL_PROVISIONEDUSPTO mailbox created successfully

Email Provisioning Statuses

IDTitleDescription
1PendingApplicant created, mailbox not yet provisioned.
2CreatedMailbox provisioned successfully.
3VerifiedEmail verified via USPTO activation link.
4FailedThird-party email provider returned error.

Bot Video Types

IDTitlePhaseAttached to Events
1SignupPhase 1APPLICANT_STATUS_CHANGED (→9 or →10), ACCOUNT_FAILED
2USPTO VerificationPhase 2IDME_VERIFIED, IDME_VERIFICATION_FAILED
3FilingPhase 3FILING_STATUS_CHANGED, SUBMISSION_COMPLETED, SUBMISSION_FAILED

Delivery & Retry Logic

Delivery Status Lifecycle

PENDING ──── dispatch tick ────► HTTP POST to your URL │ │ │ ┌─────┴─────┐ │ │ │ │ 2xx non-2xx / error │ │ │ │ ▼ ▼ │ DELIVERED attempts < MaxRetries? │ (terminal) │ │ ┌─────┴─────┐ │ │ │ │ Yes No │ │ │ │ ▼ ▼ │ FAILED_WILL_RETRY GIVEN_UP │ │ (terminal) │ │ │ NextRetryAt = now + │ (RetryBackoffSeconds × attempt) │ │ └──────────────────────────────┘

Delivery Status Reference

IDStatusTerminal?Description
1PENDINGNoWaiting for first dispatch attempt.
2DELIVEREDYes ✅Your server returned 2xx. Done.
3FAILED_WILL_RETRYNoDelivery failed, will retry after backoff.
4RETRYINGNoCurrently being retried by the dispatcher.
5GIVEN_UPYes ❌Exceeded MaxRetries. Will not be retried.

Configuration (per CompanyCallbackUrl)

SettingDescriptionExample
UrlYour webhook endpoint.https://api.yourapp.com/webhooks/uspto
HttpMethodHTTP method used for delivery.POST
MaxRetriesMaximum retry attempts before giving up.5
RetryBackoffSecondsBase backoff in seconds. Multiplied by attempt number.60 (1st=60s, 2nd=120s, 3rd=180s...)
TimeoutSecondsHTTP request timeout per attempt.30

Security Considerations

⛔ Sensitive Data in Every Payload

Every callback payload includes usptoAccountPassword and mfaSecret (when available). These are real credentials that grant access to the applicant's USPTO account.

  • Always use HTTPS for your callback URLs.
  • Store credentials securely — encrypt at rest.
  • Restrict access to your webhook endpoint.
  • Validate the source — consider IP whitelisting or shared secret headers.

Idempotency

Every payload includes a correlationId (UUID v4). If your server receives the same correlationId twice (e.g. due to retry), treat the second delivery as a no-op. Store processed correlationIds for at least the retry window duration.

Response Contract