System Overview & Lifecycle
This API powers a fully autonomous USPTO trademark filing bot. The end-to-end flow is:
API Call: Create Applicant
│
▼
┌─────────────────────────────────────────────────────────┐
│ PHASE 1 — Account Creation (Automated by Bot) │
│ │
│ 1. PENDING ──────────────► 2. EMAIL_CREATED │
│ (API inserts row) (mailbox provisioned) │
│ │
│ 3. FORM_FILLING ─────────► 4. FORM_SUBMITTED │
│ (bot fills USPTO form) (form submitted) │
│ │
│ 5. EMAIL_VERIFICATION_PENDING ► 6. EMAIL_VERIFIED │
│ (waiting for email) (link clicked) │
│ │
│ 7. PASSWORD_SETUP ───────► 8. SECURITY_METHOD_SETUP │
│ (password set) (MFA enrolled) │
│ │
│ 9. ACCOUNT_CREATED 10. ACCOUNT_FAILED │
│ (success — ready) (error — terminal) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ PHASE 2 — ID.me Verification (Automated by Bot) │
│ │
│ Bot signs in, checks /tm/verify-identity │
│ On success: 11. IDME_VERIFIED │
└─────────────────────────────────────────────────────────┘
│
▼
API Call: Create Filing (creates Application record)
│
▼
┌─────────────────────────────────────────────────────────┐
│ PHASE 3 — Trademark Filing (Automated by Bot) │
│ │
│ Filing Status: │
│ 1. PENDING ──► 2. UNDER_PROCESS ──► 3. DONE │
│ └──► 4. ERROR │
│ │
│ Bot signs in using stored credentials + TOTP, │
│ drives the multi-page USPTO wizard automatically. │
└─────────────────────────────────────────────────────────┘
Key Concepts
- Applicant — a person/entity for whom a USPTO account is created. One applicant can have many applications.
- Application — a single trademark filing tied to an applicant. Created via the master filing API.
- Company — a tenant. Each applicant belongs to a company. Companies have email domains and callback URLs.
- Lookup Codes — all enum-like fields use string codes (not database IDs). The API resolves them server-side.
- Callbacks — the bot sends webhook notifications to your registered callback URLs for status changes.
Important Rules
⚠️ Before Filing
- Applicant must exist and be
IDME_VERIFIED before filing.
- Only
PENDING applications can be edited (via PUT).
- All codes are case-insensitive.
- Country/State accept ISO2 codes OR full names.
Response Envelope (All Endpoints)
// Success
{
"IsSuccess": true,
"Data": { ... },
"Message": "Request completed successfully.",
"StatusCode": 200
}
// Error
{
"IsSuccess": false,
"Data": { "errors": [ { "path": "...", "code": "...", "message": "..." } ] },
"Message": "Validation failed",
"StatusCode": 400
}
USPTO Wizard Pages
When the bot files a trademark, it drives a multi-page USPTO wizard. Each section of your API payload maps to one or more wizard pages.
Wizard Page Sequence
| # | USPTO Wizard Page | API Section(s) | Purpose |
| 1 | Application Selection | application.typeCode | Selects "Standard" or "Less Common" type. Nearly all use "standard". |
| 2 | Owner Information | owners[] | Identifies who owns the trademark. Supports multiple owners (bot adds tabs). |
| 3 | Attorney Information | attorney | Attorney of record. Skipped entirely when attorney = null. |
| 4 | Correspondence Information | correspondence | Who receives official USPTO mail. |
| 5 | Mark Selection | mark.formatCode | Radio: Standard Character, Special Form, Sound, or Motion. |
| 6 | Standard Character (conditional) | mark.text | Only for Standard Character Mark. Single text field. |
| 7 | Stylized/Design Format (conditional) | mark.stylizedMarkTypeCode | Only for Special Form. Sub-type radio. |
| 8 | Color Claimed (conditional) | mark.colorClaimed | Only for Special Form. Yes/No color claim radio. |
| 9 | Mark Drawing (conditional) | mark.drawingFile | File upload. Bot handles color conversion panel auto. |
| 10 | Mark Details (conditional) | mark.description, mark.colorClaim | AI-generated description accepted automatically. |
| 11 | Translation | mark.translations[] | Non-English words. Empty = "No foreign words". |
| 12 | Name/Likeness Consent | mark.nameConsents[] | Living person's name/portrait. Empty = "No". |
| 13 | Goods & Services | goodsServices[] | Nice Classification class + descriptions. |
| 14 | Supporting Info (conditional) | specimen, dates | Only for basis 1A. Specimen upload. |
| 15 | Filing Basis Selection | filingBasisCode | Legal basis: 1A, 1B, 44D, 44E, or 66A. |
| 16 | Declaration & Signature | declaration | E-signature + 4 acknowledgement checkboxes. |
| 17 | Submit Overview | (terminal) | Bot saves as draft — does NOT live-submit. |
Entity Type → USPTO Owner Form
| entityTypeCode | USPTO Form Label | Identity Fields | Special Sections |
individual | Individual | firstName, lastName, countryOfCitizenshipCode | — |
sole_proprietorship | Sole Proprietorship | entityName + firstName, lastName, countryOfCitizenshipCode | — |
us_corporation | Corporation | entityName, stateOfIncorporationCode | Country auto-set to US |
us_llc | Limited Liability Company | entityName, stateOfIncorporationCode | Country auto-set to US. Requires members[] |
foreign_corporation | Corporation | entityName, countryOfIncorporationCode | — |
foreign_llc | Limited Liability Company | entityName, countryOfIncorporationCode | Requires members[] |
partnership | Partnership | entityName | Requires members[] with roleCode: "partner" |
limited_partnership | Limited Partnership | entityName, stateOfIncorporationCode | Country auto-set to US |
trust | Trust | entityName | Requires members[] with roleCode: "trustee" |
estate | Estate | entityName | Requires members[] with roleCode: "executor" |
joint_venture | Partnership | entityName | Requires members[] |
government | Other | entityName | Country auto-set to US |
other | Non-profit Association | entityName | Country auto-set to US |
💡 Key Insight
sole_proprietorship is the only entity type that requires
both entityName (business name) AND
firstName/
lastName (individual) plus
countryOfCitizenshipCode.
Mark Format → Wizard Path
| formatCode | Pages Shown | Required Fields |
Standard Character Mark | Mark Selection → Standard Character → Translation → ... | mark.text |
Special Form | Mark Selection → Stylized → Color Claimed → Drawing → Details → ... | mark.drawingFile, mark.stylizedMarkTypeCode, mark.description |
Sound Mark | Mark Selection → Drawing (audio) → ... | mark.soundFile |
Motion Mark | Mark Selection → Drawing (video) → ... | mark.motionFile |
Filing Basis → Wizard Behavior
| Code | Name | What the Bot Fills |
1A | Use in Commerce | firstUseAnywhereDate, firstUseInCommerceDate, specimen data |
1B | Intent to Use | Radio only — no additional data |
44D | Foreign Application | foreignApplication.countryCode, .serialNumber, .filingDate |
44E | Foreign Registration | foreignRegistration.countryCode, .registrationNumber, dates, certificate |
66A | Madrid Protocol | Radio only — no additional data |
Address Rules
- Mailing Address — always shown. Primary public address on trademark record.
- Domicile Address — only shown when "same as mailing" is unchecked.
- When
country = "United States" → State dropdown appears and must be filled.
- When
country ≠ "United States" → State field is hidden.
POST /applicants/create-applicant
Creates a new applicant and provisions a USPTO mailbox. The bot automatically picks up PENDING applicants and begins account creation.
POST
/api/v1/applicants/create-applicant
Request Body
{
"companyId": 1,
"customerId": 1014,
"nameTitle": "Mr",
"firstName": "Mike",
"middleName": null,
"lastName": "Jacob",
"suffix": null,
"emailAddress": "[email protected]",
"emailDomain": "trademarkluv.com",
"country": "US",
"state": "TX",
"cityId": null,
"streetAddress1": "411 Spruce St",
"streetAddress2": null,
"zipCode": "78701",
"phone": {
"dialCode": "1",
"countryCode": "US",
"number": "2179856987"
}
}
Field Reference
| Field | Type | Required | Validation | Purpose |
companyId | integer | Yes | positive int | Tenant ID. Determines available email domains. |
customerId | integer | Yes | positive int | Used as suffix in auto-generated USPTO email. |
nameTitle | string | No | max 50 | Salutation. Not used on USPTO form. |
firstName | string | Yes | 1–200 chars | Filled into USPTO "Create Account" first name field. |
middleName | string | No | max 200 | Filled into account form if present. |
lastName | string | Yes | 1–200 chars | Filled into USPTO account last name field. |
suffix | string | No | max 20 | Stored for records. Not on USPTO form. |
emailAddress | string | Yes | valid email | Your contact email. NOT the USPTO account email. |
emailDomain | string | Yes | 1–250 chars | Domain for auto-generated USPTO inbox. Must exist in AvailableDomains. |
country | string | Yes | 1–255 chars | ISO2 or full name. Used on USPTO account form. |
state | string | No | max 255 | ISO2 or full name. Only visible for US addresses. |
cityId | integer | No | positive int | City ID from lookup. Stored for records. |
streetAddress1 | string | Yes | 1–500 chars | Filled into USPTO account address field. |
streetAddress2 | string | No | max 500 | Additional address line. |
zipCode | string | No | max 50 | Filled into USPTO ZIP code field. |
phone.dialCode | string | Yes | digits only, 1–15 | Country code. No + prefix. Bot auto-prepends it. |
phone.countryCode | string | No | max 10 | ISO2 phone country. Sets flag on form. |
phone.number | string | Yes | digits only, 5–15 | Raw digits. No dashes/spaces/parentheses. |
What Happens Internally
- Country/state codes resolved to database IDs.
emailDomain validated against AvailableDomains table.
- Cryptographically strong USPTO-compliant password auto-generated (14 chars).
- Applicant inserted with
PENDING (1) status.
- USPTO email mailbox provisioned:
{firstname}.{lastname}{customerId}@{emailDomain}.
- Bot picks up on next cycle (every 10 seconds) and begins automation.
Success Response — 201 Created
{
"IsSuccess": true,
"Data": {
"applicantId": 42,
"usptoAccountEmail": "[email protected]",
"lifecycleStatus": "PENDING"
},
"Message": "Applicant created successfully.",
"StatusCode": 201
}
GET /applicants/:id/get-2fa-code
Returns the current live 6-digit TOTP code for an applicant's USPTO MFA account.
The code is generated server-side from the MFASecret stored in the database using
RFC 6238 (SHA-1, 30-second window) — identical to Google Authenticator output.
GET
/api/v1/applicants/:id/get-2fa-code
URL Parameter
| Parameter | Type | Description |
id | integer | Applicant primary-key ID |
Success Response — 200 OK
{
"IsSuccess": true,
"Data": {
"applicantId": 24,
"usptoAccountEmail": "[email protected]",
"totpCode": "482910",
"generatedAt": "2026-06-06T00:00:00.000Z"
},
"Message": "Request completed successfully.",
"StatusCode": 200
}
Response Fields
| Field | Type | Description |
applicantId | integer | The applicant's database ID |
usptoAccountEmail | string | null | USPTO mailbox provisioned for this applicant |
totpCode | string (6 digits) | Current TOTP code. Valid for up to 30 seconds from generatedAt. |
generatedAt | ISO 8601 timestamp | UTC timestamp when the code was generated |
Error Responses
| HTTP | When |
404 | Applicant with given id does not exist or has been soft-deleted. |
409 | Applicant exists but MFASecret is not set — TOTP enrollment in Phase 1 has not completed yet. |
💡 Lifecycle Note
MFASecret is written to the database only after the bot completes the
TOTP enrollment step in
Phase 1 (Account Creation). If the applicant's
lifecycle status is below
ACCOUNT_CREATED (9), expect a
409 response.
POST /applications/create-complete-application
Creates a complete trademark filing in a single atomic transaction. All child entities are inserted together — if any part fails, nothing is saved.
POST
/api/v1/applications/create-complete-application
Top-Level Fields
| Field | Type | Required | Description |
applicantId | integer | Yes | Must reference an existing, non-deleted applicant (ideally IDME_VERIFIED). |
clientApplicationId | string | No | Your external reference ID. Stored but not used by the bot. |
application | object | Yes | { "typeCode": "standard" } |
owners | array | Yes | At least 1 owner. See Owner Object below. |
attorney | object | null | No | Set null to file pro se (without attorney). |
correspondence | object | Yes | Who receives USPTO communications. |
mark | object | Yes | The trademark itself. |
goodsServices | array | Yes | At least 1 entry. Each represents one Nice Classification class. |
declaration | object | Yes | Signatory declaration under penalty of perjury. |
Owner Object
| Field | Type | Required | Description | Purpose on USPTO Form |
ownerOrder | integer | Yes | Unique sequential order (1, 2, 3...). | Determines tab order on Owner page. |
entityTypeCode | string | Yes | See Lookup Values. | Controls which sub-form USPTO renders. |
firstName | string | Cond | Required for individual & sole_proprietorship. | Fills "First name" field. |
lastName | string | Cond | Required for individual & sole_proprietorship. | Fills "Last name" field. |
countryOfCitizenshipCode | string | Cond | Required for individual & sole_proprietorship. | Fills "Country of citizenship" dropdown. Must be filled first for individuals. |
entityName | string | Cond | Required for all non-individual types. | Fills "Owner name" for juristic entities. |
stateOfIncorporationCode | string | No | For US entities. | Fills "State where legally organized" dropdown. |
countryOfIncorporationCode | string | No | For foreign entities. | Fills "Country where legally organized" dropdown. |
domicile | Address | Yes | Principal place of business. | Fills Domicile Address section. |
sameDomicileAndMailing | boolean | Yes | If true, mailing = domicile. | Controls "same as mailing" checkbox. |
mailingAddress | Address | Cond | Required when sameDomicileAndMailing = false. | Fills Mailing Address section. |
email | string | Yes | Valid email address. | Fills owner email field. |
phone | Phone | Yes | See Phone Object. | Fills phone + flag-picker. |
website | string | No | Owner's website URL. | Checks "add URL" checkbox, fills URL. |
isAddressPublic | boolean | No | Show domicile on public record. | Controls TSDR visibility. |
alternateName | string | No | DBA / alternate name. | Fills alternate name text field. |
alternateNameTypeCode | string | No | Required if alternateName set. | Selects type: DBA, AKA, TA. |
members | array | Cond | Required for: LLC, partnership, trust, estate. | Fills trustee/executor/partner cards. |
Address Object
| Field | Type | Required | Purpose |
streetLine1 | string | Yes | Fills "Address Line 1". |
streetLine2 | string | No | Fills "Address Line 2" (apt, suite). |
city | string | No | Fills "City" text field. |
state | string | No | Fills "State" dropdown. Only shown when country = "United States". |
postalCode | string | No | Fills "Zip/Postal Code". |
country | string | Yes | Fills "Country" dropdown. Drives State visibility. |
Phone Object
| Field | Type | Required | Purpose |
dialCode | string | Yes | Digits only, no +. Bot auto-prepends it. E.g. "1", "44". |
number | string | Yes | Digits only. Fills "Primary telephone" input. |
extension | string | No | Fills "Extension" input. |
Attorney Object
Set to null to file pro se (without attorney). The bot skips the Attorney page entirely.
| Field | Type | Required | Purpose |
name | string | Yes | Fills "Attorney name" field. |
firmName | string | No | Fills "Firm name" field. |
barStateCode | string | No | Fills "Bar membership state" dropdown. |
barNumber | string | No | Fills "Bar number" field. |
email | string | Yes | Attorney's email address. |
phone | Phone | Yes | Attorney's phone. |
address | Address | Yes | Attorney's mailing address. |
Correspondence Object
| Field | Type | Required | Purpose |
name | string | Yes | Fills "Correspondence Name". |
primaryEmail | string | Yes | Primary email for all USPTO communications. |
secondaryEmails | string[] | No | CC emails for correspondence. |
showPublicly | boolean | No | If true, email visible in TSDR. |
Mark Object
| Field | Type | Required | Purpose on USPTO Form |
formatCode | string | Yes | Selects mark format radio. Determines subsequent pages. |
text | string | Cond | Standard Character: fills text input. Special Form: fills "literal text" if detected. |
stylizedMarkTypeCode | string | Cond | Required for Special Form. Selects sub-type radio. |
colorClaimed | boolean | No | Drives Color Claimed page radio. |
description | string | Cond | Fallback for Mark Details. Bot first tries AI-generated description. |
colorClaim | string | No | Fallback for color claim textarea. |
disclaimer | string | No | Fills disclaimer on Additional Information page. |
drawingFile | FileRef | Cond | Required for Special Form. Uploaded to Mark Drawing page. |
soundFile | FileRef | Cond | Required for Sound Mark. |
motionFile | FileRef | Cond | Required for Motion Mark. |
translations | array | No | Each entry fills one translation row. Empty = "no foreign words". |
nameConsents | array | No | Each entry fills consent form. Empty = "no name/likeness". |
File Reference Object
Two options for providing files:
// Option A: Reference existing uploaded file
{ "fileAssetId": 123 }
// Option B: URL for bot to download
{ "sourceUrl": "https://example.com/logo.png" }
Mark Cross-Field Validation
| formatCode | text | drawingFile | soundFile | motionFile | stylizedMarkTypeCode | description |
Standard Character Mark | Required | Forbidden | — | — | — | — |
Special Form | — | Required | — | — | Required | Required |
Sound Mark | — | — | Required | — | — | — |
Motion Mark | — | — | — | Required | — | — |
Goods/Services Object
| Field | Type | Required | Purpose on USPTO Form |
entryOrder | integer | Yes | Order entries are added on the page. |
entryTypeCode | string | Yes | "idManual": search by subclass code. "freeForm": custom text. |
classNumber | string | Yes | 3-digit Nice class (e.g. "045", "009"). Zero-padded. |
subClassCode | string | Cond | Required for idManual. Search term on ID Manual tab. |
subClassTexts | string[] | No | Fills placeholder textareas in ID Manual entries. |
freeFormText | string | Cond | Required for freeForm. Typed into free-form textarea. |
filingBasisCode | string | Yes | Selects filing basis radio: 1A, 1B, 44D, 44E, 66A. |
firstUseAnywhereDate | string | Cond | MM/DD/YYYY. Required for 1A. "Date of first use anywhere". |
firstUseInCommerceDate | string | Cond | MM/DD/YYYY. Required for 1A. "Date of first use in commerce". |
specimen | object | Cond | Required for 1A. Proof of use (screenshot, label photo, etc.). |
foreignApplication | object | Cond | Required for 44D. Country, serial number, filing date. |
foreignRegistration | object | Cond | Required for 44E. Country, reg number, dates, certificate. |
Goods/Services Cross-Field Validation
| Basis | firstUseAnywhereDate | firstUseInCommerceDate | specimen | foreignApplication | foreignRegistration |
1A | Req | Req | Req | — | — |
1B | — | — | — | — | — |
44D | — | — | — | Req | — |
44E | — | — | — | — | Req |
66A | — | — | — | — | — |
Declaration Object
| Field | Type | Required | Purpose on USPTO Form |
signatureMethodCode | string | Yes | Selects signature method. Use "Electronic Signature". |
signatoryName | string | Yes | Fills "Signatory name". Declares under penalty of perjury. |
signatoryTitle | string | No | Fills "Signatory title" (e.g. CEO, Trustee). |
signatureText | string | Yes | E-signature: /FirstName LastName/ format. |
signatureDate | string | No | MM/DD/YYYY. USPTO auto-fills date — bot writes it back to DB. |
acknowledgeBasis | boolean | Yes | Must be true. "Entitled to use mark in commerce." |
acknowledgeUniqueness | boolean | Yes | Must be true. "No other person has right to use." |
acknowledgeFactualContents | boolean | Yes | Must be true. "All statements are true." |
acknowledgeWarning | boolean | Yes | Must be true. "Willful false statements punishable." |
⛔ All four acknowledge flags must be true
The request is rejected with
ACKNOWLEDGEMENT_REQUIRED if any flag is
false.
PUT /applications/create-complete-application/:appId
Atomically replaces an existing PENDING application. Deletes all child entities and re-inserts from the new payload.
PUT
/api/v1/applications/create-complete-application/{appId}
| Aspect | POST (Create) | PUT (Replace) |
| Creates new Application row | Yes | No — reuses existing |
| Deletes child entities first | No | Yes — atomic wipe + re-insert |
| Returns applicationId | New ID | Same appId from URL |
| Allowed status | Any | Application must exist & not be deleted |
| Response code | 201 | 200 |
Request body is identical to POST. The applicantId in the body is still required.
Lookup API Reference
GET
/api/v1/lookup/{resource}
| Resource | Description | Has Code Column |
owner-entity-types | All valid entity type codes | Yes |
filing-bases | Filing basis codes (1A, 1B, 44D, 44E, 66A) | Yes |
mark-formats | Mark format titles | No — use Title |
stylized-mark-types | Stylized mark sub-types | Yes |
goods-entry-types | idManual, freeForm | Yes |
signature-methods | Signature method titles | No — use Title |
name-likeness-types | Name, Portrait, Signature | Yes |
consent-proof-types | Declaration, Written Consent, Registration | Yes |
alternate-name-types | DBA, AKA, FKA, TA | Yes |
owner-member-roles | Member, Manager, Partner, Trustee, Executor, Beneficiary | Yes |
Other Lookup Endpoints
GET /api/v1/lookup/countries
GET /api/v1/lookup/states?countryId=1
GET /api/v1/lookup/cities?stateId=44
GET /api/v1/lookup/domains?companyId=1
GET /api/v1/lookup/companies
GET /api/v1/lookup/uspto-classes
GET /api/v1/lookup/uspto-sub-classes?classCode=045
All Lookup Values
📌 Note
All codes are
case-insensitive.
"us_llc",
"US_LLC",
"Us_Llc" all work.
Application Types
| Code | Title |
standard | Standard |
Owner Entity Types
| Code | Title | Required Fields |
individual | Individual | firstName, lastName, countryOfCitizenshipCode |
sole_proprietorship | Sole Proprietorship | entityName + firstName, lastName, countryOfCitizenshipCode |
us_corporation | US Corporation | entityName |
us_llc | US LLC | entityName, members[] |
foreign_corporation | Foreign Corporation | entityName |
foreign_llc | Foreign LLC | entityName, members[] |
partnership | Partnership | entityName, members[] |
limited_partnership | Limited Partnership | entityName, stateOfIncorporationCode |
joint_venture | Joint Venture | entityName, members[] |
trust | Trust | entityName, members[] |
estate | Estate | entityName, members[] |
government | Government | entityName |
other | Other | entityName |
Owner Member Roles
| Code | Title | Used With |
member | Member | us_llc, foreign_llc |
manager | Manager | us_llc, foreign_llc |
partner | Partner | partnership, joint_venture |
trustee | Trustee | trust |
executor | Executor | estate |
beneficiary | Beneficiary | trust, estate |
Alternate Name Types
| Code | Title |
dba | DBA (Doing Business As) |
aka | AKA (Also Known As) |
fka | FKA (Formerly Known As) |
ta | TA (Trading As) |
Mark Formats
⚠️ No Code column — pass the Title value
| Title (use as formatCode) | Description |
Standard Character Mark | Plain text only. No logo, no stylization. |
Special Form | Logo, stylized text, or design. Requires drawing file. |
Sound Mark | Audio mark. Requires sound file. |
Motion Mark | Video/animation mark. Requires motion file. |
Stylized Mark Types
| Code | Title |
design_only | Design Only |
wording_only | Wording Only |
wording_and_design | Wording and Design |
Filing Basis
| Code | Title | Trademark Act Section |
1A | Use in Commerce | §1(a) — Mark is already in use |
1B | Intent to Use | §1(b) — Bona fide intent to use |
44D | Foreign Application | §44(d) — Priority from foreign app |
44E | Foreign Registration | §44(e) — Based on foreign registration |
66A | Madrid Protocol | §66(a) — International registration |
Goods Entry Types
| Code | Title | Description |
idManual | ID Manual | Search by subclass code from USPTO's Trademark ID Manual. |
freeForm | Free Form | Custom description text (max 20,000 chars). |
Signature Methods
| Title (use as signatureMethodCode) |
Electronic Signature |
Handwritten Pen-and-Ink Signature |
Name Likeness Types
| Code | Title |
name | Name |
portrait | Portrait |
signature | Signature |
Consent Proof Types
| Code | Title |
declaration | Declaration |
written_consent | Written Consent |
registration | Registration |
Error Codes Reference
Schema Validation Errors (Zod — HTTP 400)
| Scenario | Example Error |
| Missing required field | "String must contain at least 1 character(s)" |
| Invalid email | "Invalid email" |
| Invalid date format | "Must be MM/DD/YYYY" |
| Invalid class number | "Must be 3-digit class like '045'" |
| Invalid phone.dialCode | "dialCode must contain digits only, no '+'" |
| Invalid phone.number | "number must contain digits only" |
Business Validation Errors (HTTP 400)
| Code | Path Example | When |
DUPLICATE_ORDER | owners[1].ownerOrder | Two owners have the same ownerOrder. |
REQUIRED | owners[0].firstName | Conditionally required field is missing. |
FORBIDDEN | owners[0].entityName | Field must be empty for this entity type. |
ACKNOWLEDGEMENT_REQUIRED | declaration | One or more acknowledge flags is false. |
UNKNOWN_CODE | owners[0].entityTypeCode | Lookup code doesn't exist in DB. |
UNKNOWN_FILE_ASSET | mark.drawingFile.fileAssetId | FileAsset doesn't exist or is deleted. |
UNKNOWN_DOMAIN | emailDomain | Domain not found in AvailableDomains. |
HTTP Status Codes
| Code | Meaning |
200 | Success (GET, PUT) |
201 | Created (POST) |
400 | Validation failed (schema or business rules) |
404 | Resource not found |
500 | Internal server error |
502 | Upstream dependency failure |
Complete Example Payloads
Example 1: Individual Owner, Standard Text Mark, 1A Basis
Scenario: An individual files a standard character trademark already in use.
{
"applicantId": 42,
"clientApplicationId": "CLIENT-REF-001",
"application": { "typeCode": "standard" },
"owners": [
{
"ownerOrder": 1,
"entityTypeCode": "individual",
"firstName": "Mike",
"lastName": "Jacob",
"countryOfCitizenshipCode": "US",
"domicile": {
"streetLine1": "411 Spruce St",
"city": "San Francisco",
"state": "CA",
"postalCode": "94102",
"country": "United States"
},
"sameDomicileAndMailing": true,
"noPhysicalLocation": false,
"email": "[email protected]",
"phone": { "dialCode": "1", "number": "2179856987" }
}
],
"attorney": null,
"correspondence": {
"name": "Mike Jacob",
"primaryEmail": "[email protected]"
},
"mark": {
"formatCode": "Standard Character Mark",
"text": "NEXOCRAFT",
"description": "The mark consists of standard characters NEXOCRAFT."
},
"goodsServices": [
{
"entryOrder": 1,
"entryTypeCode": "idManual",
"classNumber": "045",
"subClassCode": "045-2381",
"filingBasisCode": "1A",
"firstUseAnywhereDate": "01/15/2023",
"firstUseInCommerceDate": "03/01/2023",
"specimen": {
"description": "Screenshot of homepage showing the mark in use.",
"webUrl": "https://techbrand.com",
"accessDate": "2024-01-15",
"file": { "sourceUrl": "https://example.com/specimen.jpg" }
}
}
],
"declaration": {
"signatureMethodCode": "Electronic Signature",
"signatoryName": "Mike Jacob",
"signatureText": "/Mike Jacob/",
"acknowledgeBasis": true,
"acknowledgeUniqueness": true,
"acknowledgeFactualContents": true,
"acknowledgeWarning": true
}
}
Example 2: US LLC with Attorney, Logo Mark, Intent to Use
Scenario: A US LLC with members files a color logo with an attorney.
{
"applicantId": 42,
"application": { "typeCode": "standard" },
"owners": [
{
"ownerOrder": 1,
"entityTypeCode": "us_llc",
"entityName": "TechBrand LLC",
"stateOfIncorporationCode": "DE",
"domicile": {
"streetLine1": "123 Innovation Drive",
"city": "Austin",
"state": "Texas",
"postalCode": "78701",
"country": "US"
},
"sameDomicileAndMailing": true,
"email": "[email protected]",
"phone": { "dialCode": "1", "number": "5125550101" },
"website": "https://techbrand.com",
"members": [
{ "roleCode": "member", "name": "John Carter", "entityType": "individual", "countryCode": "US" },
{ "roleCode": "manager", "name": "Jane Doe", "entityType": "individual", "countryCode": "US" }
]
}
],
"attorney": {
"name": "Jane Smith",
"firmName": "Smith IP Law PLLC",
"barStateCode": "TX",
"barNumber": "TX-24098765",
"email": "[email protected]",
"phone": { "dialCode": "1", "number": "5125559988" },
"address": {
"streetLine1": "500 Congress Ave",
"city": "Austin",
"state": "TX",
"postalCode": "78701",
"country": "US"
}
},
"correspondence": {
"name": "Jane Smith",
"primaryEmail": "[email protected]",
"secondaryEmails": ["[email protected]"]
},
"mark": {
"formatCode": "Special Form",
"text": "TECHBRAND",
"stylizedMarkTypeCode": "Wording and Design",
"colorClaimed": true,
"description": "The mark consists of TECHBRAND in stylized blue text with a gear icon.",
"colorClaim": "The color blue is claimed as a feature of the mark.",
"drawingFile": { "sourceUrl": "https://example.com/logo.png" }
},
"goodsServices": [
{
"entryOrder": 1,
"entryTypeCode": "freeForm",
"classNumber": "042",
"freeFormText": "Software as a service (SaaS) featuring platforms for business automation",
"filingBasisCode": "1B"
}
],
"declaration": {
"signatureMethodCode": "Electronic Signature",
"signatoryName": "John Carter",
"signatoryTitle": "CEO",
"signatureText": "/John Carter/",
"acknowledgeBasis": true,
"acknowledgeUniqueness": true,
"acknowledgeFactualContents": true,
"acknowledgeWarning": true
}
}
Example 3: Trust with Translations & Name Consent
Scenario: A trust with trustees files a color logo containing a foreign word and a living person's name.
{
"applicantId": 42,
"application": { "typeCode": "standard" },
"owners": [
{
"ownerOrder": 1,
"entityTypeCode": "trust",
"entityName": "Carter Family Trust",
"domicile": {
"streetLine1": "500 Park Ave",
"city": "New York",
"state": "NY",
"postalCode": "10022",
"country": "United States"
},
"sameDomicileAndMailing": false,
"mailingAddress": {
"streetLine1": "PO Box 5500",
"city": "New York",
"state": "NY",
"postalCode": "10022",
"country": "US"
},
"email": "[email protected]",
"phone": { "dialCode": "1", "number": "2125550300" },
"members": [
{ "roleCode": "trustee", "name": "John Carter", "entityType": "individual", "countryCode": "US" },
{ "roleCode": "trustee", "name": "Sarah Carter", "entityType": "individual", "countryCode": "US" }
]
}
],
"attorney": null,
"correspondence": {
"name": "John Carter",
"primaryEmail": "[email protected]"
},
"mark": {
"formatCode": "Special Form",
"text": "CASA CARTER",
"stylizedMarkTypeCode": "Wording and Design",
"colorClaimed": true,
"description": "The mark consists of CASA CARTER in stylized gold script over a shield design.",
"colorClaim": "The colors gold and navy blue are claimed as features of the mark.",
"drawingFile": { "sourceUrl": "https://example.com/casa-carter-logo.png" },
"translations": [
{
"isNonLatinPhrase": false,
"nonEnglishWord": "Casa",
"language": "Spanish",
"hasEnglishMeaning": true,
"englishTranslation": "House"
}
],
"nameConsents": [
{
"likenessTypeCode": "name",
"legalName": "John Carter",
"isSignatory": true,
"consentToRegister": true,
"proofTypeCode": "declaration"
}
]
},
"goodsServices": [
{
"entryOrder": 1,
"entryTypeCode": "idManual",
"classNumber": "025",
"subClassCode": "025-0100",
"filingBasisCode": "1B"
}
],
"declaration": {
"signatureMethodCode": "Electronic Signature",
"signatoryName": "John Carter",
"signatoryTitle": "Trustee",
"signatureText": "/John Carter/",
"acknowledgeBasis": true,
"acknowledgeUniqueness": true,
"acknowledgeFactualContents": true,
"acknowledgeWarning": true
}
}
Fetching USPTO Classes
GET /api/v1/lookup/uspto-classes
→ [
{ "Id": 1, "ClassCode": "001", "ClassTitle": "Chemicals", "ClassType": "Goods" },
{ "Id": 9, "ClassCode": "009", "ClassTitle": "Electrical and Scientific Apparatus", "ClassType": "Goods" },
{ "Id": 42, "ClassCode": "042", "ClassTitle": "Computer & Scientific & Legal", "ClassType": "Services" },
{ "Id": 45, "ClassCode": "045", "ClassTitle": "Personal & Legal & Social", "ClassType": "Services" }
]
GET /api/v1/lookup/uspto-sub-classes?classCode=045
→ [
{ "Id": 100, "SubClassCode": "045-2381", "ClassCode": "045", "SubClassTitle": "Online social networking..." },
{ "Id": 101, "SubClassCode": "045-2380", "ClassCode": "045", "SubClassTitle": "Social introduction..." }
]
Date Format Summary
| Context | Format | Example |
firstUseAnywhereDate | MM/DD/YYYY | "01/15/2023" |
firstUseInCommerceDate | MM/DD/YYYY | "03/01/2023" |
signatureDate | MM/DD/YYYY | "06/03/2026" |
foreignApplication.filingDate | YYYY-MM-DD | "2023-06-15" |
foreignRegistration.registrationDate | YYYY-MM-DD | "2023-09-01" |
foreignRegistration.expirationDate | YYYY-MM-DD | "2033-09-01" |
specimen.accessDate | YYYY-MM-DD | "2024-01-15" |
📅 Date Format Rule
Domestic dates use
MM/DD/YYYY (USPTO format). Foreign dates use
YYYY-MM-DD (ISO).
Bot Automation Details
Filing Data Pipeline
Your API Call (POST /create-complete-application)
│
▼
┌─────────────────────────────────────────────────┐
│ 1. Zod Schema Validation │
│ → masterFilingSchema validates structure │
│ → Cross-field rules (entity type, basis, etc.)│
├─────────────────────────────────────────────────┤
│ 2. Business Validation │
│ → Resolve all codes to DB IDs │
│ → Validate file assets exist │
│ → Check acknowledgement flags │
├─────────────────────────────────────────────────┤
│ 3. MSSQL Transaction (atomic insert) │
│ → Application + Owners + Attorney + │
│ Correspondence + Mark + Goods + Declaration │
├─────────────────────────────────────────────────┤
│ 4. Filing Status = PENDING │
│ → Queued for bot pickup │
└─────────────────────────────────────────────────┘
│ (bot picks up on next cycle — every 10s)
▼
┌─────────────────────────────────────────────────┐
│ 5. Filing Data Assembly │
│ → DB → IRawFilingPayload → IFilingFormData │
├─────────────────────────────────────────────────┤
│ 6. USPTO Wizard Automation │
│ → Signs in with stored credentials + TOTP │
│ → Navigates wizard (max 50 page visits) │
│ → Fills each page declaratively │
├─────────────────────────────────────────────────┤
│ 7. Outcome │
│ → Success: Status = DONE + webhook │
│ → Error: Status = ERROR + webhook │
└─────────────────────────────────────────────────┘
Bot Behavior Highlights
- Draft, not submit: The bot saves as a USPTO draft — does NOT click final "Submit".
- Signature date writeback: USPTO auto-generates a signing date. Bot reads it and writes back to your DB.
- AI mark description: For Special Form, bot accepts USPTO's AI suggestion. Falls back to your text if AI fails.
- Color conversion: Color image +
colorClaimed = false → bot auto-accepts B&W conversion.
- Multi-owner tabs: Bot adds owner tabs via "+ Add" and fills each sequentially.
- Phone dial code: Bot interacts with flag-picker. US default (
"1") needs no interaction.
- Screenshots: Taken at key steps and on every error. Stored in
screenshots/.
- Error reporting: Page validation errors captured and sent via webhook.
Webhook Callbacks
| Event | When |
APPLICANT_STATUS_CHANGED | Any lifecycle status transition. |
ACCOUNT_FAILED | Account creation failed (terminal). |
IDME_VERIFIED | ID.me verification completed — ready for filing. |
FILING_STATUS_CHANGED | Filing status changes (PENDING → UNDER_PROCESS → DONE/ERROR). |
SUBMISSION_COMPLETED | Filing saved as draft successfully. |
SUBMISSION_FAILED | Filing failed with error. |
Callbacks are delivered with retry logic (configurable per company). Failed deliveries use linear backoff up to a configurable maximum.
WebSocket — Live TOTP Authenticator
The server exposes a WebSocket endpoint that pushes the current live TOTP codes
for all enrolled applicants every 10 seconds (configurable via
AUTHENTICATOR_REFRESH_INTERVAL_MS env var). No polling required — just connect and listen.
WS
/api/authenticator
Connect & Listen
const ws = new WebSocket("https://filingbot.crmbytes.com/api/authenticator");
ws.onopen = () => console.log("Connected");
ws.onmessage = (e) => {
const snapshot = JSON.parse(e.data);
console.log(snapshot);
};
ws.onclose = () => console.log("Disconnected");
ws.onerror = (err) => console.error("WS error", err);
Behavior on Connect
⚡ Immediate First Message
Upon connecting, the server
immediately sends the last known snapshot
so the client doesn’t have to wait up to 10 seconds for the first broadcast.
After that, a fresh snapshot is pushed every
AUTHENTICATOR_REFRESH_INTERVAL_MS (default 10s).
Message Shape (IAuthenticatorSnapshot)
{
"capturedAt": "2026-06-06T00:00:00.000Z",
"entries": [
{
"issuer": "[email protected]",
"account": "Applicant #24",
"code": "482910"
},
{
"issuer": "[email protected]",
"account": "Applicant #42",
"code": "719034"
}
]
}
Field Reference
| Field | Type | Description |
capturedAt | ISO 8601 string | UTC timestamp when this snapshot was generated |
entries | array | One entry per enrolled applicant. Empty array if no applicants have an MFASecret yet. |
entries[].issuer | string | The applicant’s USPTO account email (USPTOAccountEmail) |
entries[].account | string | Human-readable label e.g. "Applicant #24" |
entries[].code | string (6 digits) | Current live TOTP code. Valid for the remainder of the current 30-second window. |
Key Points
- Server-sent only — this is a one-way broadcast. The client never sends messages; the server ignores any inbound frames.
- All applicants in one message — every broadcast contains codes for all enrolled applicants. Filter by
issuer or account on the client side.
- Same port — no extra port. The WS server is attached to the same HTTP server as the REST API (
:3001 by default).
- Codes expire every 30s — RFC 6238, SHA-1, 30-second window. A code received near a window boundary may expire within seconds. The next broadcast (within 10s) will carry the fresh code.
- Only enrolled applicants — applicants without an
MFASecret (Phase 1 not yet completed) are silently excluded from the snapshot.