Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
"group": "OpenGraph",
"pages": [
"opengraph/overview",
"opengraph/quickstart",
"opengraph/requirements",
"opengraph/graph-theory",
"opengraph/schema",
Expand Down
7 changes: 6 additions & 1 deletion docs/get-started/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ title: Introduction to BloodHound

<Card title="Know your adversary with BloodHound security testing." icon="shield" iconType="solid" horizontal={true} />

BloodHound uses graph theory to reveal hidden and often unintended relationships within Active Directory, Entra ID (formerly Azure AD), and Microsoft Azure IaaS. Defenders (blue teams) and attackers (red teams) use BloodHound for a deeper understanding of privileged relationships in an environment.
BloodHound uses graph theory to reveal hidden and often unintended relationships within Active Directory and Entra ID (formerly Azure Active Directory). Defenders (blue teams) and attackers (red teams) use BloodHound for a deeper understanding of privileged relationships in an environment.

With the introduction of [OpenGraph](/opengraph/overview) in BloodHound v8.0, you can extend BloodHound's capabilities beyond Active Directory and Entra ID to visualize attack paths across hybrid environments. OpenGraph is a powerful framework that enables you to:

- **Extend coverage** to identity services across other platforms (for example, GitHub, Okta, Jamf, and more)
- **Build custom collectors** that ingest data using a standardized JSON schema

There are two BloodHound products: BloodHound Enterprise and BloodHound Community Edition (BloodHound CE). This site documents both products.

Expand Down
2 changes: 1 addition & 1 deletion docs/home.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function openSearch() {
</Card>
<Card
title="OpenGraph"
icon="diagram-project"
icon="circle-nodes"
href="/opengraph/overview"
iconType="solid"
>
Expand Down
Binary file added docs/images/opengraph/bob-and-alice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/opengraph/bob-knows-alice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/opengraph/bob.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/opengraph/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ You can remove generic data by using one of the following three (3) options:

</Accordion>
<Accordion title="Do custom nodes & edges work with Search and Pathfinding?">
No, not yet.
**Search:** Yes! As of v8.50, OpenGraph nodes are partially supported in the search functionality on the **Explore** page. You can search for OpenGraph nodes by display name or object ID, and visualize them in the graph with custom icons and colors. However, you cannot yet prepend search queries by OpenGraph node types.

In the initial BloodHound 8.0 release, OpenGraph nodes and edges are not supported in the Search or Pathfinding tab, so the Cypher tab **must** be used to query the data manually.
**Pathfinding:** Not yet. OpenGraph edges are not currently supported in the **Pathfinding** tab on the **Explore** page. For pathfinding queries involving OpenGraph data, you must use the Cypher tab to query the data manually.
</Accordion>
<Accordion title="How can I add my project to the OpenGraph library?">
Have you built a cool project using OpenGraph and want it featured here? Already got your project in the list and need to update something? Open a ["Library Change" issue](https://github.com/SpecterOps/bloodhound-docs/issues) on the BloodHound Docs repo and we'll get it added for you!
Expand Down
28 changes: 19 additions & 9 deletions docs/opengraph/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ sidebarTitle: Overview
description: "Learn about OpenGraph in BloodHound."
---

## <Icon icon="diagram-project" iconType="solid" /> The BloodHound OpenGraph
## <Icon icon="circle-nodes" iconType="solid" /> The BloodHound OpenGraph

<CardGroup cols={2}>
<Card title="OpenGraph Requirements" icon="square-check" href="/opengraph/requirements" horizontal iconType="solid"/>
<Card title="OpenGraph Best Practices" icon="thumbs-up" href="/opengraph/best-practices" horizontal iconType="solid"/>
<Card title="OpenGraph Schema" icon="gear" href="/opengraph/schema" horizontal iconType="solid"/>
<Card title="Custom Icons" icon="icons" href="/opengraph/custom-icons" horizontal iconType="solid"/>
<Card title="OpenGraph API" icon="gears" href="/opengraph/api" horizontal iconType="solid"/>
<Card title="OpenGraph Community Library" icon="book" href="/opengraph/library" horizontal iconType="solid"/>
<Card title="OpenGraph Community Incentive Program" icon="people-group" href="/opengraph/ocip" horizontal iconType="solid"/>
<Card title="OpenGraph FAQ" icon="question" href="/opengraph/faq" horizontal iconType="solid"/>
<Card title="Quickstart" icon="rocket" href="/opengraph/quickstart" horizontal iconType="solid" />

<Card title="OpenGraph Requirements" icon="square-check" href="/opengraph/requirements" horizontal iconType="solid" />

<Card title="OpenGraph Best Practices" icon="thumbs-up" href="/opengraph/best-practices" horizontal iconType="solid" />

<Card title="OpenGraph Schema" icon="brackets-curly" href="/opengraph/schema" horizontal iconType="solid" />

<Card title="Custom Icons" icon="icons" href="/opengraph/custom-icons" horizontal iconType="solid" />

<Card title="OpenGraph API" icon="brackets-curly" href="/opengraph/api" horizontal iconType="solid" />

<Card title="OpenGraph Community Library" icon="book" href="/opengraph/library" horizontal iconType="solid" />

<Card title="OpenGraph Community Incentive Program" icon="people-group" href="/opengraph/ocip" horizontal iconType="solid" />

<Card title="OpenGraph FAQ" icon="question" href="/opengraph/faq" horizontal iconType="solid" />
</CardGroup>
315 changes: 315 additions & 0 deletions docs/opengraph/quickstart.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
---
title: OpenGraph Quickstart
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something that I didn't see called out is that in BHE, all nodes must have at least one edge connecting them to other nodes. Otherwise, they'll get cleaned up by the built-in reconciliation process. Our getting started example already does that, but when you get into more advanced graph generation, you may want to make nodes first and then link them. But in BHE there has to at least be one edge to each. We call it out in the FAQ, I think, but would probably be wise to point out at least in a tooltip here.

description: Learn how to create and test OpenGraph data in BloodHound.
sidebarTitle: Quickstart
---

<img noZoom src="/assets/enterprise-AND-community-edition-pill-tag.svg" alt="Applies to BloodHound Enterprise and CE"/>

This guide walks you through creating and testing OpenGraph data using a simple example JSON file. By following these steps, you'll learn how to:

- Create a properly structured OpenGraph JSON file and upload it to BloodHound
- Define custom icons and colors for your node types to enhance visualization
- Validate the data using search and Cypher queries in the **Explore** page
- Remove the example data in the **Administration** > **Database Management** page when finished

Use this guide to get hands-on experience with the OpenGraph structure and validate custom nodes and edges in BloodHound.

## Create example data

This example defines two `Person` <Tooltip headline="node" tip="Part of the graph construct and refers to an entity in the network, such as a user, computer, group, or domain. Two nodes can be connected by an edge." cta="See the docs" href="/resources/nodes/overview">nodes</Tooltip> connected by a `Knows` <Tooltip headline="edge" tip="Part of the graph construct and refers to a relationship between two nodes, such as group membership or session information." cta="See the docs" href="/resources/edges/overview">edge</Tooltip> to demonstrate the structure of an OpenGraph payload.

You can expand on this example to create more complex graphs with additional nodes, edges, and properties as needed.

<Steps>
<Step title="Create a new JSON file">

First, you need to define your OpenGraph payload in a JSON file.

1. Create a new file called `opengraph-example.json` using a plain text editor (UTF-8 encoding).
Comment on lines +27 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we have the user create the file, would it be helpful to first reiterate that the basic structure is:

{
"metadata": {
"source_kind": "Person"
},
"graph": {
"nodes": [
...
],
"edges": [
...
]
}
}

As either a reminder OR a first inform, and then include a link that goes to the schema documentation where this is mentioned, as well as the broader schema.


1. Copy and paste the following example, which includes two nodes (`bob` and `alice`) connected by an edge (`Knows`).

```json
{
"metadata": {
"source_kind": "Person"
},
"graph": {
"nodes": [
{
"id": "123",
"kinds": [
"Person",
"Base"
],
"properties": {
"displayname": "bob",
"property1": "property1",
"objectid": "123",
"name": "BOB"
}
},
{
"id": "234",
"kinds": [
"Person",
"Base"
Comment on lines +35 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to pick a different source_kind and not Person. For context, source_kind refers to the data source, which is the system that the data reflects. For our built-in schemas, "Base" is the source_kind for Active Directory, and "AZBase" is the source_kind for Azure. I think it would be better to reflect this naming convention and do something like "EXBase".

Additional points of clarification:

  1. Currently, the first kind listed in each node's kind list is the "Primary Kind", and determines which node type (and icon representation) is associated with that node
  2. If the source_kind is declared in the metadata, then there's no need to apply it to each node individually. Using the source_kind automatically applies that kind to each of the nodes in the payload.
  • We had received feedback that it was difficult to manage all of these custom nodes, and so we made a way to quickly tag and group them
  • Using the source_kind also officially "registers" the kind as as source kind. That is required in order for a source_kind to show up in the DB Mgmt page for removal.
  • Registering only has to be done once though. After it's been registered, the source_kind can be added to nodes individually and it will be recognized as a source.
  • I'm not sure what would happen if you used a source_kind as the primary kind for something. I don't think it would be bad, but I haven't tested it, and there could be unexpected behavior.
  1. We should avoid using the "Base" source_kind as that ties the data into the graph as if it were generated by SharpHound. The only way to remove it would be to delete all of the AD data out of the graph. Hence why we created a way to label OG data as belonging to different sources, for cleaner mgmt.
  • "Base" could be used to reference existing nodes for hybrid edges, but I'd consider that a "201" level course and not an intro "101" type of thing.

],
"properties": {
"displayname": "alice",
"property1": "property1",
"objectid": "234",
"name": "ALICE"
}
}
],
"edges": [
{
"kind": "Knows",
"start": {
"value": "123",
"match_by": "id"
},
"end": {
"value": "234",
"match_by": "id"
}
}
]
}
}
```

The following table describes the structure and properties of the example JSON file:

| Section | Property | Description |
|---------|----------|-------------|
| **metadata** | `source_kind` | Optional property that identifies the type of data (e.g., "Person") in the **Database Management** page for easy clean up later |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same deal here, we shouldn't use "Person". Recommend "EXBase". I also wouldn't say that it

... identifies the type of data
so much as it identifies the source of the data, as in the system the data represents.

We may also want to call out here that using the source_kind property is the only way to register a kind as such, which is what populates the DB Mgmt page. Again, only has to be done once ever (unless DB is wiped), but if you don't use it at least once, it's treated as a regular old kind, no different than User or Group.

| **graph.nodes** | `id` | Unique identifier for the node |
| | `kinds` | Array of node types (first is your custom type, "Base" is required) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Base" is NOT required, and we should actually avoid "Base" (and "AZBase") specifically unless we're trying to create hybrid edges.

Other things we may want to call out here:

  • Have to have at least one kind, may want to mention the actual limit to how many kinds there can be, too
  • The first kind is the "Primary Kind" that determines which type the node is, and which icon is used to represent
  • A source_kind is not required here, but can be added to specific nodes if the source_kind property isn't used in the meta_data

| | `properties` | Object containing node properties (e.g., `name`, `displayname`, `objectid`, and custom properties) |
| **graph.edges** | `kind` | The edge type name (e.g., "Knows") |
| | `start` | Source node reference that must match a node ID in the nodes section |
| | `end` | Target node reference that must match a node ID in the nodes section |
Comment on lines +93 to +94
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't have to match a node ID, if you use the match_by: "name" option. Might be better to just say

... that must match either a pre-existing node, or a node declared above in the same payload

May want to avoid the match_by: "name" option for now though, as the matching gets much trickier and can seem buggy when it's really just finicky/nuanced.

Important to point out that the nodes declared as the vertices of the edge don't have to be declared in the same payload. You can create all the nodes you want in advance, and then create the edges after. In fact, that's part of our recommendation for how to generate hybrid edges right now.


**DELETE ME: `Base` kind is required for simple search to work; is that expected?**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, Base kind NOT required, and should be avoided unless intending to augment AD data and/or work with hybrid paths – both of which are more advanced.

We probably will want a guide on how to create hybrid paths, but that seems like a next step.

</Step>
<Step title="Save the file">
Save the `opengraph-example.json` file to a location you can easily access for uploading in the next step.
</Step>
<Step title="Upload the JSON file">
Use the BloodHound web interface to upload the `opengraph-example.json` file directly through the browser.

1. Log in to your BloodHound instance.
1. In the left menu, click **Quick Upload**.
1. Click the **Upload Files** screen to open a file system dialog or drag and drop the `opengraph-example.json` file.
1. Click **Upload** and wait for the upload to complete.

You should see a confirmation message indicating the file was successfully ingested.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to call out that if users have the right access then they can check on the status of file upload jobs in the Admin submenu?

I can't remember if that's limited to just Admins or not, but may be worth calling out since I think most users are admin on their own BHCE instance.


<Warning>If you receive an error, validate your JSON file using a [linter](https://jsonlint.com/) and ensure all [required properties](/opengraph/requirements) are present.</Warning>
</Step>
</Steps>

## Customize nodes

To enhance the visualization of the node types on the graph and in the **Entity** panel, you can define custom icons and colors.

<Note>This is done separately from the OpenGraph data payload and must be uploaded through the [BloodHound API](/integrations/bloodhound-api/working-with-api).</Note>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it won't come to BHCE for a little while longer, would it be worth adding something like "stay tuned for a more streamlined way to manage icons"? They'll have that ability to declare schemas, which include icon representation.


<Steps>
<Step title="Prepare your custom type definition">
This example creates a custom definition for the `Person` node type defined in the example JSON file. It specifies that the `Person` node type should display with a user icon and red color.

The custom type definition is a JSON object with the following structure:

```json
{
"custom_types": {
"Person": {
"icon": {
"type": "font-awesome",
"name": "user",
"color": "#FF0000"
}
},
... other custom type definitions ...
}
}
```

The following table describes the properties in the custom type definition:

| Property | Description |
|----------|-------------|
| `custom_types` | Object containing custom type definitions, where each key is a node type and the value defines the visualization properties for that type |
| `icon.type` | Font Awesome is the icon library used for custom icons |
| `icon.name` | Font Awesome [icon name]((https://fontawesome.com/search?s=solid)) (without "fa-" prefix) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't redirect correctly for me, but I think it's just a staging issue.

| `icon.color` | Hex color code (#RGB or #RRGGBB format) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some users have left off the # and I think it's required to be explicitly included. Would that be worth calling out?

</Step>
<Step title="Run a POST request">
Use a `POST` request to the BloodHound API to upload your custom type definition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to callout that they can then later to a PUT on the created custom type to modify an existing icon declaration?


Here's an example request body for a `Person` node type with a user icon and red color:

```bash
curl -X POST \
https://your-bloodhound-instance/api/v2/graphs/custom_nodes \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"custom_types": {
"Person": {
"icon": {
"type": "font-awesome",
"name": "user",
"color": "#FF0000"
}
}
}
}'
```

After running this request, any nodes of type `Person` in your graph display with the specified icon and color.
</Step>
</Steps>

## Validate example data

After uploading the OpenGraph example data and custom node icons/colors, it's important to validate that BloodHound ingested everything correctly and displays it as expected.

<Steps>
<Step title="Open the Explore page">
Log in to your BloodHound instance and navigate to the **Explore** page.
</Step>
<Step title="Search for nodes and edges">

Use the **Search** features to find the example nodes and edges, and verify that properties and custom icons/colors are displayed correctly.

<Tabs>
<Tab title="Search" icon="magnifying-glass">
To find nodes by display name or object ID:

1. Click the **Search** tab.
1. In the search field, enter `bob` or `alice`.
1. Select the node from the suggested search results.
1. Click the node on the graph to view its properties in the **Entity** panel.

**Expected results:**

- Suggested search results include the Bob and Alice `Person` nodes
- Node properties and custom icons/colors display in the **Entity** panel
- Custom node icons and colors **do not** display on the graph for Bob and Alice nodes

<Note>Custom icons/colors render on the graph for Cypher search only.</Note>
Comment on lines +203 to +205
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really? I thought they were going to display for anywhere that supported the data type. So if search supports OG data, the dropdown list and selection bar should show, as well as the graph itself and the entity panel?

Something may be broken here. Recommend reaching out to @sirisjo to see what reality is.


<img src="/images/opengraph/bob.png" alt="A view of the custom Bob node on the graph showing properties in the Entity panel" />
</Tab>
<Tab title="Cypher" icon="code">
To find nodes and edges by type:

1. Click the **Cypher** tab
1. Copy and paste one of the following queries and click **Run**:

- To find all `Person` nodes:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was written thinking that Person was going to be the source_kind. Right now it will still show the nodes we created, but if they're using more node types then it will only show that one specific node type. For our "getting started example" it might be useful to include a search that shows how to search for all nodes in that source, as well as how to search for a particular node type within our custom arrangement.

We may actually want to consider different node types (like Alice is Employee and Bob is Manager) to showcase that nuance.


```cypher
MATCH (n:Person)
RETURN n
```
**Expected results:**

- Nodes BOB and ALICE display on the graph (not connected by an edge)
- Node properties and custom icons/colors display in the **Entity** panel after clicking a node on the graph
- Custom node icons and colors display on the graph

<img src="/images/opengraph/bob-and-alice.png" alt="A view of the custom Bob and Alice nodes on the graph and property details for Bob in the Entity panel" />

- To find the `Knows` edge between nodes:

```cypher
MATCH p=()-[:Knows]-()
RETURN p
```
**Expected results:**

- Nodes BOB and ALICE nodes display on the graph and are connected by the `Knows` edge
- Node properties and custom icons/colors display in the **Entity** panel after clicking a node on the graph
- Custom node icons and colors display on the graph

<img src="/images/opengraph/bob-knows-alice.png" alt="A view of the custom Bob and Alice nodes connected by the Knows edge on the graph and property details for Bob in the Entity panel" />
</Tab>
</Tabs>
</Step>
</Steps>

## Delete example data

After you've finished testing, you should clean up your example data by deleting the example OpenGraph payload.

<Steps>
<Step title="Delete example data">
Use the BloodHound web interface to delete nodes by `source_kind`.

1. Log in to your BloodHound instance.
1. In the left menu, click **Administration** > **Database Management**.
1. Under **All graph data**, check the **Person data** checkbox.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace Person with the alternative source_kind (proposed EXBase)


<Note>The name of the checkbox is based on the value of the `source_kind` property in the metadata section of the example JSON file.</Note>

1. Click **Delete** and confirm the deletion.

<Warning>This action permanently deletes all nodes with the `Person` source kind, including any edges connected to those nodes.</Warning>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update source_kind

</Step>
<Step title="Verify deletion">
Run the following Cypher query to confirm the example OpenGraph data is gone:

```cypher
MATCH (n:Person)
RETURN n
```

You should see a `No results match your criteria` message confirming that the nodes have been deleted.
Comment on lines +266 to +273
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may take a little time, depending on if it's done in a completely blank slate or if there's other data. It will also likely cache the result, so the cache will need to be cleared to confirm. I think the easiest way is to just refresh the cypher page. May want to ask around and confirm.

</Step>
</Steps>

## Troubleshooting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A troubleshooting issue that can occur is that duplicate nodes can be created if there's not a perfect match. Not sure if this should be here or in the FAQ tho.


This section provides solutions to common issues you may encounter when testing your OpenGraph data.

<AccordionGroup>
<Accordion title="Upload fails">
- Validate your JSON using [JSONLint](https://jsonlint.com/)
- Ensure all required sections are present
- Verify all node IDs are unique
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should specify that this only applies to the new nodes declared in the node section. The edge section will necessarily need to utilize previously declared node IDs.

- Check that node IDs referenced in edges match the node IDs in the nodes section exactly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't have to match the nodes declared in the same payload. Can match nodes that were previously declared (or even nodes of built-in type that users never declared themselves).

</Accordion>

<Accordion title="Nodes don't appear in search">
- Ensure you correctly used the node ID values in search
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should clarify that the search is by "name" or "objectID". Which in the case of the custom nodes is the "id" that they declared. But for searching, they are accessed by referencing the "objectID" property.

- Verify the upload completed successfully without errors
- Check the BloodHound logs for any ingest errors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should confirm whether everyone has access to those or not. If limited, then specify which role can do so.

</Accordion>

<Accordion title="Custom icons not displaying">
- Verify the icon name is correct and does not include a prefix, such as `fa-` (see [FontAwesome](https://fontawesome.com/search?o=r&ic=free&s=solid) to confirm available icons)
- Ensure the color is in valid HEX format (#RGB or #RRGGBB)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And that the # is included, I believe

- Run a `GET` request to `api/v2/graphs/custom_nodes` to confirm your BloodHound instance contains the custom type definition you want to use
</Accordion>

<Accordion title="Edge not found in Cypher query">
- Verify the edge `kind` name is spelled correctly and matches your JSON file
- Ensure the node IDs in the `start` and `end` references match your node IDs exactly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to call out that they're just "ID" in the payload, but objectID as represented in the graph/entity panel.

- Check that both referenced nodes were created successfully
</Accordion>
</AccordionGroup>

## Next steps

After you're comfortable with this process, consider:

- Creating more complex node types with additional properties
- Testing multiple edge types between different node kinds
- Reading the [OpenGraph Schema](/opengraph/schema) documentation for advanced configurations
- Reviewing [OpenGraph Best Practices](/opengraph/best-practices) before deploying production data