# API

The Graph Commons API provides developers with a powerful GraphQL interface to integrate, query, and manage data. With this API, you can automate processes, dive deep into your networks, and harness the full potential of Graph Commons directly from your applications.

## GraphQL API Explorer

You can build queries, browse schemas, and test the API using the Apollo GraphQL Explorer:

👉🏼 [Open in Apollo Explorer](https://studio.apollographql.com/sandbox/explorer?endpoint=https://graphcommons.com/graphql)

<figure><img src="https://918529313-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtBdFNYyZE7d8Q4z2K2ZT%2Fuploads%2FhDVuAOMvKTiFsPGMtIBe%2Fgc-api-graphql-apollo-explorer.png?alt=media&#x26;token=57302eef-abc3-480d-b038-1345a716ac59" alt=""><figcaption><p>Try our Graph Commons API directly in the Apollo GraphQL Explorer</p></figcaption></figure>

## Authentication

No separate API key required, simply use your Graph Commons username and password to authenticate.

{% hint style="info" %}
API authentication is done with your email and password. Social logins are not supported.
{% endhint %}

Here’s a Node.js function to authenticate and retrieve a JWT token:

```typescript
export const login = async (username: string, password: string) => {
  const response = await fetch("https://graphcommons.com/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: `mutation login($username: ID!, $password: String!) {
        JWT: login(loginOrEmail: $username, password: $password)
      }`,
      variables: {
        username,
        password,
      },
    }),
  });

  if (!response.ok) {
    throw new Error(`HTTP error! Status: ${response.status}`);
  }

  const jsonResponse = await response.json();
  return jsonResponse.data.JWT;
};

```

## Create a graph

Use the `login` function from the authentication step to create a new graph.

{% hint style="info" %}
You can send **your own temporary IDs** for node types, edge types, nodes, and edges. The server will return an `idsMapping` so you can map your temp IDs to real server IDs later.
{% endhint %}

```typescript
import { login } from './path_to_login_function';

const USERNAME = process.env.GC_USERNAME!;
const PASSWORD = process.env.GC_PASSWORD!;

async function createSimpleGraph() {
  const jwt = await login(USERNAME, PASSWORD);

  // 1) Define your graph in simple JSON.
  // Use YOUR OWN temp IDs (nt_*, et_*, n_*, e_*).
  const graphInput = {
    name: "Company Mini-Graph",
    description: "A tiny example created via GraphQL API",

    // --- Node Types ---
    nodeTypes: [
      { id: "nt_person",    name: "Person",      properties: [{ id: "p_title",  name: "title",  type: "STRING" }] },
      { id: "nt_company",   name: "Company",     properties: [{ id: "p_domain", name: "domain", type: "STRING" }] },
    ],

    // --- Edge Types ---
    // IMPORTANT: sourceNodeTypeId / targetNodeTypeId must reference your temp nodeType IDs above.
    edgeTypes: [
      {
        id: "et_works_at",
        name: "WORKS_AT",
        sourceNodeTypeId: "nt_person",
        targetNodeTypeId: "nt_company",
        properties: [{ id: "p_since", name: "since", type: "NUMBER" }],
      },
    ],

    // --- Nodes ---
    // Each node's typeId references your temp node type IDs.
    nodes: [
      { id: "n_alex",  name: "Alex",  typeId: "nt_person",  properties: { title: "CTO" } },
      { id: "n_acme",  name: "Acme",  typeId: "nt_company", properties: { domain: "acme.example" } },
    ],

    // --- Edges ---
    // sourceId / targetId reference your temp node IDs; typeId references your temp edge type ID.
    edges: [
      {
        id: "e_alex_acme",
        sourceId: "n_alex",
        targetId: "n_acme",
        typeId: "et_works_at",
        weight: 1,
        properties: { since: 2020 },
      },
    ],
  };

  // 2) Send the createGraph mutation with your JSON.
  const response = await fetch("https://graphcommons.com/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${jwt}`,
    },
    body: JSON.stringify({
      operationName: "CreateGraph",
      query: `
        mutation CreateGraph($graph: GraphInput!) {
          result: createGraph(graph: $graph) {
            idsMapping {
              graph
              nodeTypes
              nodeTypeProperties
              edgeTypes
              edgeTypeProperties
              nodes
              edges
              __typename
            }
            limitations { usage max __typename }
            report { success errors warnings __typename }
            __typename
          }
        }
      `,
      variables: { graph: graphInput },
    }),
  });

  const json = await response.json();

  if (json.errors) {
    console.error("GraphQL errors:", json.errors);
    throw new Error("createGraph failed at transport level");
  }
  const { report, idsMapping } = json.data.result;

  if (!report.success) {
    console.error("createGraph errors:", report.errors);
    throw new Error(`createGraph failed: ${report.errors.join("\n")}`);
  }

  // You’ll need this for future updates:
  const realGraphId = idsMapping.graph;
  console.log("Created graph id:", realGraphId);

  // Optional: map your temp IDs -> real IDs if you’ll reference them later
  // e.g., const realAlexId = idsMapping.nodes["n_alex"];

  return { graphId: realGraphId, idsMapping };
}

// Example call:
createSimpleGraph().then(({ graphId }) => {
  console.log("Graph ready:", graphId);
});
```

## Read a graph

Use the `login` function from the authentication step together with a `graphId`—either returned from the `createGraph` step or any existing graph on Graph Commons—to fetch graph data.

```typescript
async function readGraph(graphId: string) {
  const jwt = await login(USERNAME, PASSWORD);

  const res = await fetch("https://graphcommons.com/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${jwt}`,
    },
    body: JSON.stringify({
      operationName: "GetGraphById",
      query: `
        query GetGraphById($graphId: ID!) {
          result: getGraphById(id: $graphId) {
            graph {
              id
              name
              nodeTypes { id name properties { id name type } }
              edgeTypes { id name sourceNodeTypeId targetNodeTypeId properties { id name type } }
              nodes { id name typeId properties }
              edges {
                id sourceId targetId typeId
                source { name }
                target { name }
                type { name }
                weight
                properties
              }
            }
          }
        }
      `,
      variables: { graphId },
    }),
  });

  const json = await res.json();
  return json.data.result.graph;
}

```

## Update a graph

You can update an existing graph—adding or removing nodes, edges, properties, or adjusting node positions—using the `updateGraph` mutation.

Call `savePatchGraph(id, patch)` to create new items and/or update graph properties (such as `nodesPosition`). The `create` section should use temporary IDs, which the server will map to permanent ones in the returned `idsMapping`.

```typescript
async function addEmployeeToCompany(graphId: string) {
  const jwt = await login(USERNAME, PASSWORD);

  // In this example, we add "Sam" (Person) working at "Acme" (Company),
  // and we move Alex slightly on the canvas.
  //
  // If you don't know the real type IDs, you can just reuse your original temp IDs
  // ONLY IF you've reset and recreated the graph in one go. Otherwise, read the
  // graph first to resolve the real type IDs. For brevity, we assume:
  //  - Person type = the real id behind your original "nt_person"
  //  - Company type = the real id behind your original "nt_company"
  //  - WORKS_AT type = the real id behind "et_works_at"
  //
  // To be explicit, you can fetch the graph (readGraph) and find the type IDs by name.

  // Example: pretend we looked them up:
  const PERSON_TYPE_ID  = "REPLACE_WITH_REAL_PERSON_TYPE_ID";
  const COMPANY_TYPE_ID = "REPLACE_WITH_REAL_COMPANY_TYPE_ID";
  const WORKS_AT_TYPE_ID = "REPLACE_WITH_REAL_WORKS_AT_TYPE_ID";

  // We'll reference Acme by its REAL node id (recommended). If you don’t know it,
  // call readGraph(graphId) and match by name.
  const ACME_NODE_ID = "REPLACE_WITH_REAL_ACME_NODE_ID";
  const ALEX_NODE_ID = "REPLACE_WITH_REAL_ALEX_NODE_ID";

  const patch = {
    id: graphId,
    patch: {
      create: {
        // New node with temp id "n_sam"
        nodes: [
          { id: "n_sam", name: "Sam", typeId: PERSON_TYPE_ID, properties: { title: "Engineer" } },
        ],
        edges: [
          // New edge from "n_sam" (temp) to Acme (real)
          { id: "e_sam_acme", sourceId: "n_sam", targetId: ACME_NODE_ID, typeId: WORKS_AT_TYPE_ID, weight: 1, properties: { since: 2024 } },
        ],
      },
      update: {
        graph: {
          nodesPosition: {
            // Move Alex a bit (use REAL Alex ID here)
            [ALEX_NODE_ID]: { x: 130, y: 110 },
          },
        },
      },
    },
  };

  const res = await fetch("https://graphcommons.com/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${jwt}`,
    },
    body: JSON.stringify({
      operationName: "SavePatchGraph",
      query: `
        mutation SavePatchGraph($id: ID!, $patch: GraphPatchInput!) {
          result: savePatchGraph(id: $id, patch: $patch) {
            report { success errors warnings __typename }
            idsMapping {
              nodeTypes
              nodeTypeProperties
              edgeTypes
              edgeTypeProperties
              nodes
              edges
              __typename
            }
            limitations { usage max __typename }
            __typename
          }
        }
      `,
      variables: patch,
    }),
  });

  const json = await res.json();
  if (json.errors) {
    console.error("GraphQL errors:", json.errors);
    throw new Error("savePatchGraph failed at transport level");
  }

  const { report, idsMapping } = json.data.result;
  if (!report.success) {
    console.error("savePatchGraph errors:", report.errors);
    throw new Error(`savePatchGraph failed: ${report.errors.join("\n")}`);
  }

  // New real IDs for just-created node/edge are in idsMapping
  console.log("Created (mapped) nodes:", idsMapping.nodes);
  console.log("Created (mapped) edges:", idsMapping.edges);
}

```

## Reset a graph

If you want to clear all nodes and edges while preserving the existing node/edge types and their colors, call `resetGraph` first. Then, use `savePatchGraph` with `create` blocks to re-populate the graph.

```typescript
async function resetGraphContents(graphId: string) {
  const jwt = await login(USERNAME, PASSWORD);

  const res = await fetch("https://graphcommons.com/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${jwt}`,
    },
    body: JSON.stringify({
      operationName: "resetGraph",
      query: `
        mutation resetGraph($id: String!) {
          result: resetGraph(id: $id) {
            report { success errors warnings __typename }
            __typename
          }
        }
      `,
      variables: { id: graphId },
    }),
  });

  const json = await res.json();
  const { report } = json.data.result;
  if (!report.success) {
    throw new Error(`resetGraph failed: ${report.errors.join("\n")}`);
  }
}

```

## Tips & Gotchas

* **Temp IDs in creates**: In `createGraph` and the `create` section of `savePatchGraph`, you can use any string IDs (e.g., `n_sam`, `et_works_at`). The server returns an **`idsMapping`** to translate these to real IDs. Store them if you’ll reference the same items later.
* **Referencing existing items**: When modifying existing nodes/edges, use the **real IDs** (from `idsMapping` or from a `getGraphById` read).
* **Positions**: Set positions with either the temp node IDs (during `createGraph`) or the real node IDs (when updating).
* **Types vs. Instances**: `nodeTypes`/`edgeTypes` define the schema. `nodes`/`edges` are your data. After a **reset**, types remain; nodes/edges are cleared.
* **Errors**: Always check `report.success` and surface `report.errors` in logs for faster debugging.

## Next steps

* Learn more about [GraphQL queries](https://graphql.org/learn/queries)
* Explore queries and mutations in the Graph Commons API with the [Apollo Explorer](https://studio.apollographql.com/sandbox/explorer?endpoint=https://graphcommons.com/graphql).
