> ## Documentation Index
> Fetch the complete documentation index at: https://developers.apps.filed.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Start data entry from your product

> Let a user pick their tax software client and start data entry in a Filed dialog, without leaving your product

After you push a client's documents into Filed, someone still has to say which
tax software connection and which tax software client the entries belong to.
Rather than send the user to Filed for that, ask Filed for a short-lived URL
and show it in a dialog or pop-up. Filed renders the selection there and tells
your page when the user confirms.

You can open the dialog as soon as you have pushed the documents. The user
does not have to wait for them to be processed: Filed starts preparing the
entries on its own once they are ready.

```mermaid theme={null}
flowchart LR
  A["Your server"] -->|"1. createDataEntryStartUrl"| B["url"]
  B -->|"2. iframe or pop-up"| C["Filed dialog:<br/>pick connection + client"]
  C -->|"3. user clicks Start"| D["postMessage<br/>data-entry.started"]
  C -->|"3. user clicks Start"| E["webhook<br/>task.running"]
  E -->|"documents processed,<br/>entries prepared"| F["webhook<br/>task.paused<br/>(ready_for_review)"]
  F -->|"user reviews and sends<br/>in Filed"| G["webhook<br/>task.completed"]
```

<Note>
  The tax software connections and the client list are shown by Filed inside the
  dialog. Your product never receives them.
</Note>

## Before you start

The firm needs two things in place before its users connect your product:

* An active Filed workspace.
* One or more active tax software connections in that workspace.

## 1. Request a URL

Call `createDataEntryStartUrl` from your server with a `workspaceToken` that
has write access (see [Authentication](/guides/authentication) or
[Connect with OAuth](/guides/connect-with-oauth)).

```graphql theme={null}
mutation CreateDataEntryStartUrl($clientId: ID!, $parentOrigin: String!) {
  createDataEntryStartUrl(clientId: $clientId, parentOrigin: $parentOrigin) {
    url
    expiresAt
  }
}
```

<ParamField body="clientId" type="ID!" required>
  The Filed client to start data entry for. It must belong to the token's
  workspace.
</ParamField>

<ParamField body="parentOrigin" type="String!" required>
  The origin of the page that will show the dialog, for example
  `https://app.example.com`. Must be `https` with no path. The dialog posts its
  result to this origin and to no other.
</ParamField>

<ResponseField name="url" type="String!">
  Open this in an iframe or a pop-up. It signs the browser in for the dialog
  only and expires after 10 minutes. Treat it as a credential: request it right
  before showing the dialog and never log it.
</ResponseField>

<ResponseField name="expiresAt" type="Date!">
  When the URL stops working.
</ResponseField>

## 2. Show the dialog

```js theme={null}
const dialog = document.querySelector("#filed-dialog");
const frame = dialog.querySelector("iframe");

frame.src = url; // from step 1
dialog.showModal();
```

A pop-up works the same way: `window.open(url, "filed-data-entry", "width=760,height=640")`.

Inside the dialog the user sees one of these:

| State | What the user sees |
| - | - |
| Ready | The tax software connection and client to enter into, and a Start button. A client already linked in Filed is pre-selected. |
| Documents still processing | The same, with a note that Filed will begin once the documents are ready. Start works. |
| Already started | A notice that data entry has already started for this client, with a link to review it in Filed. |
| No tax software connected | A prompt to connect tax software, with a link that opens Filed in a new tab. |
| Expired | A notice to close the dialog and start again. |

Any link in the dialog opens Filed in a new tab; the dialog itself never
navigates away.

## 3. Listen for the result

The dialog posts a message to your window when something happens. Check the
sender's origin before acting on it.

```js theme={null}
window.addEventListener("message", (event) => {
  if (event.origin !== "https://web.apps.filed.com") return;
  if (event.data?.source !== "filed") return;

  if (event.data.type === "data-entry.started") {
    dialog.close();
    // event.data.clientId, event.data.taskId
  }
  if (event.data.type === "data-entry.expired") {
    dialog.close(); // request a new URL to try again
  }
});
```

| `type` | Fields | Meaning |
| - | - | - |
| `data-entry.started` | `clientId`, `taskId` | The user started data entry. `taskId` is the `AI_DATA_ENTRY` task. |
| `data-entry.already-started` | `clientId`, `taskId` | Data entry was started for this client earlier. The dialog shows a notice and stays open. |
| `data-entry.expired` | `clientId` | The URL expired before the user started. |

Every message also carries `source: "filed"`.

## After the user starts

* Your webhook endpoint receives `task.running` for the same `taskId`, with
  `taskType: AI_DATA_ENTRY`; see [Receive Webhooks](/guides/webhooks).
* Filed waits for the client's documents to finish processing, then prepares
  the entries in the background. If the documents are still processing after
  two hours, or none can be used, the task fails and you receive `task.failed`
  with the reason in `errorMessage`.
* When the entries are ready you receive `task.paused` with
  `reason: ready_for_review`. Its `actionUrl` opens them in Filed, where the
  user reviews them and sends them to their tax software. Each person who
  reviews needs their own Filed sign-in.
* `task.completed` follows once the entries are sent and verified.
* When more documents arrive for the same client, the user opens that same
  page to prepare again. No new URL is needed.

## Things to know

* The dialog acts as the Filed user who connected your product, so it shows
  the tax software connections that user can use.
* A token without write access cannot request a URL.
* The URL signs in one browser for 10 minutes and is not renewed. If the user
  leaves the dialog open past that, they see the expired notice.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.