> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hellofriday.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Call Friday from your app

> Trigger a workflow, stream its progress, and cancel it — all from your own application.

In this guide, you'll trigger a Friday workflow from your application, stream its progress in real time, and optionally cancel it.

## Prerequisites

* Friday Studio [installed and running](/getting-started/quickstart)
* At least one space loaded with a signal configured
* The daemon API is available at `http://localhost:18080`

<Tip>
  Run `curl http://localhost:18080/api/workspaces` to see your loaded spaces and their IDs. Each space's `signals` object shows what signals are available and what payload fields they expect.
</Tip>

## Trigger a signal

Every workflow starts with a **signal**. Send a POST request with a payload and Friday runs the job.

### Fire and wait

Send a POST and block until the job completes:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST http://localhost:18080/api/workspaces/{workspaceId}/signals/{signalId} \
    -H 'Content-Type: application/json' \
    -d '{"payload": {"key": "value"}}'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "http://localhost:18080/api/workspaces/{workspaceId}/signals/{signalId}",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ payload: { key: "value" } }),
    }
  );

  const result = await response.json();
  console.log(result.sessionId); // use this to check status
  ```

  ```python Python theme={null}
  import httpx

  response = httpx.post(
      "http://localhost:18080/api/workspaces/{workspaceId}/signals/{signalId}",
      json={"payload": {"key": "value"}},
  )
  response.raise_for_status()
  print(response.json()["sessionId"])
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "message": "Signal completed",
  "status": "completed",
  "workspaceId": "my-space",
  "signalId": "my-signal",
  "sessionId": "sess_abc123"
}
```

### Stream progress in real time

Add `Accept: text/event-stream` to receive a live SSE stream as the job executes:

<CodeGroup>
  ```bash cURL theme={null}
  curl -N -X POST http://localhost:18080/api/workspaces/{workspaceId}/signals/{signalId} \
    -H 'Content-Type: application/json' \
    -H 'Accept: text/event-stream' \
    -d '{"payload": {"key": "value"}}'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "http://localhost:18080/api/workspaces/{workspaceId}/signals/{signalId}",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "text/event-stream",
      },
      body: JSON.stringify({ payload: { key: "value" } }),
    }
  );

  const reader = response.body!.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    for (const line of decoder.decode(value).split("\n")) {
      if (line.startsWith("data: ")) {
        const data = line.slice(6);
        if (data === "[DONE]") break;
        console.log(JSON.parse(data));
      }
    }
  }
  ```

  ```python Python theme={null}
  import httpx

  with httpx.stream(
      "POST",
      "http://localhost:18080/api/workspaces/{workspaceId}/signals/{signalId}",
      json={"payload": {"key": "value"}},
      headers={"Accept": "text/event-stream"},
  ) as response:
      response.raise_for_status()
      for line in response.iter_lines():
          if line.startswith("data: ") and line[6:] != "[DONE]":
              print(line[6:])
  ```
</CodeGroup>

**Event stream:**

```
data: {"type":"data-session-start","data":{"sessionId":"sess_abc123"}}

data: {"type":"text-delta","delta":"Fetching emails..."}

data: {"type":"job-complete","data":{"success":true,"sessionId":"sess_abc123","status":"completed"}}

data: [DONE]
```

## Check run status

Use the `sessionId` from the trigger response to check on the run:

<CodeGroup>
  ```bash cURL theme={null}
  curl http://localhost:18080/api/sessions/sess_abc123
  ```

  ```typescript TypeScript theme={null}
  const session = await fetch(
    "http://localhost:18080/api/sessions/sess_abc123"
  ).then(r => r.json());

  console.log(session.status); // "completed", "running", or "failed"
  ```

  ```python Python theme={null}
  import httpx

  session = httpx.get("http://localhost:18080/api/sessions/sess_abc123").json()
  print(session["status"])
  ```
</CodeGroup>

## Cancel a running job

If you need to stop a job mid-execution:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE http://localhost:18080/api/sessions/sess_abc123
  ```

  ```typescript TypeScript theme={null}
  await fetch("http://localhost:18080/api/sessions/sess_abc123", {
    method: "DELETE",
  });
  ```

  ```python Python theme={null}
  import httpx

  httpx.delete("http://localhost:18080/api/sessions/sess_abc123")
  ```
</CodeGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="API reference" icon="code" href="/api-reference/introduction">
    Full endpoint reference for every API operation.
  </Card>

  <Card title="Signals" icon="bolt" href="/core-concepts/signals">
    Signal types, payload schemas, and webhook configuration.
  </Card>
</CardGroup>
