Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Grammar and Technical Term Formatting #62

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions concepts/authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: 'Authentication'
---

Flare's API is available at `https://api.flare.io`.
Authentication is handled through two components: **API tokens** for accessing endpoints and **API keys** for generating those tokens.

## Authentication Objects and Purpose

<CardGroup cols={1}>

<Card title="API Key" icon="key">
A permanent credential used to generate API tokens. Does not expire.
</Card>

<Card title="API Token" icon="file-shield">
A temporary credential used to access API endpoints. Expires after 1 hour.
</Card>

</CardGroup>

## Authentication Steps

<CardGroup cols={3}>

<Card
title="Obtain an API Key"
icon="square-1"
href="#1-obtaining-an-api-key"
>
Generate from the profile page
</Card>

<Card
title="Generate an API Token"
icon="square-2"
href="#2-obtaining-an-api-token"
>
Use your API key to obtain a token
</Card>

<Card
title="Access API Endpoints"
icon="square-3"
href="#3-access-an-api-endpoint"
>
Make requests with your API token
</Card>

</CardGroup>


### 1 - Obtaining an API Key

Visit the [Profile page](https://app.flare.io/#/profile) and navigate to the "API Keys" section to generate an API key.

<Frame
caption="Sidebar -> Configure -> Profile -> API Keys (bottom)"
className="flex justify-center"
>
<img src="/images/introduction/authentication/api-key-create.png" />
</Frame>

Your API key inherits the permissions of your user account:
- Access to tenants you can access
- Organization administrator privileges if you are an organization administrator


### 2 - Obtaining an API Token

Generate API tokens using your API key through the
[tokens/generate <Icon icon="code" size={16} />](/api-reference/tokens/endpoints/generate)
endpoint.

<CodeGroup>
```bash cURL example
curl --request POST \
--url https://api.flare.io/tokens/generate \
--header 'Authorization: <api-key>'
```

</CodeGroup>

### 3 - Access an API Endpoint

Include your API token in requests by setting the `Authorization: Bearer <api-token>` header.

You can verify your API token using the
[tokens/test <Icon icon="code" size={16} />](/api-reference/tokens/endpoints/test)
endpoint.

<CodeGroup>

```bash cURL example
curl --request GET \
--url https://api.flare.io/tokens/test \
--header 'Authorization: Bearer <api-token>'
```

</CodeGroup>

## Finding Tenant IDs

Access your tenant IDs by visiting the [Profile page](https://app.flare.io/#/profile) and navigating to the "Tenants" section.

<Frame
caption="Sidebar -> Configure -> Profile -> Tenants"
className="flex justify-center"
>
<img src="/images/introduction/authentication/profile-tenants.png" />
</Frame>

## End-to-End Examples

Here are complete authentication examples in different programming languages:

<AccordionGroup>

<Accordion title="Python Example">
```python
import os
import requests


api_key = os.environ.get("FLARE_API_KEY")
if not api_key:
raise Exception("Please provide an API key")

# Generate the API token
token: str = requests.post(
"https://api.flare.io/tokens/generate",
headers={
"Authorization": api_key,
},
).json()["token"]

# Use the token to access the testing endpoint
resp = requests.get(
"https://api.flare.io/tokens/test",
headers={
"Authorization": f"Bearer {token}",
},
)
print(resp.json())
```
</Accordion>

<Accordion title="Python SDK Example">
```python Python SDK
import os

from flareio import FlareApiClient


api_key = os.environ.get("FLARE_API_KEY")
if not api_key:
raise Exception("Please provide an API key")

client = FlareApiClient(api_key=api_key)

# Generate the API token
token: str = client.generate_token()

# Use the token to access the testing endpoint
resp = client.get("/tokens/test")
print(resp.json())
```
</Accordion>

</AccordionGroup>
197 changes: 197 additions & 0 deletions concepts/paging.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
title: 'Paging'
---

Some Flare APIs use a common pattern for paging through results.
This pattern pairs the `from` request parameter with the `next` response field.

## Using `from` and `next` paging

<Steps>

<Step title="First Request">
Perform the first request without specifying the `from` parameter.
This indicates that you want to retrieve the first page of results.
</Step>

<Step title="Subsequent Requests">
Use the `next` response field value from your last response as the
value for your following request's `from` parameter.
This indicates that you want to retrieve the next page of results.

All parameters other than `from` must remain identical to the original request.

If the `next` field is missing from the last response (or is `null`), it means you have viewed all available pages.

<Note>
Empty pages (no results) do not necessarily mean you have viewed all pages.
Some filters (like ignored events) will cause empty pages.
Therefore, you should continue requesting the next page even after receiving an empty page.
</Note>

</Step>

</Steps>


## The `from` Request Parameter

<ParamField query="from" type="string">
Used to indicate where to resume paging.

Should be omitted on the first request.
</ParamField>

## The `next` Response Field

<ResponseField name="next" type="string">
The value that should be included in the next request's `from` parameter.

Most of the time, this is an opaque string.

The value of the `next` response field can be saved for long periods.
For example, you can use it to export all results from a given search and then resume
fetching new results the next day.
</ResponseField>

## End-to-End Examples

These are end-to-end examples in various programming languages.

<AccordionGroup>

<Accordion title="Python SDK Example">
```python
import os
import time

from flareio import FlareApiClient


api_key = os.environ.get("FLARE_API_KEY")
if not api_key:
raise Exception("Please provide an API key")

api_client = FlareApiClient(api_key=api_key)

last_from: str | None = None
fetched_pages: int = 0

for resp in api_client.scroll(
method="GET",
url="/leaksdb/v2/sources",
params={
"from": None,
},
):
# Rate limiting
time.sleep(1)

# Get results from the response
resp_data = resp.json()
items = resp_data.get("items")

fetched_pages += 1
print(f"Fetched page {fetched_pages} ({last_from=}) with {len(items)} items...")

# Save the last "next" value
last_from = resp_data.get("next") or last_from

print("The last value for 'next' was", last_from)
```
</Accordion>

<Accordion title="Python Generic Example">
```python
import os
import time

from flareio import FlareApiClient


api_key = os.environ.get("FLARE_API_KEY")
if not api_key:
raise Exception("Please provide an API key")

api_client = FlareApiClient(api_key=api_key)

from_: str | None = None
fetched_pages: int = 0

while True:
# Rate limiting
time.sleep(1)

params: dict = {}
if from_:
params["from"] = from_

# Fetch the next page
resp = api_client.get(
"/leaksdb/v2/sources",
params=params,
)
resp.raise_for_status()

fetched_pages += 1
print(f"Fetched {fetched_pages} pages...")

# Stop if there is no "next" value
next_page = resp.json().get("next")
if not next_page:
print("The last value for 'next' was", from_)
break
else:
print(f"Next page will be from {next_page}")
from_ = next_page
```
</Accordion>


<Accordion title="Go SDK Example">
```go
package main

import (
"fmt"
"os"
"time"

"github.com/Flared/go-flareio"
)

func main() {
client := flareio.NewApiClient(
os.Getenv("FLARE_API_KEY"),
)

fetchedPages := 0

for result, err := range client.IterGet(
"/leaksdb/v2/sources", nil,
) {
// Rate Limiting
time.Sleep(time.Second * 1)

if err != nil {
fmt.Printf("unexpected error: %s\n", err)
os.Exit(1)
}

// Handle the response
result.Response.Body.Close()

// Print the status
fetchedPages = fetchedPages + 1
fmt.Printf(
"Fetched %d page(s) of LeaksDB Sources, next=%s\n",
fetchedPages,
result.Next,
)
}

}
```
</Accordion>

</AccordionGroup>
Loading