# Add Business Source: https://docs.worthai.com/api-reference/add-or-update-business/add-business post /businesses/customers/{customerID} Create a single business record based on the provided details. For more details on using this endpoint, please reference the [Getting Started](https://docs.worthai.com/getting-started/overview) guide. # Update Business Source: https://docs.worthai.com/api-reference/add-or-update-business/update-business patch /businesses/customers/{customerID} Update an existing business record based on the provided details. One of businessID or external_id MUST be provided to identify a business to update. # Create Customer User Source: https://docs.worthai.com/api-reference/auth/customers/create-customer-user post /customers/{customerID}/users Allows Customer to create a new user under a specific customer. # Customer User Resend Invitation Source: https://docs.worthai.com/api-reference/auth/customers/customer-user-resend-invitation post /customers/{customerID}/users/{userID}/resend-invite Allows customer with proper permissions to resend an invite to a specific user associated with a customer. # Get Customer Subroles Source: https://docs.worthai.com/api-reference/auth/customers/get-customer-subroles get /customers/{customerID}/subroles Fetches a list of subroles associated with a specific customer. Accessible by respective Customer. # Get Customer User By ID Source: https://docs.worthai.com/api-reference/auth/customers/get-customer-user-by-id get /customers/{customerID}/users/{userID} Fetch details of a specific user associated with a customer. # Get Customer Users Source: https://docs.worthai.com/api-reference/auth/customers/get-customer-users get /customers/{customerID}/users Fetches a list of users associated with a specific customer. Accessible by respective Customer. # Update Customer User By ID Source: https://docs.worthai.com/api-reference/auth/customers/update-customer-user-by-id patch /customers/{customerID}/users/{userID} Update user details for a specific customer. # Customer Logout Source: https://docs.worthai.com/api-reference/auth/sign-in/customer-logout post /customer/logout Logs out a customer user by invalidating their session or token. # Customer Refresh Token Source: https://docs.worthai.com/api-reference/auth/sign-in/customer-refresh-token post /refresh-token/customer Refreshes the customer's authentication token to maintain session validity. # Customer Sign In Source: https://docs.worthai.com/api-reference/auth/sign-in/customer-sign-in post /customer/sign-in This endpoint allows customers to sign in with their email and password. See Response -> Data -> customer_details below for the customerID used in other requests. # Customer Forgot Password Init Source: https://docs.worthai.com/api-reference/auth/sign-in/forgot-password-init post /customer/forgot-password Sends a password reset link to the Customer account registered with the given email. If no account exists for that portal, the response is the same and no email is sent. # Reset Password Source: https://docs.worthai.com/api-reference/auth/sign-in/reset-password post /reset-password Allows a user to reset their password using a valid reset token. # Accept Invitation Source: https://docs.worthai.com/api-reference/auth/users/accept-invitation post /invite/{inviteToken}/accept Allows a user to accept an invitation using an invite token. # Adding Custom Fields with POST Add Business and PATCH Update Business Source: https://docs.worthai.com/api-reference/case/businesses/add-update-business-custom-fields ## Using POST Add Business and PATCH Update Business with Custom Fields ### Getting Started 1. Ensure you are utilizing custom fields by contacting your Customer Success representative. 2. Await confirmation that a custom field template has been added to your environment. 3. Gather custom field IDs and review type structures in the "Custom Field Types" section. 4. Utilize the "Adding to POST and PATCH" section below to see payload structure and examples. 5. Make your POST or PATCH request ### Custom Field Types Currently, the following custom field types are supported via POST Add Business and PATCH Update Business requests: * **Boolean**: Standard true/false boolean values. * **Integer**: Whole number types (1, 2, 100, -1000, 999999999, etc.) * **Decimal**: Decimal number types (1.1, 2.0195, -1000.0001, 999999.9999992, etc.) * **Text**: Single strings with no line breaks. * **Dropdown**: A label/value object pair, a stringifed object pair, or a string representing the selected dropdown value. * **Example 1**: Dropdown JSON Object ```JSON lines theme={null} { "label": "Option1", "value": "Option1" } ``` * **Example 2**: Stringified dropdown object: `"{\"label\": \"Option1\", \"value\": \"Option1\"}"` * **Example 3**: String value: `"Option1"` *(Note: this is the value, not the label)* * **Checkbox**: An array of checkbox objects or a stringified array of checkbox objects representing the checked items. * **Example 1**: Checkbox JSON Object Array - Single Checked Option ```JSON lines theme={null} [ { "label": "Option1", "value": "Option1", "checkbox_type": "", "checked": true } ] ``` * **Example 2**: Checkbox JSON Object Array - Multiple Checked Options ```JSON lines theme={null} [ { "label": "Option1", "value": "Option1", "checkbox_type": "", "checked": true }, { "label": "Option2", "value": "Option2", "checkbox_type": "", "checked": true } ] ``` * **Example 3**: Stringified checkbox object array: `"[{\"label\": \"Option1\", \"value\": \"Option1\", \"checkbox_type\": \"\", \"checked\": true}]"` ### Adding to POST and PATCH To add custom fields to the [POST Add Business](/api-reference/add-or-update-business/add-business) payload or [PATCH Update Business](/api-reference/add-or-update-business/update-business) payload, simply include them in the payload body using a combination of "custom:" prefix and custom field ID as the property name. Then, provide the data appropriately using the "Custom Field Types" as reference. #### POST examples Enabled Custom Fields: * Age of Business (years): * **Custom field ID**: age\_of\_business\_years * **Type**: `integer` * Age of Business (months) * **Custom field ID**: age\_of\_business\_months * **Type**: `integer` * Business Fun Fact * **Custom field ID**: fun\_fact * **Type**: `text` Minimum Add Business Payload: ```JSON lines theme={null} { "name": "Company Incorporated LLC" } ``` Add Business Payload with Custom Fields: ```JSON lines wrap theme={null} { "external_id": "Custom_Fields_Example_01", "name": "Company Incorporated LLC", "custom:age_of_business_years": 49, "custom:age_of_business_months": 11, "custom:fun_fact": "This business will always be one month short of 50 years old!" } ``` Enabled Custom Fields: * Age of Business (years): * **Custom field ID**: age\_of\_business\_years * **Type**: `integer` * Age of Business (months) * **Custom field ID**: age\_of\_business\_months * **Type**: `integer` * Business Fun Fact * **Custom field ID**: fun\_fact * **Type**: `text` * How Did You Hear About Us? * **Custom field ID**: marketing\_channel * **Type**: `dropdown` * **Options**: * Label: "Web Ad", Value: "Web Ad" * Label: "Phone Call", Value: "Phone Call" * Label: "Recommendation", Value: "Recommendation" * Label: "Other", Value: "Other" * What Services Do You Need? * **Custom field ID**: services\_needed * **Type**: `checkbox` * **Options**: * Label: "Loan", Value: "Loan" * Label: "Business Advice", Value: "Business Advice" * Label: "Other", Value: "Other" Minimum Add Business Payload: ```JSON lines theme={null} { "name": "Company Incorporated LLC" } ``` Add Business Payload with Custom Fields: ```JSON lines wrap theme={null} { "external_id": "Custom_Fields_Example_02", "name": "Company Incorporated LLC", "custom:age_of_business_years": 49, "custom:age_of_business_months": 11, "custom:fun_fact": "This business will always be one month short of 50 years old!", "custom:marketing_channel": { "label": "Phone Call", "value": "Phone Call" }, "custom:services_needed": [ { "label": "Loan", "value": "Loan", "checkbox_type": "", "checked": true } ] } ``` Enabled Custom Fields: * Does Business Vertical Match Typical? * **Custom field ID**: business\_vertical\_compatible * **Type**: `boolean` * *internal field* * Age of Business (years): * **Custom field ID**: age\_of\_business\_years * **Type**: `integer` * *external field* * Age of Business (months) * **Custom field ID**: age\_of\_business\_months * **Type**: `integer` * *external field* * Business Fun Fact * **Custom field ID**: fun\_fact * **Type**: `text` * *external field* * Business Un-fun Fact * Custom field ID: un\_fun\_fact * **Type**: `text` * *external field* * How Did You Hear About Us? * **Custom field ID**: marketing\_channel * **Type**: `dropdown` * **Options**: * Label: "Web Ad", Value: "giggle\_addcents" * Label: "Phone Call", Value: "sales\_channel-cold" * Label: "Recommendation", Value: "partner\_rec" * Label: "Other", Value: "other" * *external field* * What Services Do You Need? * **Custom field ID**: services\_needed * **Type**: `checkbox` * **Options**: * Label: "Loan", Value: "loan" * Label: "Business Advice", Value: "business\_advice" * Label: "Other", Value: "other" * *external field* Minimum Add Business Payload: ```JSON lines theme={null} { "name": "Company Incorporated LLC" } ``` Add Business Payload with Custom Fields: ```JSON lines wrap theme={null} { "external_id": "Custom_Fields_Example_03", "name": "Company Incorporated LLC", "custom:business_vertical_compatible": true, "custom:age_of_business_years": 49, "custom:age_of_business_months": 11, "custom:un_fun_fact": "Fun facts are not fun.", "custom:marketing_channel": "giggle_addcents", "custom:services_needed": [ { "label": "Loan", "value": "loan", "checkbox_type": "", "checked": true }, { "label": "Business Advice", "value": "business_advice", "checkbox_type": "", "checked": true }, { "label": "Other", "value": "other", "checkbox_type": "", "checked": true } ] } ``` When a field is not needed, do not include it in the payload. Sending a blank or null value could lead to an empty field being returned later. # Get Business Cases Source: https://docs.worthai.com/api-reference/case/businesses/get-business-cases get /customers/{customerID}/businesses/{businessID}/cases Retrieve details about cases associated with a particular customerID and businessID. # Get Business By ID Source: https://docs.worthai.com/api-reference/case/businesses/get-business-details get /businesses/{businessID} Retrieve details for a particular business associated with the businessID provided # Get Business Custom Fields Source: https://docs.worthai.com/api-reference/case/businesses/get-custom-fields get /businesses/{businessID}/custom-fields Retrieves custom fields associated with a specified business ID. Custom fields must be enabled to utilize this endpoint. To confirm if you have custom fields enabled, please reach out to your Customer Success representative. # Get Customer Businesses Source: https://docs.worthai.com/api-reference/case/businesses/get-customer-businesses get /businesses/customers/{customerID} Get all businesses associated with a particular customerID. # Reverse NPI Lookup with POST Add Business Source: https://docs.worthai.com/api-reference/case/businesses/npi-reverse-lookup ## NPI Reverse Lookup Using POST Add Business ### Getting Started 1. Confirm NPI lookup has been enabled by contacting your Customer Success representative. 2. Add NPI related name fields to payload. 3. POST ### NPI Reverse Lookup Payload Additions In the body of the payload during an Add Business call, the following fields MUST be added for a reverse lookup: * `npi_first_name` - the first name of the provider to be checked * `npi_last_name` - the last name of the provider to be checked These additional fields will prompt Worth systems to do a reverse lookup of the provider and associate their NPI info with their case. For reverse lookup to find a match, the provider *must* match to a business registered within the NPI database. If the provider is not associated with a business, no match will be found. If the business is not found, even with a valid provider, no match will be made. ## Example Add Business Payload with Lookup Fields: ```json theme={null} { "external_id": "abc-123", "name": "Medical Office, LLC", "tin": "123456789", "address_line_1": "123 Testing Blvd", "address_city": "Townsville", "address_state": "IL", "address_postal_code": "12345", "npi_first_name": "Fessor", "npi_last_name": "Utanium" } ``` # Get Customer Case By ID Source: https://docs.worthai.com/api-reference/case/cases/get-customer-case-by-id get /customers/{customerID}/cases/{caseID} Retrieve details about a particular case associated with the given customerID and caseID. # Get Customer Cases Source: https://docs.worthai.com/api-reference/case/cases/get-customer-cases get /customers/{customerID}/cases Retrieve all cases associated with a particular customerID. # Update case status Source: https://docs.worthai.com/api-reference/case/cases/update-assign-case openapi/case-service/update-assign-case.json patch /customers/{customerID}/cases/{caseID} Updates the status of a case (and optionally the assignee). Only certain status transitions are allowed depending on the case’s current status. # Send Business Invite Source: https://docs.worthai.com/api-reference/case/invites/send-business-invite POST /customers/{customerID}/businesses/invite Send an invitation to onboard a business and its applicants. You can either create a new business with the invite or reference an existing business. At least one applicant must be provided via the `applicants` array. Applicant email addresses must not use disposable email domains. # Get Related Businesses Source: https://docs.worthai.com/api-reference/case/related-businesses/get-related-businesses get /customers/{customerID}/businesses/{businessID}/related-businesses Retrieves a list of businesses related to the one specified by the given businessID. # Get Reports Source: https://docs.worthai.com/api-reference/integration/accounting/get-reports get /accounting/report/{business_id}/{report} Retrieve reports (balance sheet, income statement, or cash flow) associated with a particular business_id. # Banking Information Details Source: https://docs.worthai.com/api-reference/integration/banking/banking-information-details openapi/integration-service/banking_information_details.json get /banking/business/{businessID} Retrieve banking information for a particular business. # Bankruptcies Judgements & Liens (BJL) Source: https://docs.worthai.com/api-reference/integration/facts/bankruptcies-judgements-&-liens-bjl get /facts/business/{businessId}/bjl Retrieve bankruptcies, judgements, and liens associated with a business # KYB Source: https://docs.worthai.com/api-reference/integration/facts/kyb get /facts/business/{businessId}/kyb Retrieves comprehensive 'Know Your Business' verification details for a given business identifier, including legal, formation, ownership, address, and match data from multiple sources. Prior to utilizing this service, one must first obtain a businessID by creating a business via the [Add business](https://docs.worthai.com/api-reference/add-or-update-business/add-business) service. For more details on using these endpoints, please reference the [Getting Started](https://docs.worthai.com/getting-started/overview) guide. # Reviews Source: https://docs.worthai.com/api-reference/integration/facts/reviews get /facts/business/{businessId}/reviews Retrieves 'Business Reviews' for a given business identifier from multiple sources across several review platforms. Prior to utilizing this service, one must first obtain a businessID by creating a business via the [Add business](https://docs.worthai.com/api-reference/add-or-update-business/add-business) service. For more details on using these endpoints, please reference the [Getting Started](https://docs.worthai.com/getting-started/overview) guide. # Check Match Pro Connection Source: https://docs.worthai.com/api-reference/integration/match-pro/check-match-pro-connection openapi/integration-service/match-pro.json get /match-pro/{customerId}/check-connection-status Tests whether the stored Match Pro credentials are valid and reachable. Use this endpoint after saving credentials to confirm the setup is working before running match checks. **Status values**: - `CONNECTED` — credentials are valid and the connection is active - `NOT_CONNECTED` — no credentials saved, or `isActive` is `false` - `EXPIRED` — the key file certificate has passed its expiry date - `ERROR` — credentials exist but the connection attempt failed The `customerId` path parameter must belong to the caller's tenant. Cross-tenant access is rejected with `403`. # Get Match Pro Environment Source: https://docs.worthai.com/api-reference/integration/match-pro/get-match-pro-environment openapi/integration-service/match-pro.json get /match-pro/{customerId}/environment Returns the Match Pro environment the customer tenant is currently configured for. The environment determines which payment network endpoint Match Pro checks run against. **Environment values**: - `sandbox` — Sandbox (test data only) - `mtf` — MTF / Market Test Facility (pre-production testing) - `prod` — Production (live data) **The environment cannot be changed through the API.** To move a customer between environments — for example from Sandbox to MTF or Production — contact the Worth team to request the change. The `customerId` path parameter must belong to the caller's tenant. Cross-tenant access is rejected with `403`. # Get Match Pro Result Source: https://docs.worthai.com/api-reference/integration/match-pro/get-match-pro-result openapi/integration-service/match-pro.json get /verification/businesses/{businessId}/match-pro Retrieves the latest Match Pro result for a business. The response shape depends on the current state: - **Result available**: Returns the full match data object. - **Processing**: The check is still running. Retry after a short delay (results typically appear within 1–5 minutes). - **Not yet run**: No Match Pro check has been initiated for this business. The `businessId` path parameter must belong to the caller's tenant. Cross-tenant access is rejected with `403`. # Match Pro Overview Source: https://docs.worthai.com/api-reference/integration/match-pro/match-pro-overview Configure credentials, verify connectivity, and run Match Pro checks against businesses in your portfolio. ## What is Match Pro? Match Pro lets you screen the businesses in your portfolio against a payment network's merchant termination database. Once configured, you can run checks per business and retrieve the results through the API. All Match Pro requests require an `Authorization: Bearer ` header. The customer and business path parameters are scoped to your account — requests for resources outside your account are rejected with `403`. ## Recommended flow Set up your Match Pro credentials (consumer key, customer name, ICA identifiers, and key file) in the Worth dashboard. Credential setup is managed through the UI, not the API. Call [`GET /match-pro/{customerId}/check-connection-status`](/api-reference/integration/match-pro/check-match-pro-connection) to confirm the saved credentials are valid and reachable before running any checks. Call [`POST /verification/customers/{customerId}/businesses/{businessId}/match-pro`](/api-reference/integration/match-pro/run-match-pro) for a specific business. The call returns a task acknowledgment — the result is retrieved separately. Poll [`GET /verification/businesses/{businessId}/match-pro`](/api-reference/integration/match-pro/get-match-pro-result) until the result is available. Results typically appear within 1–5 minutes. ## Managing credentials Match Pro credentials (consumer key, customer name, ICA identifiers, and key file) are configured in the Worth dashboard, not through the API. Set up or update your credentials in the UI before using the Match Pro endpoints. After configuring credentials in the dashboard, confirm the setup from the API with [`GET /match-pro/{customerId}/check-connection-status`](/api-reference/integration/match-pro/check-match-pro-connection) before running checks. A `CONNECTED` status means credentials are valid and active. `NOT_CONNECTED`, `EXPIRED`, or `ERROR` indicate the configuration is not ready. ## Running checks and retrieving results Run a check with [`POST /verification/customers/{customerId}/businesses/{businessId}/match-pro`](/api-reference/integration/match-pro/run-match-pro). The request body is optional: include `{ "icas": ["1996"] }` to target specific ICA identifiers, or omit it to use the ICAs stored in your credentials. Checks run asynchronously, so this endpoint returns a task acknowledgment rather than the result. Retrieve the result with [`GET /verification/businesses/{businessId}/match-pro`](/api-reference/integration/match-pro/get-match-pro-result), which returns one of three states: result available, still processing, or not yet run. Results typically appear within 1–5 minutes, so poll periodically until the result is available. ## Environment You can check which Match Pro environment your account is configured for with [`GET /match-pro/{customerId}/environment`](/api-reference/integration/match-pro/get-match-pro-environment): * `sandbox` — test data only * `mtf` — pre-production testing * `prod` — live data The environment cannot be changed through the API. To move between environments — for example from Sandbox to Production — contact the Worth team. # Run Match Pro Source: https://docs.worthai.com/api-reference/integration/match-pro/run-match-pro openapi/integration-service/match-pro.json post /verification/customers/{customerId}/businesses/{businessId}/match-pro Initiates a Match Pro check for a specific business. The check runs asynchronously; this endpoint returns a task acknowledgment, not the match result. To retrieve the match result, poll `GET /verification/businesses/{businessId}/match-pro` after the task reaches `completed` status. Results typically appear within 1–5 minutes. **Prerequisites**: Match Pro credentials must be configured in the Worth dashboard and the connection must be `CONNECTED` before running a check. Verify connectivity with `GET /match-pro/{customerId}/check-connection-status`. The `customerId` and `businessId` path parameters must belong to the caller's tenant. Cross-tenant access is rejected with `403`. # Adverse Media Source: https://docs.worthai.com/api-reference/integration/public-records/adverse-media openapi/integration-service/adverse-media.json get /business/{businessID}/adverse-media Retrieve adverse media associated with a particular businessID # Public Records Source: https://docs.worthai.com/api-reference/integration/public-records/public-records get /business/{businessID}/public-records Retrieve public records associated with a particular businessID # Tax Filing Source: https://docs.worthai.com/api-reference/integration/taxation/tax-filing get /accounting/tax-filing/business/{businessID} Retrieve annualized tax data associated with a particular businessID # Get Website Data Source: https://docs.worthai.com/api-reference/integration/verification/get-business-website-data get /verification/businesses/{businessID}/website-data Fetch enriched business website data, including domain details, SSL status, and associated metadata. # Get NPI Details Source: https://docs.worthai.com/api-reference/integration/verification/get-npi-details get /verification/businesses/{businessID}/healthcare Fetch NPI healthcare provider details associated with a business # Get Verification Details Source: https://docs.worthai.com/api-reference/integration/verification/get-verification-details get /verification/businesses/{businessID}/business-entity Retrieves detailed verification results for a business, including submitted values, matched sources, and confidence levels. # KYC Ownership Verification Source: https://docs.worthai.com/api-reference/integration/verification/kyc-ownership-verification get /verification/businesses/{businessId}/owners Know Your Customer: returns a list of individuals with ownership or control, including their submitted personal details and verification results. Prior to utilizing this service, one must first obtain a businessID by creating a business via the [Add business](https://docs.worthai.com/api-reference/add-or-update-business/add-business) service. For more details on using these endpoints, please reference the [Getting Started](https://docs.worthai.com/getting-started/overview) guide. # Get Business Score Source: https://docs.worthai.com/api-reference/score/score/get-business-score get /score/business/{businessID} Retrieve the Worth score and detailed score breakdown for the specified business entity. The optional `year` and `month` query parameters can be used to retrieve a historical score for a specific month. Because a business score can be generated more than once within the same month, supplying these parameters will return the **last** score generated for that specific year/month combination. If `year` and `month` are not supplied, the API defaults to the current year and current month and returns the latest score generated within the current month. # Check Worth 360 Report Generation Status Source: https://docs.worthai.com/api-reference/worth-360-report/check-worth-360-report-generation-status get /reports/businesses/{businessID}/status # Download Worth 360 Report Source: https://docs.worthai.com/api-reference/worth-360-report/download-worth-360-report post /reports/{reportID}/download # Generate Worth 360 Report Using Customer Source: https://docs.worthai.com/api-reference/worth-360-report/generate-worth-360-report-using-customer post /reports/customers/{customerID}/businesses/{businessID} # Get Worth 360 Report Details Source: https://docs.worthai.com/api-reference/worth-360-report/get-worth-360-report-details get /reports/{reportID} ### Get Report by ID This endpoint retrieves a specific report based on the provided report ID. #### Request No request body is required for this endpoint. - `reportID` (path parameter) - The ID of the report to be retrieved. #### Response The response will be a JSON object with the following schema: ``` json { "type": "object", "properties": { "status": { "type": "string" }, "message": { "type": "string" }, "data": { "type": "object", "properties": { "id": { "type": "string" }, "report_type_id": { "type": "integer" }, "status": { "type": "string" }, "log": { "type": ["string", "null"] }, "created_at": { "type": "string" }, "created_by": { "type": "string" }, "updated_at": { "type": "string" }, "triggered_by": { "type": "string" }, "triggered_id": { "type": "string" }, "report_type": { "type": "object", "properties": { "core_report_types": { "type": "object", "properties": { "id": { "type": "integer" }, "code": { "type": "string" }, "label": { "type": "string" } } } } } } } } } ``` # Add Business Source: https://docs.worthai.com/getting-started/add-business The following steps are intended to help you add a business to the customer portal. This step is needed in order to generate a business ID. This business ID will be used to make other API calls such as KYB and KYC as it serves as the unique identifier of each business that is onboarded. ## 1. *Customer Sign In* * Using your login credentials you will sign into the customer portal via the [API Customer Sign In](https://docs.worthai.com/api-reference/auth/sign-in/customer-sign-in) endpoint * Upon signing in you will get an *`id_token`* and *`customer_id`* * These two identifiers are needed to make the **Add Business** call ## 2. *Add Business* *For more information on the Add Business route, please see the [API Reference for Add Business](https://docs.worthai.com/api-reference/add-or-update-business/add-business)*. * The following three data fields are the ***MINIMUM*** requirements needed to Add a Business: 1. **Authorization**: REQUIRED * Insert the `id_token` captured from the Customer Sign In call for authentication 2. **Customer ID**: REQUIRED * Insert the `customer_id` captured from the Customer Sign In call for authentication 3. **Name**: REQUIRED * This is the name of the company that you are adding **Important Note**: while there are only three required fields for the Add Business route, the more information that is captured in the Add Business data fields, the more robust and enriched the KYB/KYC response data will be. **Required/Recommended Fields: KYB**
The following fields are ***recommended*** when making the Add Business call for **KYB**, as it will return a more robust data set:
Field Name Required / Recommended Notes
name ✅ Required Legal business name
external\_id 🔶 Recommended Internal identifier for tracking
tin (Tax ID) 🔶 Recommended Strongest match for business identity
address\_line\_1 🔶 Recommended Business street address
address\_city 🔶 Recommended City of the business
address\_state 🔶 Recommended State where business operates
address\_postal\_code 🔶 Recommended ZIP/Postal code
naics\_code or mcc\_code 🔶 Recommended Industry classification business code
year\_created 🔶 Recommended The year the company was created
annual\_total\_income 🔶 Recommended Business revenue
official\_website 🔶 Recommended Company website
**Required/Recommended Fields: KYC**
The following fields are ***recommended*** when making the Add Business call for **KYC**, as it will return a more robust data set:
Field Name Required / Recommended Notes
owner1\_first\_name 🔶 Recommended Individual’s legal first name
owner1\_last\_name 🔶 Recommended Individual’s legal last name
owner1\_mobile 🔶 Recommended Personal contact number
owner1\_email 🔶 Recommended Primary email address
owner1\_dob 🔶 Recommended Used for identity matching (encrypted)
owner1\_ssn 🔶 Recommended Encrypted — critical for verification
owner1\_address\_line\_1 🔶 Recommended Home street address
owner1\_address\_line\_2 🔶 Recommended Apartment / Suite / Unit
owner1\_address\_city 🔶 Recommended Residential city
owner1\_address\_state 🔶 Recommended Residential state
owner1\_address\_postal 🔶 Recommended ZIP code of the residential address
owner1\_title ✅ Required Insert one of the following strings: Partner, Limited Partner, Director, Chief Accounting Officer, Chief Executive Officer, Chief Operations Officer, President, Vice President, Treasurer, Assistant Treasurer, 1% Shareholder, Shareholder, Controller, Managing Member, Owner, Sole Proprietor, Executor, Beneficiary, Trustee, Administrator
owner1\_owner\_type ✅ Required Insert one of the following strings: `CONTROL` or `BENEFICIARY`
## Viewing Add Business call in your Customer Portal If you are using the Customer Portal you can validate the businesses that have been onboarded by following these two steps: **Step 1:** Once the business is added, you can log into your customer account and review the business onboarded. **Step 2:** Once logged in, on the left nav bar, click on **Businesses** and you will see the business you onboarded. * Click on “View Details” * Click on the unique “Ticket Number” * You will now see company verification details, **KYB** and other verifications and validations automatically populate into the portal from the Add Business Call # Banking Source: https://docs.worthai.com/getting-started/banking When the [GET Banking Info](https://docs.worthai.com/api-reference/integration/banking/banking-information) call is made, two background processes are triggered: **verification** and **authentication**. These work together to confirm that a bank account is real, active, and that the person or business submitting it is authorized to use it. In order to properly verify and validate banking information, a specific set of data is **_required_** to return the appropriate verifications and validations. This information is captured in the [POST Add Business](https://docs.worthai.com/api-reference/add-or-update-business/add-business) endpoint. The following data validations will highlight what information is **required** to validate and authenticate banking information. ### **Verification** Verifying a bank account is done by capturing the account number, routing number, and account type (checking or savings). This information helps confirm that the account is valid, active, and associated with an authorized user, while also identifying potential risk signals. **Route:** ```http theme={null} https://api.joinworth.com/integration/api/v1/banking/business/{businessID} ``` **Requirements:**\ The following 3 parameters are ***required*** to verify banking information: ```json theme={null} { "bank_account_number": "bank account number", "bank_routing_number": "9 digit routing number", "bank_account_subtype": "Checking" or "Savings" } ``` ### **Authentication** Authenticating the bank account is done by capturing the account number, routing number, account type (checking or savings), and either the company name **or** the account owner’s first and last name are sent. This ensures the person or entity submitting the account has the legal authority to access or transact on it. **Requirements:**\ In addition to the bank account number, routing number, and account type (checking or savings), the following is ***also required***: * **If a business account:** * `name` * **If a personal account:** * `owner1_first_name` * `owner1_last_name` ```json theme={null} { "bank_account_number": "bank account number", "bank_routing_number": "9 digit routing number", "bank_account_subtype": "Checking" or "Savings", "name": "SMITH & ASSOCIATES CONSULTING", // required if business bank account // or "owner1_first_name": "John", // required if owner bank account "owner1_last_name": "Smith" // required if owner bank account } ``` This information will allow for banking information to be **verified**. # KYB/KYC Source: https://docs.worthai.com/getting-started/kyb-kyc ## **API Steps for calling KYB/KYC** Once the Business has been added, you can make calls to the **KYB** and **KYC** endpoints to retrieve verification and validation about this business and its customers. Using the ***business ID***, you will be able to make the **GET KYB** call and **GET KYC** calls. ## KYB Retrieves comprehensive *Know Your Business* verification details for a given business identifier, including legal, formation, ownership, address, and match data from multiple sources. Prior to utilizing this service, you must first obtain a business ID by creating a business via the [Add business](/api-reference/add-or-update-business/add-business) service. **Once the business has been added**, you can make the **GET KYB** call to get verification and validation about this business. For more detailed information on using the KYB endpoint, please see the [KYB](https://docs.worthai.com/api-reference/integration/facts/kyb) API Reference Guide. ## KYC Know your Customer returns a list of individuals with ownership or control, including their submitted personal details and verification results. Prior to utilizing this service, you must first obtain a business ID by creating a business via the [Add business](/api-reference/add-or-update-business/add-business) service. **Once the business has been added**, you can make the **GET KYC** call to get verification and authorization about ownership. For more detailed information on using the KYC endpoint, please see the [KYC](https://docs.worthai.com/api-reference/integration/verification/kyc-ownership-verification) API Reference Guide. # Overview Source: https://docs.worthai.com/getting-started/overview Hello and welcome to Worth API! Here at Worth we want to ensure a seamless onboarding experience and have created this guide for you and your businesses. This guide will show you how to get started using the Worth API documentation. Should you have any questions please feel free to reach out to a Worth team member to better assist you. Thanks! ## Credentialing Please provide the following credentials to the Worth Team to create your admin account: * First Name * Last Name * Email These credentials will allow you to **send invites** to merchants and/or onboard businesses via single business onboard. > **Note:** Sending over a *service email* will also work to set up API credentialing access. ## Email Access Link You should have received an email from [no-reply@worth.com](mailto:no-reply@worth.com) with this email body requesting you to log in.
**Note**: This link will expire within 7 days of receiving this email. ## Create Login Upon clicking the link in the email, you will be prompted to **create a password**.\ These credentials will allow you access to make API calls such as [Add Business](/api-reference/add-or-update-business/add-business) and get business information such as [KYB](/api-reference/integration/facts/kyb) and [KYC](/api-reference/integration/verification/kyc-ownership-verification). ## Authentication Accessing the API relies on a username/password authentication flow. Using the [Customer Sign In](/api-reference/auth/sign-in/customer-sign-in) route, you’ll capture **3 key identifiers** that are specific to your team: the `id_token`, the `refresh_token`, and the `customerID`. * `id_token`: represents the authorization (Bearer) token for the authenticated user and their role within the Worth platform.\ *Note: for security purposes, this is a relatively short-lived token and must be refreshed programmatically.* * `refresh_token`: represents the token needed at [Customer Refresh Token](/api-reference/auth/sign-in/customer-refresh-token) when `id_token` is expired. Upon successful refresh, a new `id_token` and `refresh_token` will be returned in the response. * `customer_details.id`: represents the instance ID of the user's company where other API operations will take place. Some endpoints require this ID (referred to as `customerID`) for querying and submitting business data. ## Add Business * Adding a Business is the next critical step in getting started with the Worth API docs. * The [Add Business](/api-reference/add-or-update-business/add-business) route creates a unique business ID. This ID is used to make many of the **GET** calls listed in the documentation. * While the Add Business route only requires **four** data fields to make a successful call, it is highly recommended to add as much business and owner information to this POST call to capture robust KYB and KYC information. * More information about required and recommended data fields can be found in the **API reference** tab. ## Responses * **The FINAL STEP!** Once you have added a business, it’s time to pull back the data! * It’s important to note that **GET** responses associated with business information will require a `businessID` in the endpoint URL. This `businessID` is generated via the Add Business endpoint. Once this initial step is complete, you will be able to make several **GET** calls to retrieve cases, business details, and reports. # Introduction Source: https://docs.worthai.com/introduction Welcome to the official API documentation for Worth! This documentation serves as a comprehensive guide to help you understand and integrate with our API effectively. ## Purpose This API documentation is designed to: * Guide a new user on Getting Started with Worth API * Provide detailed information about endpoints, request parameters, and response formats. * Offer examples and code snippets to assist with API integration. * Explain authentication and authorization mechanisms required for accessing the API. * Outline best practices and guidelines for using our API securely and efficiently. * Serve as a reference for financial institutes using applications that interact with Worth. ## Getting Started If you're new to Worth API, we recommend following the [Getting Started](https://docs.worthai.com/getting-started) guide for step-by-step instructions on adding a business and retrieving KYB, KYC, and Banking data. ## Feedback and Support We value your feedback! If you have any questions, suggestions, or encounter any issues while using Worth API, please don't hesitate to [contact us](mailto:support@joinworth.com). ## Explore Start exploring the API documentation by navigating to the [API Reference](https://docs.worthai.com/api-reference/auth/sign-in/customer-sign-in) or using the search functionality to find specific endpoints or topics. Thank you for choosing Worth API. We hope you find this documentation helpful! # Sample API Onboarding Flow Overview Source: https://docs.worthai.com/onboarding-sdk-2/api-overview Complete guide to the business invitation and onboarding process This API Onboarding Flow guides you through the complete process of inviting a business to your platform and adding owner details. This flow consists of two sequential API calls that handle business invitation, business verification, and owner prefill details addition. ## Important information This flow is provided as an example use case of the SDK. It may be different depending on your integration requests with Worth services. ## Quick Overview The business onboarding process follows a linear sequence of API calls: ```mermaid theme={null} flowchart TD A[Customer Sign In] --> B[Add Business] B --> C[Initialize SDK] ``` **Flow Steps**: 1. **Customer Sign In** (POST) - Returns customer id\_token 2. **Add Business** (POST) - Creates business and case data 3. **Initialize SDK** ## Next Steps * View the [Detailed Sequence Diagram](/onboarding-sdk-2/api-sequence-diagram) to see the complete interaction flow between services * Read the [Step-by-Step Breakdown](/onboarding-sdk-2/api-step-by-step-breakdown) for detailed information about each endpoint * Review the [API Reference](/onboarding-sdk-2/api-reference) for complete endpoint documentation ## Related Documentation * Check the [Getting Started](/getting-started/overview) guide for key concepts * Explore [Business Onboarding Flows](/use-cases/onboarding/overview) for additional use cases # API Reference Source: https://docs.worthai.com/onboarding-sdk-2/api-reference ## createOnboardingApp API reference for all Onboarding SDK methods, types, and options. ### Import ```typescript theme={null} import { createOnboardingApp } from '@worthai/onboarding-sdk'; ``` ### Parameters The function accepts a single argument object with the following properties: | Property | Type | Description | | - | - | - | | `origin` | `string` | The origin URL of the onboarding app | | `inviteToken` | `string` | The invite token used to authenticate and initialize the onboarding session | | `mode?` | `'embedded' \| 'non-embedded' \| undefined` | The iframe mode. When set to `'embedded'`, the iframe is embedded in the parent site. When `'non-embedded'` or `undefined`, the iframe operates in standalone mode | | `loadingTimeout?` | `number` | Loading timeout in milliseconds. The minimum allowed value is 15000 ms | ### Example ```typescript theme={null} import { createOnboardingApp } from '@joinworth/onboarding-sdk'; const onboardingApp = createOnboardingApp({ origin: '{{WORTH_ONBOARDING_APP_DOMAIN}}', inviteToken: '{{YOUR_INVITE_TOKEN}}', mode: 'embedded', }); ``` ### Returned Methods The `createOnboardingApp` function returns an object with the following methods and properties: #### `subscribe(callback)` Subscribes to messages from the Worth Onboarding App. Returns a subscription object with an `unsubscribe` method. **Parameters:** * `callback: (event: MessageEvent) => void` - A callback function that receives message events from the Worth Onboarding App **Returns:** * `{ unsubscribe: () => void }` - A subscription object with an `unsubscribe` method to stop listening to messages **Example:** ```typescript theme={null} const subscription = onboardingApp.subscribe((event) => { if (event.data.type === 'ROUTE_URL') { console.log('Current route:', event.data.payload.url); } }); // Clean up when done subscription.unsubscribe(); ``` **Message Types Received:** * `ROUTE_URL` - Notifies when the route changes in the onboarding app * `IFRAME_RESIZE` - Notifies when the iframe needs to resize (includes height) * `IFRAME_INITIALIZED` - Notifies when the iframe has finished initializing * `ONBOARDING_STARTED` - Signals that the onboarding flow is ready; the parent clears the loading state and the SDK initializes the detached iframe. * `STAGE_NAVIGATION` - Updates as the user moves through stage. With this event that the parent receives it, updates navigation, and re-renders the buttons and labels accordingly. See more details about [how this message type is handled](#handling-stage_navigation-message-type). * `LOADING_TIMED_OUT` - Fired when the onboarding app does not load within the configured time limit. This event requires the `loadingTimeout` option to be set when creating the `createOnboardingApp` instance. Fallback event to hide loading state. * `RESTARTING` - Fired when the onboarding app is restarted after `LOADING_TIMED_OUT`. * `AUTHENTICATION_STATUS` - Notifies when the onboarding app's `isAuthenticated` state changes. * `ONBOARDING_COMPLETED` - Fired when the full onboarding is submitted. * `ERROR` - Handles ERROR events from the onboarding SDK subscription. See more details about [how this message type is handled](#handling-error-message-type). *** #### Handling STAGE\_NAVIGATION message type Drives navigation actions, and the SDK app responds with the new navigation state and stage metadata. ```typescript theme={null} // Object definition export type StageNavigation = { isInitialStage: boolean; isLastStage: boolean; stage: string | undefined; nextStatus: { visible: boolean; disabled: boolean; loading: boolean; isSubmit: boolean; }; prevStatus: { visible: boolean; disabled: boolean; loading: boolean }; skipStatus: { visible: boolean; disabled: boolean; loading: boolean }; }; ``` ##### Field‑by‑field semantics * ***isInitialStage:*** true when the current stage is the very first step of the flow. The parent uses this to decide that “Back” should leave the flow entirely instead of going to a previous stage. * ***isLastStage:*** true when the current stage is the final step. The parent uses this to change both behavior (navigate to a “completed” route instead of NEXT\_STAGE) and label (“Complete” vs “Next”). * ***stage:*** A logical identifier for the current stage (e.g. "personal-info", "documents", etc.). In your parent UI it’s currently just displayed for observability / debugging. * ***nextStatus:*** controls the Next/Complete button * ***visible:*** whether the Next/Complete button should be rendered at all. * ***disabled:*** whether the button is clickable (e.g. when validation not satisfied). * ***loading:*** whether the action is in progress (you could map this to a spinner on the button if desired). * ***isSubmit:*** the child is telling you “this click actually submits data / form”, even if it’s not the very last stage. You could use this to show different copy or confirmation. * ***prevStatus:*** controls the Back button Same idea: visible, disabled, loading communicate whether Back should be shown and usable. * ***skipStatus:*** controls the Skip button Same structure:\*\*\* visible, disabled, loading, telling you whether skipping is allowed on this particular stage. **Example:** How the parent consumes STAGE\_NAVIGATION. The parent subscribes to SDK events and stores stageNavigation into local state: ```typescript theme={null} // Get Button Inner Elements const prevButton = document.getElementById('prev-btn'); const skipButton = document.getElementById('skip-btn'); const nextButton = document.getElementById('next-btn'); // Listen for onboarding messages const subscription = onboardingApp.subscribe((event) => { if (event.data.type === 'STAGE_NAVIGATION') { console.log('Current stage:', event.data.payload.stageNavigation); const stageNavigation = event.data.payload.stageNavigation; // Set prev button disabled state based on stageNavigation event if (prevButton) { prevButton.disabled = stageNavigation.prevStatus.disabled; } // Set skip button disabled state based on stageNavigation event if (skipButton) { skipButton.disabled = stageNavigation.skipStatus.disabled; } // Set next button disabled state based on stageNavigation event if (nextButton) { nextButton.disabled = stageNavigation.nextStatus.disabled; } } }); // Get the current stage navigation const navigation = onboardingApp.navigation(); /** Prev button handler **/ // That navigation object (of type StageNavigation) // then directly drives your buttons: prevButton?.addEventListener('click', () => { if (navigation?.isInitialStage) { // HERE: implement code to back to home or previous page window.location.href = '/'; } else { onboardingApp.prev(); } }); /** Skip button handler **/ skipButton?.addEventListener('click', () => { onboardingApp.skip(); }); /** Next button handler **/ nextButton?.addEventListener('click', () => { if (navigation?.isLastStage) { // HERE: implement code to navigate into onboarding-completed page // or custom redirection window.location.href = '../onboarding-completed'; } else { onboardingApp.next(); } }); ``` *** #### Handling ERROR message type Extracts the error message and displays it via notification UI component. ```typescript theme={null} // Listen for onboarding messages const subscription = onboardingApp.subscribe((event) => { if (event.data.type === 'ERROR') { const message = event.data.payload.error.message; // Show error message into your Notification UI Component alert(`Error Title: ${message}`); } }); ``` *** #### `setMode(mode)` Sets the iframe mode to control how the onboarding app is displayed. Sends a `SET_IFRAME_MODE` message to the Worth Onboarding App. **Parameters:** * `mode: 'embedded' | 'non-embedded' | undefined` - The mode to set * `'embedded'` - The iframe is embedded within the parent site's layout * `'non-embedded'` - The iframe is displayed in standalone mode * `undefined` - Uses as default `non-embedded` mode **Returns:** `void` **Example:** ```typescript theme={null} // Switch to embedded mode onboardingApp.setMode('embedded'); // Switch to non-embedded mode onboardingApp.setMode('non-embedded'); // Toggle mode based on checkbox const modeToggle = document.getElementById('mode-toggle'); modeToggle?.addEventListener('change', (event) => { const isEmbedded = (event.target as HTMLInputElement).checked; onboardingApp.setMode(isEmbedded ? 'embedded' : 'non-embedded'); }); ``` *** #### `next()` Navigates the onboarding app to the next stage. Sends a `NEXT_STAGE` message to the Worth Onboarding App. **Parameters:** None **Returns:** `void` **Example:** ```typescript theme={null} const nextButton = document.getElementById('next-btn'); nextButton?.addEventListener('click', () => { onboardingApp.next(); }); ``` *** #### `prev()` Navigates the onboarding app to the previous stage. Sends a `PREV_STAGE` message to the Worth Onboarding App. **Parameters:** None **Returns:** `void` **Example:** ```typescript theme={null} const prevButton = document.getElementById('prev-btn'); prevButton?.addEventListener('click', () => { onboardingApp.prev(); }); ``` #### `skip()` Skips the current onboarding app stage. Sends a `SKIP_STAGE` message to the Worth Onboarding App. **Parameters:** None **Returns:** `void` **Example:** ```typescript theme={null} const prevButton = document.getElementById('prev-btn'); prevButton?.addEventListener('click', () => { onboardingApp.prev(); }); ``` *** #### `setCustomCss(css)` Injects custom CSS styles into the Worth Onboarding App iframe. Sends a `SET_CUSTOM_CSS` message to the Worth Onboarding App. **Parameters:** * `css: string` - A string containing CSS rules to apply to the Worth Onboarding App **Returns:** `void` **Example:** ```typescript theme={null} // Apply custom background color onboardingApp.setCustomCss('body { background: #f0f0f0; }'); // Apply multiple styles onboardingApp.setCustomCss(` body { background: #ffffff; font-family: 'Custom Font', sans-serif; } .onboarding-container { padding: 20px; border-radius: 8px; } `); // Dynamic CSS based on user preference const themeToggle = document.getElementById('theme-toggle'); themeToggle?.addEventListener('change', (event) => { const isDark = (event.target as HTMLInputElement).checked; onboardingApp.setCustomCss( isDark ? 'body { background: #1a1a1a; color: #ffffff; }' : 'body { background: #ffffff; color: #000000; }', ); }); ``` *** #### `refreshSize()` Requests the Worth Onboarding App to recalculate and report its size. This is useful when the iframe content changes dynamically. Sends a `REFRESH_SIZE` message to the Worth Onboarding App. **Parameters:** None **Returns:** `void` **Example:** ```typescript theme={null} // Refresh size after content changes onboardingApp.refreshSize(); // Refresh size on window resize window.addEventListener('resize', () => { onboardingApp.refreshSize(); }); // Refresh size on button click const refreshButton = document.getElementById('refresh-size-btn'); refreshButton?.addEventListener('click', () => { onboardingApp.refreshSize(); }); ``` *** #### `iframe` A read-only property that contains the Worth Onboarding App. This is the actual iframe DOM element that should be appended to your page. **Type:** `HTMLIFrameElement` **Example:** ```typescript theme={null} // Append iframe to container const container = document.getElementById('onboarding-container'); if (container) { container.appendChild(onboardingApp.iframe); } // Example of creating and appending in vanilla TypeScript function setupOnboarding() { const onboardingApp = createOnboardingApp({ origin: '{{WORTH_ONBOARDING_APP_DOMAIN}}', inviteToken: 'YOUR_TOKEN', }); const container = document.getElementById('onboarding-container'); if (container) { container.appendChild(onboardingApp.iframe); } } // Call setup function during your app's initialization setupOnboarding(); ``` # Sample Implementation API - Detailed Sequence Diagram Source: https://docs.worthai.com/onboarding-sdk-2/api-sequence-diagram Complete sequence diagram showing all API interactions in the onboarding flow This diagram shows the complete sequence of API calls required for the business onboarding process, from sending business invite through to adding owners. ```mermaid theme={null} sequenceDiagram participant Customer API as Customer Backend participant WorthAPI as Worth API Note over Customer Backend,WorthAPI: Step 1: Customer Sign In Customer Backend->>+WorthAPI: POST /auth/api/v1/customer/sign-in Note right of Customer Backend: Request: email, password WorthAPI-->>-Customer Backend: Response: data.id_token, data.customer_details.id Note over Customer Backend,WorthAPI: Step 2: Add Business Customer Backend->>+WorthAPI: POST /case/api/v1/businesses/customers/{customerID} Note right of Customer Backend: Request: business data
Auth: customer_token (id_token) WorthAPI-->>-Customer Backend: Response: business_id, business details Note over Customer Backend,SDK: Step 3: Initialize SDK Customer Backend->>+SDK: SDK instance Note right of Customer Backend: Request: invite_token extracted from step 2. ``` ## Understanding the Diagram This sequence diagram illustrates: * **Customer API**: The parent site application that displays the onboarding UI * **Worth SDK**: The SDK layer that handles API calls to Worth API for subsequent steps * **Worth API**: The underlying API services (does not need to specify individual microservices like "Auth Service" or "Case Service") ## Key Points * **Step 1: Customer Sign In (POST)**: * Signs in a customer. * Provides the customer id\_token. * **Step 2: Add Business (POST)**: * Creates business and case information. * It uses the `customer_token` for authentication. * Returns `invitation_url` for the iframe to render. * **Step 3: Initialize SDK**: * It uses the invite\_token obtained from Step 2. ## Related Documentation * [Overview](/onboarding-sdk-2/overview) - Return to the flow overview * [Step-by-Step Breakdown](/onboarding-sdk-2/api-step-by-step-breakdown) - Detailed endpoint information * [API Reference](/onboarding-sdk-2/api-reference) - Complete endpoint documentation # Sample Implementation API - Step by step breakdown Source: https://docs.worthai.com/onboarding-sdk-2/api-step-by-step-breakdown Detailed breakdown of each step in the API onboarding flow This page provides detailed information about each step in the business onboarding flow, including endpoint paths, key parameters, and links to the complete API reference documentation. ## Step 1: Customer Sign-In Authenticate the customer using username (email) and password to obtain the customer token. **Authentication**: None (public endpoint) **Example Request**: ``` POST /auth/api/v1/customer/sign-in ``` **Example Request Body**: ```json theme={null} { "email": "customer@joinworth.com", "password": "12345" } ``` **Response includes**: * `id_token`: Token used for secure API communication (recommended for all API calls) * `customer_details`: Object containing customer information * `id`: The unique identifier of the customer (customerID) > **Important**: Always use the `id_token` (also referred to as `customer_token`) for secure API communication in subsequent steps. > **API Reference**: [Customer Sign In](/api-reference/auth/sign-in/customer-sign-in) ## Step 2: Add Business This service creates the business, the case and a applicant invite link and returns it on the api response if `generate_invite_link` is true. **Example Request**: ``` POST /case/api/v1/businesses/customers/:customerID ``` ### Important fields * `external_id`: This field is the parent site identifier for this business. * `name`: Business name. * `address_`: This ones are related to the business address. * `tin`: Business Tax Identification Number. * `owner_`: This fields are related to the business owner information, that will be autopopulated. * `applicant_`: This fields are related to the applicant that will be linked to the invite. * `applicant_subrole_code`: This field needs to be "owner" in lowercase for the platform to work. * `generate_invite_link`: This field needs to be true so we receive the invite link as part of the API response. ### Example Request Body ```json theme={null} { "external_id": "external-sdk-business", "name": "SDK Business One", "address_line_1": "601-7 Sansburys Way", "address_city": "West Palm Beach", "address_state": "FL", "address_postal_code": "33411", "tin": "942404110", "owner1_first_name": "Leslie", "owner1_last_name": "Knope", "owner1_email": "leslie.knope@joinworth.com", "owner1_mobile": "+12055551212", "owner1_ssn": "123456788", "owner1_dob": "1975-01-18", "owner1_address_line_1": "123 Main St.", "owner1_address_city": "Pawnee", "owner1_address_state": "IN", "owner1_address_postal": "46001", "owner1_address_country": "US", "owner1_title": "1% Shareholder", "owner1_owner_type": "CONTROL", "owner1_ownership_percentage": 100, "applicant_first_name": "Frank", "applicant_last_name": "Swarz", "applicant_email": "frank.swarz@joinworth.com", "applicant_subrole_code": "owner", "generate_invite_link": true } ``` ### Response The response includes: * `invitation_url`: The customer bearer token needed for the iframe initialization. This is part of the "applicant" object inside data\[0]. > **Note**: This documentation shows only the fields needed to onboard a user using the SDK. > For the complete API reference with all available fields, see [Add Business](/api-reference/add-or-update-business/add-business). ## Related Documentation * [Overview](/onboarding-sdk-2/overview) - Return to the flow overview * [Detailed Sequence Diagram](/onboarding-sdk-2/api-sequence-diagram) - Visual representation of the flow * [API Reference](/onboarding-sdk-2/api-reference) - Complete endpoint documentation # API Error Handling - Add Business Service Source: https://docs.worthai.com/onboarding-sdk-2/errors/add-business Complete guide to handling errors for the POST /businesses/customers/:customerID endpoint ## Endpoint ``` POST /api/v1/businesses/customers/:customerID ``` ## Overview This document provides comprehensive error handling guidance for external developers integrating with the Add Business API endpoint. This endpoint allows you to add a new business to a customer's account. Each error scenario includes classification, sample responses, and actionable recommendations for handling the error in your application. ## Error Types The endpoint can return errors classified into four main categories: * **Validation Error**: Request format, schema, or data validation issues * **Network Error**: HTTP method or connectivity issues * **Authentication Error**: Authentication, authorization, or permission issues * **Internal Server Error**: Server-side failures requiring retry logic ## Error Index Quick navigation to specific error scenarios: 1. [Validation Error (Request Body Schema)](#1-validation-error-request-body-schema) 2. [Method Not Allowed Error](#2-method-not-allowed-error) 3. [Authentication Error (Missing or Invalid Token)](#3-authentication-error-missing-or-invalid-token) 4. [Authorization Error (Role Not Allowed)](#4-authorization-error-role-not-allowed) 5. [Feature Flag Not Enabled](#5-feature-flag-not-enabled) 6. [Onboarding Limit Exhausted](#6-onboarding-limit-exhausted) 7. [Onboarding Limit Will Be Exceeded](#7-onboarding-limit-will-be-exceeded) 8. [Data Permission Error](#8-data-permission-error) 9. [Business Processing Error (Mapper Error)](#9-business-processing-error-mapper-error) 10. [Business Not Found Error](#10-business-not-found-error) *** ## 1. Validation Error (Request Body Schema) ### Scenario Request body does not match the required schema for adding a business. ### When It Happens * Missing required fields (e.g., `name`) * Invalid field types (e.g., `customerID` is not a valid UUID, `tin` format is invalid) * Invalid field formats (e.g., `applicant_email` is not a valid email format, `mobile` is not a valid phone number) * Invalid UUID format for `customerID` in URL path * Invalid query parameters * Extra fields that are not allowed ### Classification **Validation Error** ### Error Details * **Error Class**: `ValidationMiddlewareError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Validation error message from schema", "errorCode": "INVALID", "data": { "errorName": "ValidationMiddlewareError" } } ``` ### Example Scenarios * Missing `name`: `{ "external_id": "ext-123" }` * Invalid `customerID` UUID: `POST /api/v1/businesses/customers/invalid-uuid` * Invalid `tin` format: `{ "external_id": "ext-123", "name": "Business", "tin": "invalid" }` * Invalid email format: `{ "external_id": "ext-123", "name": "Business", "applicant_email": "not-an-email" }` ### How to Handle 1. **Validate input before sending the request**: Implement client-side validation to ensure all required fields are present and properly formatted before making the API call. 2. **Ensure proper request format**: Verify that your request body matches the expected schema: * `name`: Must be a non-empty string (required) * `external_id`: Must be a non-empty string * `customerID`: Must be a valid UUID in the URL path * `tin`: Must match valid TIN formats (9 digits, UK formats, etc.) * Optional fields must match their expected types 3. **Do not retry automatically**: This is a client-side error that requires user action. Wait for the user to correct the input before attempting the request again. *** ## 2. Method Not Allowed Error ### Scenario Request uses an HTTP method other than POST (e.g., GET, PUT, DELETE, PATCH). ### When It Happens * Client sends GET request to `/businesses/customers/:customerID` * Client sends PUT/DELETE/PATCH request to this endpoint * Any non-POST request to this endpoint ### Classification **Network Error** (HTTP method mismatch) ### Error Details * **Error Class**: `MethodNotAllowedError` * **HTTP Status**: `405 Method Not Allowed` * **Error Code**: `NOT_ALLOWED` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Method Not Allowed", "errorCode": "NOT_ALLOWED", "data": { "errorName": "MethodNotAllowedError" } } ``` ### How to Handle 1. **Verify HTTP method**: Ensure you are using the `POST` method for this endpoint. This is a configuration issue in your HTTP client code. 2. **Check your API client setup**: Review your HTTP client configuration (fetch, axios, etc.) to ensure the correct method is being used. 3. **No retry needed**: This is a permanent error that indicates incorrect API usage. Fix the HTTP method in your code and the request will succeed. 4. **Update your integration**: If you're using a generated API client or SDK, ensure it's up to date with the latest API specification. *** ## 3. Authentication Error (Missing or Invalid Token) ### Scenario Request is missing the Authorization header or the token is invalid, expired, or malformed. ### When It Happens * Missing `Authorization` header * Authorization header does not start with "Bearer" * Token is expired * Token is invalid or malformed * Token verification fails ### Classification **Authentication Error** ### Error Details * **Error Class**: `AuthenticationMiddlewareError` or token verification error * **HTTP Status**: `401 Unauthorized` or `400 Bad Request` * **Error Code**: `UNAUTHENTICATED` or `INVALID` * **Message**: Varies based on the specific error ### Sample API Response **Missing Authorization Header:** ```json theme={null} { "status": "fail", "message": "Authorization header not present", "errorCode": "UNAUTHENTICATED", "data": { "errorName": "AuthenticationMiddlewareError" } } ``` **Invalid Authorization Header Format:** ```json theme={null} { "status": "fail", "message": "Invalid Authorization header type", "errorCode": "INVALID", "data": { "errorName": "AuthenticationMiddlewareError" } } ``` **Expired Token:** ```json theme={null} { "status": "fail", "message": "User Session Expired", "errorCode": "UNAUTHENTICATED", "data": { "errorName": "TokenExpiredError" } } ``` ### How to Handle 1. **Check Authorization header**: Ensure your request includes a valid `Authorization` header in the format: `Authorization: Bearer ` 2. **Handle token expiration**: If you receive a "User Session Expired" error, you need to: * Refresh the user's authentication token * Retry the request with the new token * If token refresh fails, redirect the user to re-authenticate 3. **Do not retry with the same token**: If the token is invalid or expired, do not automatically retry with the same token. You must obtain a new valid token first. 4. **Implement token refresh logic**: Implement automatic token refresh when you detect token expiration errors, then retry the original request. 5. **Handle gracefully**: If authentication fails, redirect the user to your login page or show an appropriate error message. *** ## 4. Authorization Error (Role Not Allowed) ### Scenario The authenticated user does not have the required role (ADMIN or CUSTOMER) to access this endpoint. ### When It Happens * User has APPLICANT role (not allowed) * User has a role that is not ADMIN or CUSTOMER * Role information is missing or invalid ### Classification **Authentication Error** ### Error Details * **Error Class**: `RoleMiddlewareError` * **HTTP Status**: `401 Unauthorized` * **Error Code**: `UNAUTHORIZED` * **Message**: `"Role Not Allowed"` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Role Not Allowed", "errorCode": "UNAUTHORIZED", "data": { "errorName": "RoleMiddlewareError" } } ``` ### How to Handle 1. **Verify user permissions**: Ensure the user making the request has ADMIN or CUSTOMER role. This endpoint is not available for APPLICANT role users. 2. **Do not retry**: This is a permanent authorization issue. The user's role cannot be changed by retrying the request. 3. **Show appropriate message**: Display a message to the user indicating they do not have permission to perform this action. 4. **Redirect if needed**: If your application has role-based UI, redirect the user to an appropriate page or show a "permission denied" message. *** ## 5. Feature Flag Not Enabled ### Scenario The feature flag `PAT_120_ADD_BUSINESS` is not enabled for the user or environment. ### When It Happens * Feature flag is disabled for the current user * Feature flag is disabled for the environment * Feature flag service is unavailable ### Classification **Authentication Error** (Feature access restriction) ### Error Details * **HTTP Status**: `405 Method Not Allowed` * **Error Code**: `NOT_ALLOWED` * **Message**: `"This feature has not been enabled."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "This feature has not been enabled.", "erroCode": "NOT_ALLOWED", "data": {} } ``` ### How to Handle 1. **Do not retry**: This error indicates the feature is not available. Retrying will not resolve the issue. 2. **Contact support**: If you believe this feature should be enabled, contact support to verify feature flag configuration. 3. **Check feature availability**: If your application checks feature availability before showing UI elements, ensure this check is performed before allowing users to attempt this action. *** ## 6. Onboarding Limit Exhausted ### Scenario The customer has reached their monthly onboarding limit and cannot add more businesses. ### When It Happens * Customer has already added the maximum number of businesses allowed for the current month * Monthly onboarding limit has been exhausted * Feature flag for monthly onboarding limit is enabled and limit is reached ### Classification **Authentication Error** (Resource limit restriction) ### Error Details * **Error Class**: `OnboardingLimitError` * **HTTP Status**: `403 Forbidden` * **Error Code**: `NOT_ALLOWED` * **Message**: `"Monthly onboarding limit exhausted."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Monthly onboarding limit exhausted.", "errorCode": "NOT_ALLOWED", "data": { "errorName": "OnboardingLimitError" } } ``` ### How to Handle 1. **Display the error message**: Show the error message clearly to the user, explaining that they have reached their monthly limit. 2. **Do not retry**: This error will persist until the next billing cycle or until the limit is increased. Automatic retries are not useful. 3. **Provide next steps**: Inform the user about: * When the limit will reset (typically at the start of the next month) * How to contact support to increase their limit * Alternative options if available 4. **Prevent future attempts**: Consider disabling the "Add Business" functionality in your UI when this error is encountered, or show a clear message about the limit. 5. **Contact support**: Provide a way for users to contact support if they need to increase their limit. *** ## 7. Onboarding Limit Will Be Exceeded ### Scenario Adding the requested number of businesses would exceed the customer's monthly onboarding limit. ### When It Happens * Customer is attempting to add businesses that would exceed their remaining monthly limit * The sum of existing businesses plus new businesses exceeds the limit ### Classification **Validation Error** (Business logic validation) ### Error Details * **Error Class**: `OnboardingLimitError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Onboarding limit will be reached, check remaining limit count."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Onboarding limit will be reached, check remaining limit count.", "errorCode": "INVALID", "data": { "errorName": "OnboardingLimitError" } } ``` ### How to Handle 1. **Display the error message**: Show the error message to the user, indicating that adding this many businesses would exceed their limit. 2. **Calculate remaining capacity**: If possible, calculate and display how many businesses the user can still add this month. 3. **Suggest alternatives**: Offer the user options such as: * Adding fewer businesses now * Waiting until the next billing cycle * Contacting support to increase their limit 4. **Do not retry automatically**: This requires user action to either reduce the number of businesses or wait for limit reset. *** ## 8. Data Permission Error ### Scenario The authenticated CUSTOMER user is attempting to access data (customerID) that does not belong to them. ### When It Happens * CUSTOMER role user tries to add a business to a different customer's account * The `customerID` in the URL path does not match the authenticated user's `customer_id` * Data permission validation fails ### Classification **Authentication Error** (Data access restriction) ### Error Details * **Error Class**: `AccessMiddlewareError` * **HTTP Status**: `403 Forbidden` * **Error Code**: `UNAUTHORIZED` * **Message**: `"You are not allowed to access the data."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "You are not allowed to access the data.", "errorCode": "UNAUTHORIZED", "data": { "errorName": "AccessMiddlewareError" } } ``` ### How to Handle 1. **Verify customer ID**: Ensure you are using the correct `customerID` in the URL path that matches the authenticated user's customer. 2. **Do not retry**: This is a permanent authorization issue. The user cannot access data that doesn't belong to them. 3. **Show appropriate message**: Display a message indicating the user does not have permission to access this data. 4. **Fix the request**: If this is a bug in your application, correct the `customerID` being sent in the request. 5. **Handle gracefully**: Redirect the user to their own data or show a "permission denied" message. *** ## 9. Business Processing Error (Mapper Error) ### Scenario Business data validation fails during processing, such as invalid field values, missing required data, or business logic violations. ### When It Happens * Invalid phone number format * Invalid owner data (e.g., ownership percentages don't add up to 100%, missing control owner) * Duplicate external ID for the customer * Invalid business ID provided when it shouldn't be * Missing required applicant information * Invalid address data * Other business-specific validation failures ### Classification **Validation Error** (Business logic validation) ### Error Details * **Error Class**: `MapperError` or `BusinessApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: Varies based on the specific validation failure ### Sample API Response **Duplicate External ID:** ```json theme={null} { "status": "fail", "message": "Bulk process had errors", "errorCode": null, "data": { "runId": "e49f04e9-c82b-454b-b6b7-cde0325b825a", "failed_rows": { "0": { "message": "Validation failed. Error details:", "data": [ { "column": "external_id", "providedKey": "external_id", "value": "test-external-id", "reason": "The business external ID already exists for this customer (business ID: 9d75fc32-6770-4586-8dd6-9a9a0b6596b2)", "existing_business_id": "9d75fc32-6770-4586-8dd6-9a9a0b6596b2" } ] } }, "result": {} } } ``` **Invalid Ownership:** ```json theme={null} { "status": "fail", "message": "Bulk process had errors", "errorCode": null, "data": { "runId": "fbd78c5b-1c79-4035-a63b-2d091142da78", "failed_rows": { "0": { "message": "Validation failed. Error details:", "data": [ { "column": "owner1_ownership_percentage", "providedKey": "owner1_ownership_percentage", "value": 104, "reason": "Owner1 Ownership Percentage must be a number between 0 and 100." } ] } }, "result": {} } } ``` ### How to Handle 1. **Parse error details**: The error response includes specific field information (`providedKey`, `column`, `value`, `description`) that you can use to highlight the problematic field in your UI. 2. **Display field-specific errors**: Show the error message next to or below the specific field that failed validation. 3. **Fix and retry**: After the user corrects the data, allow them to retry the request. Do not auto-retry without user action. 4. **Validate client-side**: Implement client-side validation for common issues (phone number format, ownership percentages, etc.) to catch errors before sending the request. 5. **Handle bulk errors**: If processing multiple businesses, the response may include a `failed_rows` object with errors for specific rows. Display these errors appropriately in your UI. *** ## 10. Business Not Found Error ### Scenario A referenced business, applicant, or related entity cannot be found in the system. ### When It Happens * Referenced `applicant_id` does not exist * Referenced `businessID` in query parameters does not exist * Business referenced in update operations does not exist ### Classification **Validation Error** (Resource not found) ### Error Details * **Error Class**: `BusinessApiError` * **HTTP Status**: `404 Not Found` * **Error Code**: `NOT_FOUND` * **Message**: Varies (e.g., "Business not found", "Applicant details not found") ### Sample API Response ```json theme={null} { "status": "fail", "message": "Business not found", "errorCode": "NOT_FOUND", "data": { "errorName": "BusinessApiError" } } ``` ### How to Handle 1. **Verify referenced IDs**: Ensure all referenced IDs (applicant\_id, businessID, etc.) exist and are valid before making the request. 2. **Display error message**: Show the error message to the user, indicating which resource was not found. 3. **Allow user to correct**: Provide a way for the user to select a valid resource or enter the correct ID. 4. **Do not retry automatically**: This error requires user action to provide valid resource references. *** # API Error Handling - Sign In Service Source: https://docs.worthai.com/onboarding-sdk-2/errors/sign-in ``` POST /api/v1/customer/sign-in ``` ## Overview This document provides comprehensive error handling guidance for external developers integrating with the Customer Sign-In API endpoint. Each error scenario includes classification, sample responses, and actionable recommendations for handling the error in your application. ```bash theme={null} curl -X POST https://api.dev.joinworth.com/customer/sign-in \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "password": "userpassword123" }' ``` ## Error Types The endpoint can return errors classified into four main categories: * **Validation Error**: Request format or schema issues * **Network Error**: HTTP method or connectivity issues * **Authentication Error**: User account or credential issues * **Internal Server Error**: Server-side failures requiring retry logic *** ## Error Index Quick navigation to specific error scenarios: 1. [Validation Error (Request Body Schema)](#1-validation-error-request-body-schema) 2. [Method Not Allowed Error](#2-method-not-allowed-error) 3. [User not found / Incorrect credentials](#3-user-not-found-/-incorrect-credentials) 4. [Account Disabled / Inactive](#4-account-disabled-/-inactive) 5. [Invalid User Status (Not Active/Inactive)](#5-invalid-user-status-not-active/inactive) 6. [Incomplete Account Setup](#6-incomplete-account-setup) *** ## 1. Validation Error (Request Body Schema) ### Scenario Request body does not match the required schema (`Auth.SignIn.SignInWithPasswordRequestSchema`). ### When It Happens * Missing required fields (e.g., `email` or `password`) * Invalid field types (e.g., `email` is not a string, `password` is not a string) * Invalid field formats (e.g., `email` is not a valid email format) * Extra fields that are not allowed ### Classification **Validation Error** ### Error Details * **Error Class**: `ValidationMiddlewareError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Validation error message from schema", "errorCode": "INVALID", "data": { "errorName": "ValidationMiddlewareError" } } ``` ### Example Scenarios * Missing email: `{ "password": "password123" }` * Missing password: `{ "email": "user@example.com" }` * Invalid email format: `{ "email": "not-an-email", "password": "password123" }` * Empty body: `{}` ### How to Handle 1. **Validate input before sending the request**: Implement client-side validation to ensure all required fields (`email` and `password`) are present and properly formatted before making the API call. 2. **Ensure proper request format**: Verify that your request body matches the expected schema: * `email`: Must be a valid email address string * `password`: Must be a non-empty string * Remove any extra fields that are not part of the schema *** ## 2. Method Not Allowed Error ### Scenario Request uses an HTTP method other than POST (e.g., GET, PUT, DELETE, PATCH). ### When It Happens * Client sends GET request to `/customer/sign-in` * Client sends PUT/DELETE/PATCH request to `/customer/sign-in` * Any non-POST request to this endpoint ### Classification **Network Error** (HTTP method mismatch) ### Error Details * **Error Class**: `MethodNotAllowedError` * **HTTP Status**: `405 Method Not Allowed` * **Error Code**: `NOT_ALLOWED` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Method Not Allowed", "errorCode": "NOT_ALLOWED", "data": { "errorName": "MethodNotAllowedError" } } ``` ### How to Handle 1. **Verify HTTP method**: Ensure you are using the `POST` method for this endpoint. This is a configuration issue in your HTTP client code. 2. **Check your API client setup**: Review your HTTP client configuration (fetch, axios, etc.) to ensure the correct method is being used. 3. **No retry needed**: This is a permanent error that indicates incorrect API usage. Fix the HTTP method in your code and the request will succeed. 4. **Update your integration**: If you're using a generated API client or SDK, ensure it's up to date with the latest API specification. *** ## 3. User Not Found / Incorrect Credentials ### Scenario User with the provided email does not exist in the database, OR email exists but password is incorrect. ### When It Happens * Email does not exist for CUSTOMER role * Email exists but password is incorrect * User exists but does not have CUSTOMER role assigned ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Incorrect username or password."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Incorrect username or password.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Do not auto-retry**: This error requires user action (correcting credentials), so do not automatically retry the request. 2. **Implement rate limiting on your side**: To prevent brute force attacks, consider limiting the number of failed sign-in attempts from your application before requiring additional verification. 3. **Handle gracefully**: Since this is a common user error, ensure your UI handles it gracefully without causing frustration. Consider showing helpful hints like "Check your email and password" or "Make sure Caps Lock is off". 4. **Do not store credentials**: Never log or store the user's password in any form, even in error logs. *** ## 4. Account Disabled / Inactive ### Scenario User account exists but has been disabled (status is INACTIVE). ### When It Happens * User's status is `INACTIVE` * Account has been manually disabled by an administrator ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Your account has been disabled, Contact Support."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Your account has been disabled, Contact Support.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Display the error message clearly**: Fail gracefully, show the exact error message "Your account has been disabled, Contact Support." to the user. 2. **Provide support contact information**: Display contact information for support (email, phone, or support portal) so the user knows how to get help. 3. **Log for monitoring**: Consider logging this error (without sensitive information) for your monitoring systems to track account issues. 4. **Do not auto-retry**: This error will persist until the account is reactivated by an administrator, so automatic retries are not useful. *** ## 5. Invalid User Status (Not Active/Inactive) ### Scenario User exists but has a status that is not ACTIVE or INACTIVE (e.g., SIGNUP\_PENDING, etc.). ### When It Happens * User status is `SIGNUP_PENDING` or any other status not in `[ACTIVE, INACTIVE]` * User has not completed onboarding process ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Onboard the platform via Invitation Link sent to your email or Contact Support."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Onboard the platform via Invitation Link sent to your email or Contact Support.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Provide support contact**: Include support contact information in case the user needs help accessing their invitation or has questions about the onboarding process. 2. **Do not allow immediate retry**: This error indicates the user needs to take action outside of your application (checking email, completing onboarding). Do not allow immediate retry. 3. **Helpful messaging**: Consider adding context like "This account is pending setup. Please check your email for the invitation link to complete your registration." *** ## 6. Incomplete Account Setup ### Scenario User account exists but setup is incomplete (first login or email not verified). ### When It Happens * First login has not been completed * Email has not been verified * User has not completed initial account setup ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Your account setup is incomplete. Please contact support for assistance."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Your account setup is incomplete. Please contact support for assistance.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Display the error message**: Show the error message clearly to the user, as it explains that their account setup is incomplete. 2. **Provide support contact**: Include support contact information prominently, as the user needs to contact support to resolve this issue. 3. **Do not allow retry**: This error indicates the account requires administrative action or additional setup steps that cannot be completed through the sign-in process. Do not allow immediate retry. *** # Overview Source: https://docs.worthai.com/onboarding-sdk-2/overview The Worth AI Onboarding SDK enables customers to embed portions of the Worth Applicant Web App into their own websites. This provides a seamless, branded experience while leveraging Worth's application processing functionality. ## Why Use the Onboarding SDK? The SDK enables: * **Faster integration**: Reduce custom development work and integrate Worth's onboarding functionality quickly * **Branded experience**: Maintain your brand identity while utilizing Worth's core functionality * **Flexible embedding**: Embed specific portions of the Applicant Web App via iframe * **Type-safe communication**: Built-in TypeScript support with type-safe message passing ## Installation Install the SDK via npm: ```bash theme={null} npm install @worthai/onboarding-sdk ``` *** ## Quick Start > **Note**: The following example is illustrative code for vanilla TypeScript. Adapt to your framework's patterns when using React or other JavaScript frameworks. ```typescript theme={null} import { createOnboardingApp } from '@worthai/onboarding-sdk'; // Create an onboarding app instance and communicate with it const onboardingApp = createOnboardingApp({ // Make sure to have password login disabled on Worth Admin // before using inviteToken origin: '{{WORTH_ONBOARDING_APP_DOMAIN}}', inviteToken: '{{YOUR_INVITE_TOKEN}}', mode: 'embedded', }); // Listen for onboarding messages const subscription = onboardingApp.subscribe((event) => { if (event.data.type === 'ROUTE_URL') { console.log('Current route:', event.data.payload.url); } }); // ⚠️ Important: Remember to unsubscribe when // component unmounts or cleanup is needed. // subscription.unsubscribe(); // Append the onboarding app iframe document .getElementById('onboarding-container') .appendChild(onboardingApp.iframe); // Adding event listeners to Prev and Next buttons const prevButton = document.getElementById('onboarding-prev'); const nextButton = document.getElementById('onboarding-next'); // Next stage navigation command prevButton && prevButton.addEventListener('click', () => onboardingApp.prev()); // Prev stage navigation command nextButton && nextButton.addEventListener('click', () => onboardingApp.next()); // In your HTML: //
// // ``` ## Scope and Limitations ### What's In Scope * ✅ Applicant Web App pages embedding * ✅ JavaScript/TypeScript web SDK * ✅ Modern browser support (last 2 versions of Chrome, Firefox, Safari, Edge) * ✅ Client-side rendering * ✅ Iframe-based embedding with secure communication ### What's Out of Scope * ❌ Non-Applicant Web App pages or other Worth products * ❌ SSO authentication between parent site and Worth Applicant webapp * ❌ Mobile native SDKs (iOS/Android) * ❌ Server-side rendering support * ❌ Offline functionality * ❌ Legacy browser support *** ## Browser Support The SDK supports modern browsers only: * Chrome (last 2 versions) * Firefox (last 2 versions) * Safari (last 2 versions) * Edge (last 2 versions) *** ## Next Steps * See [API Reference](/onboarding-sdk-2/api-reference) for complete API documentation *** ## Support For questions or issues, please contact your Worth Customer Success team or reach out to [support@joinworth.com](mailto:support@joinworth.com). # API Reference Source: https://docs.worthai.com/onboarding-sdk-3/api-reference API reference for all Onboarding SDK methods, types, and options. ## createWorthOnboarding ### Import ```typescript theme={null} import { createWorthOnboarding } from '@worthai/onboarding-sdk'; ``` ### Parameters `createWorthOnboarding` accepts a single argument object with the following properties: | Property | Type | Required | Description | | - | - | - | - | | `inviteToken` | `string` | Yes | The invite token used to authenticate and load the onboarding session. Must be a non-empty string | | `onStepSubmit` | `callback` | No | Called each time the applicant submits a step. Receives `{ inviteToken, stepId, values }` and returns either `Promise` or `void` | | `onComplete` | `callback` | No | Called once the applicant submits the final step of the onboarding flow. Receives `{ inviteToken, values }` and returns either `Promise` or `void` | | `onError` | `callback` | No | Called whenever the SDK encounters an error. See [Error Handling](#error-handling) | | `onAuthenticated` | `callback` | No | Called when the invite token successfully authenticates | | `onAuthUnsupported` | `callback` | No | Called when the invite token's auth mode isn't supported by the embedded flow | | `styleNonce` | `string` | No | A CSP nonce applied to the styles that the SDK injects during `mount()`. Required only if your page enforces a strict `style-src` Content Security Policy | | `storageNamespace` | `string` | No | Overrides the default browser storage namespace (`worth:onboarding-sdk`) that the SDK uses | | `routeBasePath` | `string` | No | Overrides the base path that the SDK's internal router mounts under | | `apiBaseUrl` | `string` | No | Overrides the default Worth API origin. This is for environments where traffic must be routed through a proxy | | `flowInput` | `WorthOnboardingFlowInput` | No | Supplies a custom flow definition instead of resolving one from an invite token | `createWorthOnboarding` validates its options synchronously. An invalid or missing `inviteToken` or other malformed option throws a `WorthOnboardingError` immediately rather than surfacing it later through `mount()` or `onError`. See [Error Handling](#error-handling). ### Example ```typescript theme={null} import { createWorthOnboarding } from '@worthai/onboarding-sdk'; const onboarding = createWorthOnboarding({ apiBaseUrl: 'https://api-dev.joinworth.ai', inviteToken, onStepSubmit: ({ inviteToken, stepId, values }) => { console.log('Step submitted', { inviteToken, stepId, values }); }, onComplete: ({ inviteToken, values }) => { console.log('Onboarding completed', { inviteToken, values }); }, onError: (error) => { console.error(error); }, }); await onboarding.mount('#worth-onboarding'); // Later, for route cleanup: onboarding.unmount(); ``` SDK 3 also ships a browser-global build at `dist-sdk/sdk3/worthai-onboarding-sdk.global.js`. When loaded directly in a browser page, use the global namespace configured by the SDK build: ```html theme={null} ``` ### Returned Methods `createWorthOnboarding` returns a `WorthOnboarding` object with two methods: #### `mount(target)` Mounts the embedded onboarding runtime into a DOM target. SDK styles are injected automatically as part of this call. **Parameters:** * `target: HTMLElement | string` - The element to mount into, or a CSS selector string that resolves to one **Returns:** * `Promise` - Resolves with the mounted host element once the runtime has rendered **Example:** ```typescript theme={null} try { await onboarding.mount('#worth-onboarding'); } catch (error) { console.error('Failed to mount onboarding:', error); } ``` Only one onboarding instance can be mounted at a time. Call `unmount()` before mounting a new instance on the same page. *** #### `unmount()` Tears down the mounted runtime, removes its DOM element, and releases the mount target so that a new instance can be mounted later. **Parameters:** None **Returns:** `void` **Example:** ```typescript theme={null} // Call when the containing route or component unloads onboarding.unmount(); ``` If the runtime fails to tear down cleanly, `unmount()` will throw a `WorthOnboardingError` with the code `UNMOUNT_FAILED`. *** ## Callbacks ### `onComplete(event)` Observes the completion of the onboarding flow once the applicant has submitted the final step. **Event shape (`WorthOnboardingCompleteEvent`):** ```typescript theme={null} { inviteToken: string; values: Record; } ``` If `onComplete` fails or rejects, it will throw a `WorthOnboardingError` with the code `CALLBACK_FAILED`. ### `onStepSubmit(event)` Observes submitted step payloads as an applicant progresses through the onboarding flow. **Event shape (`WorthOnboardingStepSubmitEvent`):** ```typescript theme={null} { inviteToken: string; stepId: string; values: Record; } ``` If `onStepSubmit` fails or rejects, it will throw a `WorthOnboardingError` with the code `CALLBACK_FAILED`. ### `onError(error)` Observes every SDK and runtime error, including validation failures, mount failures, and callback failures. See [Error Handling](#error-handling) for a complete list of codes. ### `onAuthenticated(result)` / `onAuthUnsupported(result)` Observes authentication outcomes for the invite token. * `onAuthenticated` fires when the invite token authenticates successfully. The result includes `authMode`, `authResponse`, and `status: 'authenticated'` * `onAuthUnsupported` fires when the invite token's auth mode isn't supported by the embedded flow. The result includes `authMode`, `message`, an optional `redirectPath`, and `status: 'unsupported'` *** ## Error Handling Every error that the SDK raises is an instance of `WorthOnboardingError`, an `Error` subclass with a stable `code`: ```typescript theme={null} import { isWorthOnboardingError } from '@worthai/onboarding-sdk'; onError: (error) => { if (isWorthOnboardingError(error)) { console.error(`[${error.code}] ${error.message}`); } else { console.error(error); } }; ``` `WorthOnboardingError` has the following shape: | Property | Type | Description | | - | - | - | | `code` | `WorthOnboardingErrorCode` | A stable string identifying the error condition | | `message` | `string` | A human-readable description | | `details` | `Record \| undefined` | Optional structured context | ### Error Codes | Code | Raised From | Description | | - | - | - | | `MISSING_INVITE_TOKEN` | `createWorthOnboarding()` | `inviteToken` was omitted or is an empty string. Thrown synchronously at construction | | `INVALID_OPTIONS` | `createWorthOnboarding()` | The options object failed validation. Thrown synchronously at construction | | `ALREADY_MOUNTED` | `mount()` | The onboarding instance is already mounted | | `MOUNT_IN_PROGRESS` | `mount()` | `mount()` was called while a previous `mount()` call was still in progress | | `INVALID_MOUNT_TARGET` | `mount()` | The `target` passed to `mount()` isn't an `HTMLElement` or a valid selector string | | `MOUNT_TARGET_NOT_FOUND` | `mount()` | The selector string passed to `mount()` did not match any element in the document | | `MOUNT_CANCELLED` | `mount()` | The mount was interrupted before the runtime finished rendering | | `RUNTIME_RENDER_FAILED` | `mount()` | The onboarding runtime threw an error while rendering | | `UNMOUNT_FAILED` | `unmount()` | The mounted runtime failed to tear down cleanly | | `CALLBACK_FAILED` | Onboarding instance | `onStepSubmit` or `onComplete` threw or rejected | | `RUNTIME_ERROR` | Onboarding instance | The onboarding runtime reported an error during normal operation | Every error raised from `mount()` and `unmount()` is delivered to `onError` (if provided) before the returned promise rejects with the same error object. ## Next Steps * New to SDK 3? Follow the [Quick Start Guide](/onboarding-sdk-3/quickstart) * Migrating from SDK 2? Read the [Migration Guide](/onboarding-sdk-3/migrate) *** ## Support For questions or issues, please contact your Worth Customer Success team or reach out to [support@joinworth.com](mailto:support@joinworth.com). # API Error Handling - Send Business Invite Source: https://docs.worthai.com/onboarding-sdk-3/errors/send-business-invite ## Overview This document provides comprehensive error handling guidance for external developers integrating with the Send Business Invite API endpoint. This endpoint creates a business invitation, optionally creating a new business or attaching the invite to an existing one, and sends an invitation email to the applicant. Each error scenario includes classification, sample responses, and actionable recommendations for handling the error in your application. ## Endpoint ``` POST /api/v1/customers/:customerID/businesses/invite ``` ## Error Types The endpoint can return errors classified into four main categories: * **Validation Error**: Request format, schema, or data validation issues * **Network Error**: HTTP method or connectivity issues * **Authentication Error**: Authentication, authorization, or permission issues * **Internal Server Error**: Server-side failures requiring retry logic ## Error Index Quick navigation to specific error scenarios: 1. [Validation Error (Request Body Schema)](#1-validation-error-request-body-schema) 2. [Method Not Allowed Error](#2-method-not-allowed-error) 3. [Authentication Error (Missing or Invalid Token)](#3-authentication-error-missing-or-invalid-token) 4. [Authorization Error (Role Not Allowed)](#4-authorization-error-role-not-allowed) 5. [Data Permission Error](#5-data-permission-error) 6. [Insufficient Permissions Error](#6-insufficient-permissions-error) 7. [Onboarding Not Permitted For Customer](#7-onboarding-not-permitted-for-customer) 8. [Monthly Onboarding Limit Exhausted](#8-monthly-onboarding-limit-exhausted) 9. [Onboarding Template Version Errors](#9-onboarding-template-version-errors) 10. [Applicant Email Already Associated With An Account](#10-applicant-email-already-associated-with-an-account) 11. [Duplicate Business External ID](#11-duplicate-business-external-id) 12. [Existing Business Not Found](#12-existing-business-not-found) *** ## 1. Validation Error (Request Body Schema) ### Scenario Request body does not match the required schema for sending a business invite. ### When It Happens * Neither `applicants` nor `new_applicants` is provided (at least one is required) * An applicant is missing `first_name`, `last_name`, or `email` * `email` uses a disposable email domain, or isn't a valid email format * `mobile` (applicant or business) isn't a valid phone number for the detected region * Both `business`/`new_business` and `existing_business`/`existing_business_id` are provided together (these are mutually exclusive) * Neither business information (`business`, `new_business`, `existing_business`, or `existing_business_id`) nor an existing business reference is provided * `case_id` is provided without `existing_business_id` or `existing_business` * Invalid UUID format for `customerID` in the URL path, or for any of `existing_business_id`, `case_id`, `esign_template_id`, `custom_field_template_id`, `template_version_id`, or `existing_applicant_ids` * Extra fields that are not allowed are included in the request ### Classification **Validation Error** ### Error Details * **Error Class**: `ValidationMiddlewareError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Validation error message from schema", "errorCode": "INVALID", "data": { "errorName": "ValidationMiddlewareError" } } ``` ### Example Scenarios * Missing applicants: `{ "new_business": { "name": "Acme Corp" } }` * Invalid email: `{ "new_business": { "name": "Acme Corp" }, "new_applicants": [{ "first_name": "Jane", "last_name": "Doe", "email": "not-an-email" }] }` * Conflicting business fields: `{ "business": { "name": "Acme Corp" }, "new_business": { "name": "Acme Corp" }, "new_applicants": [...] }` * Invalid `customerID` UUID: `POST /api/v1/customers/invalid-uuid/businesses/invite` ### How to Handle 1. **Validate input before sending the request**: Confirm at least one applicant object is present and that business information is provided through exactly one of `business`, `new_business`, `existing_business`, or `existing_business_id`. 2. **Check field formats**: `email` must be a real, non-disposable address; `mobile` fields must be valid phone numbers for the applicable region. 3. **Do not retry automatically**: This is a client-side error that requires user action. Wait for the user to correct the input before retrying. *** ## 2. Method Not Allowed Error ### Scenario Request uses an HTTP method other than POST (e.g., GET, PUT, DELETE, PATCH). ### When It Happens * Client sends a non-POST request to `/customers/:customerID/businesses/invite` ### Classification **Network Error** (HTTP method mismatch) ### Error Details * **Error Class**: `MethodNotAllowedError` * **HTTP Status**: `405 Method Not Allowed` * **Error Code**: `NOT_ALLOWED` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Method Not Allowed", "errorCode": "NOT_ALLOWED", "data": { "errorName": "MethodNotAllowedError" } } ``` ### How to Handle 1. **Verify HTTP method**: Ensure you are using the `POST` method for this endpoint. 2. **Check your API client setup**: Review your HTTP client configuration (fetch, axios, etc.) to ensure the correct method is being used. 3. **No retry needed**: This is a permanent error that indicates incorrect API usage. Fix the HTTP method in your code and the request will succeed. *** ## 3. Authentication Error (Missing or Invalid Token) ### Scenario Request is missing the Authorization header or the token is invalid, expired, or malformed. ### When It Happens * Missing `Authorization` header * Authorization header does not start with "Bearer" * Token is expired, invalid, or malformed ### Classification **Authentication Error** ### Error Details * **Error Class**: `AuthenticationMiddlewareError` * **HTTP Status**: `401 Unauthorized` or `400 Bad Request` * **Error Code**: `UNAUTHENTICATED` or `INVALID` * **Message**: Varies based on the specific error ### Sample API Response **Missing Authorization Header:** ```json theme={null} { "status": "fail", "message": "Authorization header not present", "errorCode": "UNAUTHENTICATED", "data": { "errorName": "AuthenticationMiddlewareError" } } ``` **Invalid Authorization Header Format:** ```json theme={null} { "status": "fail", "message": "Invalid Authorization header type", "errorCode": "INVALID", "data": { "errorName": "AuthenticationMiddlewareError" } } ``` ### How to Handle 1. **Check Authorization header**: Ensure your request includes a valid `Authorization` header in the format: `Authorization: Bearer `. 2. **Handle token expiration**: Refresh the token and retry once with the new token. Do not retry automatically with the same token. 3. **Handle gracefully**: If authentication fails, redirect to your login flow or show an appropriate error message. *** ## 4. Authorization Error (Role Not Allowed) ### Scenario The authenticated user does not have the required role (`CUSTOMER` or `ADMIN`) to access this endpoint. ### When It Happens * User has the `APPLICANT` role (not allowed) * User has a role that is not `CUSTOMER` or `ADMIN` ### Classification **Authentication Error** ### Error Details * **Error Class**: `RoleMiddlewareError` * **HTTP Status**: `401 Unauthorized` * **Error Code**: `UNAUTHORIZED` * **Message**: `"Role Not Allowed"` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Role Not Allowed", "errorCode": "UNAUTHORIZED", "data": { "errorName": "RoleMiddlewareError" } } ``` ### How to Handle 1. **Verify user permissions**: This endpoint is only available to `CUSTOMER` and `ADMIN` role tokens. 2. **Do not retry**: This is a permanent authorization issue. 3. **Show appropriate message**: Display a message indicating the user does not have permission to perform this action. *** ## 5. Data Permission Error ### Scenario A `CUSTOMER`-role user is attempting to send an invite for a `customerID` that does not belong to them. ### When It Happens * The `customerID` in the URL path does not match the authenticated user's own customer ### Classification **Authentication Error** (Data access restriction) ### Error Details * **Error Class**: `AccessMiddlewareError` * **HTTP Status**: `403 Forbidden` * **Error Code**: `UNAUTHORIZED` * **Message**: `"You are not allowed to access the data."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "You are not allowed to access the data.", "errorCode": "UNAUTHORIZED", "data": { "errorName": "AccessMiddlewareError" } } ``` ### How to Handle 1. **Verify customer ID**: Ensure the `customerID` in the URL path matches the authenticated user's own customer. 2. **Do not retry**: This is a permanent authorization issue. 3. **Fix the request**: If this is a bug in your integration, correct the `customerID` being sent. *** ## 6. Insufficient Permissions Error ### Scenario A `CUSTOMER`-role user's assigned subrole does not grant the permissions required to send business invites. ### When It Happens * Your organization has custom roles enabled, and the authenticated user's subrole does not include `businesses:write` or `businesses:create:invite` * The authenticated user's token has no subrole assigned This check only applies to `CUSTOMER`-role tokens with custom roles enabled for your organization. `ADMIN` tokens are never subject to this check, and it has no effect if custom roles aren't enabled for your account. ### Classification **Authentication Error** (Permission restriction) ### Error Details * **Error Class**: `PermissionMiddlewareError` * **HTTP Status**: `403 Forbidden` * **Error Code**: `UNAUTHENTICATED` * **Message**: `"User subrole not found"` or `"You do not have the necessary permissions to perform this action."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "You do not have the necessary permissions to perform this action.", "errorCode": "UNAUTHENTICATED", "data": { "errorName": "PermissionMiddlewareError" } } ``` ### How to Handle 1. **Verify subrole permissions**: Confirm the user's subrole has been granted `businesses:write` or `businesses:create:invite`. 2. **Do not retry**: This is a permanent authorization issue until the subrole's permissions are updated. 3. **Contact an admin**: Direct the user to an account administrator to adjust their subrole's permissions. *** ## 7. Onboarding Not Permitted For Customer ### Scenario The customer account does not have permission to onboard businesses. ### When It Happens * The customer's account is not provisioned with the `onboarding_module:write` permission ### Classification **Authentication Error** (Account-level permission restriction) ### Error Details * **Error Class**: `BusinessApiError` * **HTTP Status**: `403 Forbidden` * **Error Code**: `INVALID` * **Message**: `"Customer does not have permission to onboard businesses."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Customer does not have permission to onboard businesses.", "errorCode": "INVALID", "data": { "errorName": "BusinessApiError" } } ``` ### How to Handle 1. **Do not retry**: This is an account-provisioning issue, not something your request can fix. 2. **Contact support**: Reach out to your Worth Customer Success team to confirm your account is provisioned for onboarding. *** ## 8. Monthly Onboarding Limit Exhausted ### Scenario The customer has reached their monthly onboarding limit and cannot send more invites. ### When It Happens * The customer has already onboarded the maximum number of businesses allowed for the current month This check is skipped for customers enrolled in the easy onboarding flow. ### Classification **Authentication Error** (Resource limit restriction) ### Error Details * **Error Class**: `OnboardingLimitError` * **HTTP Status**: `403 Forbidden` * **Error Code**: `NOT_ALLOWED` * **Message**: `"Monthly onboarding limit exhausted."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Monthly onboarding limit exhausted.", "errorCode": "NOT_ALLOWED", "data": { "errorName": "OnboardingLimitError" } } ``` ### How to Handle 1. **Display the error message**: Show the error message clearly to the user. 2. **Do not retry**: This will persist until the next billing cycle or until the limit is increased. 3. **Contact support**: Provide a way for users to contact support if they need to increase their limit. *** ## 9. Onboarding Template Version Errors ### Scenario The request includes `template_version_id`, but full onboarding configuration isn't enabled for the customer, or the referenced template version doesn't exist. ### When It Happens * `template_version_id` is provided, but the customer doesn't have the full onboarding configuration setup enabled * `template_version_id` is provided, but no matching template version exists for the customer ### Classification **Validation Error** (Business logic validation) ### Error Details **Full onboarding configuration not enabled:** * **Error Class**: `BusinessApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Full onboarding configuration is not enabled for this customer"` **Template version not found:** * **Error Class**: `BusinessApiError` * **HTTP Status**: `404 Not Found` * **Error Code**: `NOT_FOUND` * **Message**: `"Onboarding template version {template_version_id} not found for customer {customerID}"` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Onboarding template version 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found for customer 3fa85f64-5717-4562-b3fc-2c963f66afa6", "errorCode": "NOT_FOUND", "data": { "errorName": "BusinessApiError" } } ``` ### How to Handle 1. **Omit `template_version_id`** unless you intend to use a specific onboarding template version and full onboarding configuration is enabled for your account. 2. **Verify the template version ID**: Confirm it exists and belongs to the calling customer. 3. **Contact support**: If you believe full onboarding configuration should be enabled, contact your Worth Customer Success team. *** ## 10. Applicant Email Already Associated With An Account ### Scenario An applicant's email address is already registered to a non-applicant account (for example, an existing customer or admin user). ### When It Happens * An applicant in `applicants`/`new_applicants` has an `email` that already exists in the system under a role other than `APPLICANT` ### Classification **Validation Error** (Business logic validation) ### Error Details * **Error Class**: `BusinessApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Cannot onboard {email} to the platform. Contact support."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Cannot onboard jane.doe@example.com to the platform. Contact support.", "errorCode": "INVALID", "data": { "errorName": "BusinessApiError" } } ``` ### How to Handle 1. **Verify the applicant's email**: Confirm the applicant is using an email address that isn't already tied to another Worth account. 2. **Do not retry with the same email**: This requires the user to provide a different email address, or to contact support. 3. **Display the error message**: Show the error to the user so they know which applicant needs a different email. *** ## 11. Duplicate Business External ID ### Scenario The `external_id` provided on `business` or `new_business` already exists for this customer. ### When It Happens * A business with the same `external_id` was already created for this customer (including soft-deleted businesses) * A race condition causes the underlying database's uniqueness constraint to reject the insert ### Classification **Validation Error** (Business logic validation) ### Error Details * **Error Class**: `BusinessApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"The business external ID already exists for this customer (business ID: {existing_business_id})"`, or, in rare race-condition cases, `"The business external ID already exists for this customer"` without an ID ### Sample API Response ```json theme={null} { "status": "fail", "message": "The business external ID already exists for this customer (business ID: 9d75fc32-6770-4586-8dd6-9a9a0b6596b2)", "errorCode": "INVALID", "data": { "errorName": "BusinessApiError", "existing_business_id": "9d75fc32-6770-4586-8dd6-9a9a0b6596b2" } } ``` ### How to Handle 1. **Parse `data.existing_business_id`**: When present, use it to look up or reference the existing business instead of creating a duplicate. 2. **Use a unique `external_id`**: Generate or verify uniqueness of your external identifier before sending the request. 3. **Do not retry with the same `external_id`**: Correct the value first. *** ## 12. Existing Business Not Found ### Scenario `existing_business_id` (or the `business_id` on `existing_business`) doesn't reference a business that this customer has onboarded. ### When It Happens * The referenced business doesn't exist, is soft-deleted, or belongs to a different customer Unlike the other business-logic errors on this page, this one does not set an explicit HTTP status or `errorCode`. It surfaces as a generic `500` response with `"status": "error"` and `"errorCode": "UNKNOWN_ERROR"` rather than a `"fail"`-style `4xx` response. Handle it by matching on the message text rather than the status code or error code. ### Classification **Validation Error** (Resource not found) ### Error Details * **Error Class**: `BusinessApiError` * **HTTP Status**: `500 Internal Server Error` * **Error Code**: `UNKNOWN_ERROR` * **Message**: `"This business was not onboarded by the current customer."` ### Sample API Response ```json theme={null} { "status": "error", "message": "This business was not onboarded by the current customer.", "errorCode": "UNKNOWN_ERROR", "data": null } ``` ### How to Handle 1. **Verify the business reference**: Confirm `existing_business_id` (or `existing_business.business_id`) is correct and belongs to the calling customer. 2. **Match on message text**: Because this error doesn't use a distinguishing status code or error code, detect it by checking the `message` field rather than treating every `500` as a transient server error. 3. **Do not blindly retry**: Retrying without correcting the business reference will fail the same way every time. *** ## Related Documentation * [API Reference: Send Business Invite](/api-reference/case/invites/send-business-invite) - Complete endpoint and schema documentation * [Overview](/onboarding-sdk-3/overview) - Return to the SDK 3 overview *** ## Support For questions or issues, please contact your Worth Customer Success team or reach out to [support@joinworth.com](mailto:support@joinworth.com). # API Error Handling - Sign In Source: https://docs.worthai.com/onboarding-sdk-3/errors/sign-in ## Overview This document provides comprehensive error handling guidance for external developers integrating with the Customer Sign-in API endpoint. Each error scenario includes classification, sample responses, and actionable recommendations for handling the error in your application. ## Endpoint ``` POST /api/v1/customer/sign-in ``` ```bash theme={null} curl -X POST https://api.dev.joinworth.com/customer/sign-in \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "password": "userpassword123" }' ``` ## Error Types The endpoint can return errors classified into four main categories: * **Validation Error**: Request format or schema issues * **Network Error**: HTTP method or connectivity issues * **Authentication Error**: User account or credential issues * **Internal Server Error**: Server-side failures requiring retry logic *** ## Error Index Quick navigation to specific error scenarios: 1. [Validation Error (Request Body Schema)](#1-validation-error-request-body-schema) 2. [Method Not Allowed Error](#2-method-not-allowed-error) 3. [User not found / Incorrect credentials](#3-user-not-found-/-incorrect-credentials) 4. [Account Disabled / Inactive](#4-account-disabled-/-inactive) 5. [Invalid User Status (Not Active/Inactive)](#5-invalid-user-status-not-active/inactive) 6. [Incomplete Account Setup](#6-incomplete-account-setup) *** ## 1. Validation Error (Request Body Schema) ### Scenario Request body does not match the required schema (`Auth.SignIn.SignInWithPasswordRequestSchema`). ### When It Happens * Missing required fields (e.g., `email` or `password`) * Invalid field types (e.g., `email` is not a string, `password` is not a string) * Invalid field formats (e.g., `email` is not a valid email format) * Extra fields that are not allowed are included in the request ### Classification **Validation Error** ### Error Details * **Error Class**: `ValidationMiddlewareError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Validation error message from schema", "errorCode": "INVALID", "data": { "errorName": "ValidationMiddlewareError" } } ``` ### Example Scenarios * Missing email: `{ "password": "password123" }` * Missing password: `{ "email": "user@example.com" }` * Invalid email format: `{ "email": "not-an-email", "password": "password123" }` * Empty body: `{}` ### How to Handle 1. **Validate input before sending the request**: Implement client-side validation to ensure all required fields (`email` and `password`) are present and properly formatted before making the API call. 2. **Ensure proper request format**: Verify that your request body matches the expected schema: * `email`: Must be a valid email address string * `password`: Must be a non-empty string * Remove any extra fields that are not part of the schema *** ## 2. Method Not Allowed Error ### Scenario Request uses an HTTP method other than POST (e.g., GET, PUT, DELETE, PATCH). ### When It Happens * Client sends GET request to `/customer/sign-in` * Client sends PUT/DELETE/PATCH request to `/customer/sign-in` * Any non-POST request to this endpoint ### Classification **Network Error** (HTTP method mismatch) ### Error Details * **Error Class**: `MethodNotAllowedError` * **HTTP Status**: `405 Method Not Allowed` * **Error Code**: `NOT_ALLOWED` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Method Not Allowed", "errorCode": "NOT_ALLOWED", "data": { "errorName": "MethodNotAllowedError" } } ``` ### How to Handle 1. **Verify HTTP method**: Ensure you are using the `POST` method for this endpoint. This is a configuration issue in your HTTP client code. 2. **Check your API client setup**: Review your HTTP client configuration (fetch, axios, etc.) to ensure the correct method is being used. 3. **No retry needed**: This is a permanent error that indicates incorrect API usage. Fix the HTTP method in your code and the request will succeed. 4. **Update your integration**: If you're using a generated API client or SDK, ensure it's up to date with the latest API specification. *** ## 3. User Not Found / Incorrect Credentials ### Scenario User with the provided email does not exist in the database, OR email exists but password is incorrect. ### When It Happens * Email does not exist for CUSTOMER role * Email exists but password is incorrect * User exists but does not have CUSTOMER role assigned ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Incorrect username or password."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Incorrect username or password.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Do not auto-retry**: This error requires user action (correcting credentials), so do not automatically retry the request. 2. **Implement rate limiting on your side**: To prevent brute force attacks, consider limiting the number of failed sign-in attempts from your application before requiring additional verification. 3. **Handle gracefully**: Since this is a common user error, ensure your UI handles it gracefully without causing frustration. Consider showing helpful hints like "Check your email and password" or "Make sure Caps Lock is off". 4. **Do not store credentials**: Never log or store the user's password in any form, even in error logs. *** ## 4. Account Disabled / Inactive ### Scenario User account exists but has been disabled (status is INACTIVE). ### When It Happens * User's status is `INACTIVE` * Account has been manually disabled by an administrator ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Your account has been disabled, Contact Support."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Your account has been disabled, Contact Support.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Display the error message clearly**: Fail gracefully, show the exact error message "Your account has been disabled, Contact Support." to the user. 2. **Provide support contact information**: Display contact information for support (email, phone, or support portal) so the user knows how to get help. 3. **Log for monitoring**: Consider logging this error (without sensitive information) for your monitoring systems to track account issues. 4. **Do not auto-retry**: This error will persist until the account is reactivated by an administrator, so automatic retries are not useful. *** ## 5. Invalid User Status (Not Active/Inactive) ### Scenario User exists but has a status that is not ACTIVE or INACTIVE (e.g., SIGNUP\_PENDING, etc.). ### When It Happens * User status is `SIGNUP_PENDING` or any other status not in `[ACTIVE, INACTIVE]` * User has not completed onboarding process ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Onboard the platform via Invitation Link sent to your email or Contact Support."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Onboard the platform via Invitation Link sent to your email or Contact Support.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Provide support contact**: Include support contact information in case the user needs help accessing their invitation or has questions about the onboarding process. 2. **Do not allow immediate retry**: This error indicates the user needs to take action outside of your application (checking email, completing onboarding). Do not allow immediate retry. 3. **Helpful messaging**: Consider adding context like "This account is pending setup. Please check your email for the invitation link to complete your registration." *** ## 6. Incomplete Account Setup ### Scenario User account exists but setup is incomplete (first login or email not verified). ### When It Happens * First login has not been completed * Email has not been verified * User has not completed initial account setup ### Classification **Authentication Error** ### Error Details * **Error Class**: `SignInApiError` * **HTTP Status**: `400 Bad Request` * **Error Code**: `INVALID` * **Message**: `"Your account setup is incomplete. Please contact support for assistance."` ### Sample API Response ```json theme={null} { "status": "fail", "message": "Your account setup is incomplete. Please contact support for assistance.", "errorCode": "INVALID", "data": { "errorName": "SignInApiError" } } ``` ### How to Handle 1. **Display the error message**: Show the error message clearly to the user, as it explains that their account setup is incomplete. 2. **Provide support contact**: Include support contact information prominently, as the user needs to contact support to resolve this issue. 3. **Do not allow retry**: This error indicates the account requires administrative action or additional setup steps that cannot be completed through the sign-in process. Do not allow immediate retry. *** ## Related Documentation * [API Reference: Send Business Invite](/api-reference/case/invites/send-business-invite) - Complete endpoint and schema documentation * [Overview](/onboarding-sdk-3/overview) - Return to the SDK 3 overview *** ## Support For questions or issues, please contact your Worth Customer Success team or reach out to [support@joinworth.com](mailto:support@joinworth.com). # Migration Guide Source: https://docs.worthai.com/onboarding-sdk-3/migrate This guide details steps to migrate from the iframe-based Onboarding SDK 2 integration to the SDK 3 embedded runtime integration. ## What's Changed? The core change is ownership of the iframe. With SDK 2, your host page creates and manages a Worth iframe directly. With SDK 3, you give the SDK a DOM element and it mounts, renders, and tears down the onboarding runtime for you with no iframe and no `postMessage` subscription required. | | SDK 2 | SDK 3 | | - | - | - | | Rendering | Host-managed `