diff --git a/docs/backend-sdk/java.mdx b/docs/backend-sdk/java.mdx deleted file mode 100644 index b0e92df82..000000000 --- a/docs/backend-sdk/java.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: 'Java' -description: 'Introduction to our Java SDK' ---- -## Requirements - -- Java 8 -- Maven - -## Installation - -If you use Maven, place the following within the `` tag in your pom.xml file: - -```XML - - dev.panora - panora-sdk - 0.0.1 - -``` - -If you use Gradle, paste the next line inside the dependencies block of your build.gradle file: - -```Gradle -implementation group: "dev.panora", name: "PanoraSDK", version: "0.0.1" -``` - -## Authentication - -To see whether an endpoint needs a specific type of authentication check the endpoint's documentation. - -### Bearer Authentication -The PanoraSDK API uses bearer tokens as a form of authentication. You can set the bearer token when initializing the SDK through the constructor: -```Java -PanoraSDK sdk = new PanoraSDK("YOUR_BEARER_TOKEN"); -``` - -Or through the `setBearerToken` method: -```Java -PanoraSDK sdk = new PanoraSDK(); -sdk.setBearerToken("YOUR_BEARER_TOKEN"); -``` - - -### List all connections to your app - -```java -package dev.panora.examples; - -import dev.panora.PanoraSDK; -import dev.panora.exceptions.ApiException; - -public class Main { - - public static void main(String[] args) { - PanoraSDK client = new PanoraSDK(System.getenv("PANORASDK_BEARER_TOKEN")); - try { - Object response = client.connectionsService.getConnections(); - System.out.println(response); - } catch (ApiException e) { - e.printStackTrace(); - } - } -} - -``` - -This will list all the connections available, across all users. You should get an object similar to this one below. [Read more about the `connection` object.](/connections/overview) -```json -{ - "id_connection": "6cd057cb-39df-44ce-9be8-ax9d167c3940", - "status": "valid", - "provider_slug": "hubspot", - "account_url": null, - "token_type": "oauth", - "access_token": "904570287538dddf72fd821e4d5cec51:66266ee62310752d4a243c12b133656edd5af42947a832f4439c710334e045e59782107d40e856c27e813b7a6ed068100376b3ff83d1c8237330ba034605dd846650524e6fcfb708e3f62b1401d8a0dc3d90022cdf9ad1c76fc9209f3a5d153f6e33bbb8f6642600a6c9a098e81fb1e2da0fdff0455b7823519fba195b5065b4319a314013e22f934c80e4f60bec4385989c92c2dd9036d19f720e85b10325c42dc8a035c363e279af0e4ab2c4cd016051c5b32bf6009bf0df0aa8565d048856", - "refresh_token": "904570287538dddf72fd821e4d5cec51:58d9c1492b908caef83885b467d1ab1ea9fc6994a59ed4392edbb5365b89a02a8a4995347d8ec37037192a96856e2c24", - "expiration_timestamp": "2023-12-20T18:44:44.869Z", - "created_at": "2023-12-10T18:20:06.275Z", - "id_project": "801f9ede-c698-4e66-a7fc-48d19eebaa4f", - "id_linked_user": "d7a0af02-0f9b-40a6-86a9-612dcfe341fe" -} -``` - - - diff --git a/docs/backend-sdk/python.mdx b/docs/backend-sdk/python.mdx index 2880ad9d2..d4aa3db34 100644 --- a/docs/backend-sdk/python.mdx +++ b/docs/backend-sdk/python.mdx @@ -1,62 +1,64 @@ --- -title: 'Python' -description: 'Introduction to our Python SDK' +title: "Python" +description: "Introduction to our Python SDK" --- ## Installing & instantiating the Python SDK -Install it with your favorite package manager, e.g.: ```bash pip install panorasdk ``` Instantiate the SDK: - -Go to your dashboard to get your API Key - + +Go to your dashboard to get your API Key ```python -sdk = PanoraSDK('YOUR_BEARER_TOKEN') +sdk = PanoraSDK('YOUR_API_KEY') ``` + Or through the `set_access_token` method: + ```python sdk = PanoraSDK() -sdk.set_access_token('YOUR_BEARER_TOKEN') +sdk.set_access_token('YOUR_API_KEY') ``` + You can also set it for each service individually: + ```python sdk = PanoraSDK() -sdk.main.set_access_token('YOUR_BEARER_TOKEN') +sdk.main.set_access_token('YOUR_API_KEY') ``` ### List all connections to your app ```python -from os import getenv -from pprint import pprint from panorasdk import PanoraSDK + sdk = PanoraSDK() -sdk.set_access_token(getenv("PANORASDK_ACCESS_TOKEN")) + +sdk.set_access_token("YOUR_API_KEY") + results = sdk.connections.get_connections() -pprint(vars(results)) +print(results) ``` -This will list all the connections available, across all users. You should get an object similar to this one below. [Read more about the `connection` object.](/connections/overview) +This will list all the connections available, across all users. You should get an object similar to this one below. Read more about the `connection` object here in the [API reference](/connections/overview) or the [glossary](/glossary/connection-object). + ```json { - "id_connection": "6cd057cb-39df-44ce-9be8-ax9d167c3940", - "status": "valid", - "provider_slug": "hubspot", - "account_url": null, - "token_type": "oauth", - "access_token": "904570287538dddf72fd821e4d5cec51:66266ee62310752d4a243c12b133656edd5af42947a832f4439c710334e045e59782107d40e856c27e813b7a6ed068100376b3ff83d1c8237330ba034605dd846650524e6fcfb708e3f62b1401d8a0dc3d90022cdf9ad1c76fc9209f3a5d153f6e33bbb8f6642600a6c9a098e81fb1e2da0fdff0455b7823519fba195b5065b4319a314013e22f934c80e4f60bec4385989c92c2dd9036d19f720e85b10325c42dc8a035c363e279af0e4ab2c4cd016051c5b32bf6009bf0df0aa8565d048856", - "refresh_token": "904570287538dddf72fd821e4d5cec51:58d9c1492b908caef83885b467d1ab1ea9fc6994a59ed4392edbb5365b89a02a8a4995347d8ec37037192a96856e2c24", - "expiration_timestamp": "2023-12-20T18:44:44.869Z", - "created_at": "2023-12-10T18:20:06.275Z", - "id_project": "801f9ede-c698-4e66-a7fc-48d19eebaa4f", - "id_linked_user": "d7a0af02-0f9b-40a6-86a9-612dcfe341fe" + "id_connection": "6cd057cb-39df-44ce-9be8-ax9d167c3940", + "status": "valid", + "provider_slug": "hubspot", + "account_url": null, + "token_type": "oauth", + "access_token": "904570287538dddf72fd821e4d5cec51:66266ee62310752d4a243c12b133656edd5af42947a832f4439c710334e045e59782107d40e856c27e813b7a6ed068100376b3ff83d1c8237330ba034605dd846650524e6fcfb708e3f62b1401d8a0dc3d90022cdf9ad1c76fc9209f3a5d153f6e33bbb8f6642600a6c9a098e81fb1e2da0fdff0455b7823519fba195b5065b4319a314013e22f934c80e4f60bec4385989c92c2dd9036d19f720e85b10325c42dc8a035c363e279af0e4ab2c4cd016051c5b32bf6009bf0df0aa8565d048856", + "refresh_token": "904570287538dddf72fd821e4d5cec51:58d9c1492b908caef83885b467d1ab1ea9fc6994a59ed4392edbb5365b89a02a8a4995347d8ec37037192a96856e2c24", + "expiration_timestamp": "2023-12-20T18:44:44.869Z", + "created_at": "2023-12-10T18:20:06.275Z", + "id_project": "801f9ede-c698-4e66-a7fc-48d19eebaa4f", + "id_linked_user": "d7a0af02-0f9b-40a6-86a9-612dcfe341fe" } ``` - - diff --git a/docs/backend-sdk/typescript.mdx b/docs/backend-sdk/typescript.mdx index e3649c2a1..433527762 100644 --- a/docs/backend-sdk/typescript.mdx +++ b/docs/backend-sdk/typescript.mdx @@ -1,33 +1,30 @@ --- -title: 'TypeScript' -description: 'Introduction to our Typescript SDK' +title: "TypeScript" +description: "Introduction to our Typescript SDK" --- - ## Installing & instantiating the Typescript SDK -Install it with your favorite package manager, e.g.: ```bash npm i @panora/typescript-sdk ``` Instantiate the SDK: - -Go to your dashboard to get your API Key - + +Go to your dashboard to get your [API Key](/core-concepts/auth) ```javascript -import { PanoraSDK } from '@panora/typescript-sdk'; +import { PanoraSDK } from "@panora/typescript-sdk"; -const sdk = new PanoraSDK('YOUR_API_KEY'); +const sdk = new PanoraSDK("YOUR_API_KEY"); ``` ### List all connections to your app ```javascript -import { PanoraSDK } from '@panora/typescript-sdk'; +import { PanoraSDK } from "@panora/typescript-sdk"; -const sdk = new PanoraSDK('YOUR_API_KEY'); +const sdk = new PanoraSDK("YOUR_API_KEY"); (async () => { const result = await sdk.connections.getConnections(); @@ -35,21 +32,20 @@ const sdk = new PanoraSDK('YOUR_API_KEY'); })(); ``` -This will list all the connections available, across all users. You should get an object similar to this one below. [Read more about the `connection` object.](/connections/overview) +This will list all the connections available, across all users. You should get an object similar to this one below. Read more about the `connection` object here in the [API reference](/connections/overview) or the [glossary](/glossary/connection-object). + ```json { - "id_connection": "6cd057cb-39df-44ce-9be8-ax9d167c3940", - "status": "valid", - "provider_slug": "hubspot", - "account_url": null, - "token_type": "oauth", - "access_token": "904570287538dddf72fd821e4d5cec51:66266ee62310752d4a243c12b133656edd5af42947a832f4439c710334e045e59782107d40e856c27e813b7a6ed068100376b3ff83d1c8237330ba034605dd846650524e6fcfb708e3f62b1401d8a0dc3d90022cdf9ad1c76fc9209f3a5d153f6e33bbb8f6642600a6c9a098e81fb1e2da0fdff0455b7823519fba195b5065b4319a314013e22f934c80e4f60bec4385989c92c2dd9036d19f720e85b10325c42dc8a035c363e279af0e4ab2c4cd016051c5b32bf6009bf0df0aa8565d048856", - "refresh_token": "904570287538dddf72fd821e4d5cec51:58d9c1492b908caef83885b467d1ab1ea9fc6994a59ed4392edbb5365b89a02a8a4995347d8ec37037192a96856e2c24", - "expiration_timestamp": "2023-12-20T18:44:44.869Z", - "created_at": "2023-12-10T18:20:06.275Z", - "id_project": "801f9ede-c698-4e66-a7fc-48d19eebaa4f", - "id_linked_user": "d7a0af02-0f9b-40a6-86a9-612dcfe341fe" + "id_connection": "6cd057cb-39df-44ce-9be8-ax9d167c3940", + "status": "valid", + "provider_slug": "hubspot", + "account_url": null, + "token_type": "oauth", + "access_token": "904570287538dddf72fd821e4d5cec51:66266ee62310752d4a243c12b133656edd5af42947a832f4439c710334e045e59782107d40e856c27e813b7a6ed068100376b3ff83d1c8237330ba034605dd846650524e6fcfb708e3f62b1401d8a0dc3d90022cdf9ad1c76fc9209f3a5d153f6e33bbb8f6642600a6c9a098e81fb1e2da0fdff0455b7823519fba195b5065b4319a314013e22f934c80e4f60bec4385989c92c2dd9036d19f720e85b10325c42dc8a035c363e279af0e4ab2c4cd016051c5b32bf6009bf0df0aa8565d048856", + "refresh_token": "904570287538dddf72fd821e4d5cec51:58d9c1492b908caef83885b467d1ab1ea9fc6994a59ed4392edbb5365b89a02a8a4995347d8ec37037192a96856e2c24", + "expiration_timestamp": "2023-12-20T18:44:44.869Z", + "created_at": "2023-12-10T18:20:06.275Z", + "id_project": "801f9ede-c698-4e66-a7fc-48d19eebaa4f", + "id_linked_user": "d7a0af02-0f9b-40a6-86a9-612dcfe341fe" } ``` - - diff --git a/docs/core-concepts/auth.mdx b/docs/core-concepts/auth.mdx index e9a1b89a0..ab2ea49d2 100644 --- a/docs/core-concepts/auth.mdx +++ b/docs/core-concepts/auth.mdx @@ -1,16 +1,17 @@ --- title: "Authentication" description: "Learn how to authenticate your requests to the Panora API." -icon: "code" +icon: "key" --- This guide assumes you have a Panora account, or a working self-hosted version -### The Panora API uses uses two elements to indentify requests: API keys and a connection_token. +### The Panora API uses uses two elements to indentify requests. -**API Keys** are used to authenticate yourself to our backend, while a **connection_token** serves to identify which of your user's you're making API calls for. +- `API key` which is a Bearer Acess Token used to authenticate yourself to our backend. +- `connection_token` which serves to identify which of your user's you're making API calls for. Depending on your setup, you should make requests to one of those endpoints: @@ -35,7 +36,7 @@ Depending on your setup, you should make requests to one of those endpoints: - Go to your dashboard, and visit the API Keys section. Click the Create New Key button. + Go to your dashboard, and visit the _API Keys_ section. Click the `Create New Key` button. @@ -45,13 +46,13 @@ Depending on your setup, you should make requests to one of those endpoints: Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth. - + A `connection_token` is created everytime a user connects an account to your platform. - You need to setup a webhook and listen to events `connection.created` to catch a `connection_token`. - `connection_token` is a string, located in the "data" object, inside a `connection.created` event. + You need to setup a webhook and listen to events tagged as `connection.created` to catch a it. + The `connection_token` is a string, located in the _data_ object, inside a `connection.created` event. - Read about webhooks [here](/webhooks/overview) + Read more about webhooks [here](/webhooks/overview) ```json Example connection.created event { @@ -59,7 +60,7 @@ Depending on your setup, you should make requests to one of those endpoints: "type": "connection.created", "data": { "id" : "6fc7017a-6596-4b05-81b6-595296a59f87" - "connection_token": "CONNECTION_TOKEN_HERE", + "connection_token": "MY_CONNECTION_TOKEN", "provider_slug": "hubspot", ... }, @@ -76,99 +77,97 @@ Depending on your setup, you should make requests to one of those endpoints: Take a look at these examples to understand the concept. We also recommend practising by looking at the specific verticals you want to integrate. - - - - ```javascript TypeScript SDK - import { PanoraSDK } from '@panora/typescript-sdk'; - const sdk = new PanoraSDK({ accessToken: "MY_API_KEY" }); - ``` - - ```python Python SDK - sdk = PanoraSDK('YOUR_BEARER_TOKEN') - ``` - - ```java Java SDK - PanoraSDK sdk = new PanoraSDK("YOUR_BEARER_TOKEN"); - ``` - - - - - In this example, we will create a contact in a CRM. Visit other sections of the documentation to find category-specific examples - - - ```curl curl - curl --request POST \ - --url https://api.panora.dev/crm/contacts \ - --header 'Authorization: Bearer dfsdf' \ - --header 'Content-Type: application/json' \ - --header 'x-connection-token: ' \ - --data '{ - "first_name": "Mark", - "last_name": "Zuckerbeg", - "email_addresses": [ + + You can find the Typescript SDK on NPM + [here](https://www.npmjs.com/package/@panora/sdk-typescript) + + In this example, we will create a contact in a CRM. Visit other sections of the [documentation](/ticketing/try) to find category-specific examples. + + ```javascript TypeScript + import { PanoraSDK } from '@panora/sdk-typescript'; + + const sdk = new PanoraSDK({ accessToken: "MY_API_KEY" }); + + const input = { + first_name: 'tom', + last_name: 'jedusor', + email_addresses: [ { - "email_address": "mark@zuckerberg.com", - "email_address_type": "personal", - "owner_type": "contact" + 'email_address': 'tom@jedusor.com', + 'email_address_type': 'PERSONAL' } - ], - "phone_numbers": [ + ], + phone_numbers: [ { - "phone_number": "+33694837462", - "phone_type": "personal", - "owner_type": "contact" + 'phone_number': '+33650438278', + 'phone_type': 'MOBILE' } - ], - "field_mappings": {} - }' - ``` - - ```javascript TypeScript - import { PanoraSDK } from '@panora/typescript-sdk'; - const sdk = new PanoraSDK({ accessToken: "MY_API_KEY" }); - - (async () => { - const input = { - email_addresses: [], - field_mappings: {}, - first_name: 'first_name', - last_name: 'last_name', - phone_numbers: [], - }; - const result = await sdk.crmContact.addContact(input, 'connection_token', { - remoteData: true, - }); - console.log(result); - })(); - ``` - - ```python Python - from os import getenv - from pprint import pprint + ], + }; + + const result = await sdk.crmContact.addContact(input, 'MY_USER_CONNECTION_TOKEN', { + remoteData: true, + }); + + console.log(result); + ``` + + ```python Python from panorasdk import PanoraSDK + sdk = PanoraSDK() - sdk.set_access_token(getenv("YOUR_API_KEY")) + + sdk.set_access_token("MY_API_KEY") + request_body = { - 'email_addresses': [], - 'field_mappings': {}, - 'first_name': 'first_name', - 'last_name': 'last_name', - 'phone_numbers': [] + 'first_name': 'tom', + 'last_name': 'jedusor', + 'email_addresses': [ + { + 'email_address': 'tom@jedusor.com', + 'email_address_type': 'PERSONAL' + } + ], + 'phone_numbers': [ + { + 'phone_number': '+33650438278', + 'phone_type': 'MOBILE' + } + ] } + results = sdk.crm_contact.add_contact( request_input = request_body, - connection_token = 'USER_CONNECTION_TOKEN', + connection_token = 'MY_USER_CONNECTION_TOKEN', remote_data = True ) - pprint(vars(results)) + print(results) + ``` - ``` - - - - + ```shell curl + curl --request POST \ + --url https://api.panora.dev/crm/contacts \ + --header 'Authorization: Bearer ' \ + --header 'Content-Type: application/json' \ + --header 'x-connection-token: ' \ + --data '{ + "first_name": "tom", + "last_name": "jedusor", + "email_addresses": [ + { + "email_address": "tom@jedusor.com", + "email_address_type": "PERSONAL" + } + ], + "phone_numbers": [ + { + "phone_number": "+33650438278", + "phone_type": "MOBILE" + } + ] + }' + ``` + Read more about our SDKs in [TypeScript](/backend-sdk/typescript), [Java](/backend-sdk/java), [Python](/backend-sdk/python) diff --git a/docs/core-concepts/custom-fields.mdx b/docs/core-concepts/custom-fields.mdx index d140abdb1..05471eba2 100644 --- a/docs/core-concepts/custom-fields.mdx +++ b/docs/core-concepts/custom-fields.mdx @@ -1,18 +1,20 @@ --- -title: 'Custom Fields Mapping' +title: "Custom Fields Mapping" description: "Easily extend Panora's unified model to recognize specific fields" -icon: 'code' +icon: "code" --- ## Overview -Creating a Field Mapping involves two majors actions: -Defining a custom field on Panora's side, and then mapping it to a field from your customer's software. +Creating a `Field Mapping` involves two majors actions: + +- Defining a custom field on Panora's side +- Mapping it to a field from your customer's software. - Login to your account dashboard and click `Configuration` and go to section `Field Mapping`. + Login to your account dashboard and click on _Configuration_ section and go to tab **Field Mapping**. @@ -20,16 +22,16 @@ Defining a custom field on Panora's side, and then mapping it to a field from yo - Now, move to the `Map Fields` section. To finish the mapping, select the custom field you just created, and fill the fields `Provider` and Linked User ID. - + +Now, move to the `Map Fields` section. To finish the mapping, select the custom field you just created, and fill the fields `Provider` and Linked User ID. + + - You will now find all the fields your user has in its software. Pick the one that you want to map to. - - - - +You will now find all the fields your user has in its software. Pick the one that you want to map to. + + diff --git a/docs/core-concepts/magic-links.mdx b/docs/core-concepts/magic-links.mdx index 0f5b02ed5..f421e4b24 100644 --- a/docs/core-concepts/magic-links.mdx +++ b/docs/core-concepts/magic-links.mdx @@ -1,8 +1,9 @@ --- -title: 'Magic Links' -description: 'Use Magic Links to invite your users to grant you access to their data without a dedicated website. Create a full connection flow in just a few clicks. No code required.' -icon: 'wand-magic-sparkles' +title: "Magic Links" +description: "Use Magic Links to invite your users to grant you access to their data without a dedicated website. Create a full connection flow in just a few clicks. **No code required.**" +icon: "wand-magic-sparkles" --- + - -Login to your account dashboard - +Login to your account dashboard - -Go to section Connections and local button `Create a Magic Link` - +Go to section _Connections_ and local button `Create a Magic Link` - -Click `Create a Unique Magic Link` - +Click `Create a Unique Magic Link` -You'll be asked for two informations: an email and an `Origin User Identifier`. -The `Origin User Identifier` is the id of the user you're inviting, as represented in your systems. + You'll be asked for two informations: an `Origin User Email` and an `Origin + User Identifier`. The `Origin User Identifier` is the id of the user you're + inviting, as represented in your systems. - -Click Generate. You can now share the link! - +Click `Generate`. You can now share the link! -The connection will show as `status` until the user connects to a platform. -We recommend listening to webhooks to get notified once a user connects. \ No newline at end of file +Once the user successfully completes the granting auth flow, the connection will have a `status` value of `valid`. +We recommend listening to [webhooks](/webhooks/overview) to get notified once a user connects. diff --git a/docs/core-concepts/sync-strategies.mdx b/docs/core-concepts/sync-strategies.mdx index 3ffb9b0d9..2b7e8443c 100644 --- a/docs/core-concepts/sync-strategies.mdx +++ b/docs/core-concepts/sync-strategies.mdx @@ -1,14 +1,13 @@ --- -title: 'Sync Strategies' -description: 'Panora gives you flexibility about how often your data will get pulled from sources: periodic or real-time' -icon: 'gear' +title: "Sync Strategies" +description: "Panora gives you flexibility about how often your data will get pulled from sources: periodic or real-time" +icon: "rotate" --- ## Periodic Sync - - ## Real Time Webhooks ### Auto-configure Webhooks -### Configure webhooks for aggregation \ No newline at end of file + +### Configure webhooks for aggregation diff --git a/docs/crm/quick-start.mdx b/docs/crm/quick-start.mdx index 621ce36d9..8b0b46aea 100644 --- a/docs/crm/quick-start.mdx +++ b/docs/crm/quick-start.mdx @@ -35,7 +35,7 @@ description: "Read and write data to multiple CRM platforms using a single API" In this example, we will create a contact in a CRM. Visit other sections of the documentation to find category-specific examples - ```curl curl + ```shell curl curl --request POST \ --url https://api.panora.dev/crm/contacts \ --header 'Authorization: Bearer dfsdf' \ diff --git a/docs/glossary/connection-object.mdx b/docs/glossary/connection-object.mdx new file mode 100644 index 000000000..cb6f7e40e --- /dev/null +++ b/docs/glossary/connection-object.mdx @@ -0,0 +1,30 @@ +--- +title: "Connection Object" +description: "Understand the connection object." +icon: "link" +--- + +## The `connection` object represents an access right to a end-user's software. + +```json JSON +{ + "id_connection": "6cd057cb-39df-44ce-9be8-ab9d167c3940", + "status": "valid", + "connection_token": "e6d46c3763dc3e85fb078eae952654bd4f4861b313b7ccae201b91aa37532b71", + "provider_slug": "hubspot", + "account_url": null, + "expiration_timestamp": "2023-12-20T18:44:44.869Z", + "created_at": "2023-12-10T18:20:06.275Z", + "id_project": "801f9ede-c698-4e66-a7fc-48d19eebaa4f", + "id_linked_user": "d7a0af02-0f9b-40a6-86a9-612dcfe341fe" +} +``` + +A `connection` is created once a user completes the auth granting access flow (through [magic-link](/core-concepts/magic-links) or inside [code](/core-concepts/embedded-catalog)). + +`connection_token` is **mandatory** for each **unified API request**. + +### It helps Panora get important data + +- metadata about the software where the data has to be fetched/created (e.g _provider & vertical_). +- private encrypted credentials **(access_token/refresh_token)** to make the requests on behalf of the user. diff --git a/docs/glossary/linked-account-object.mdx b/docs/glossary/linked-account-object.mdx new file mode 100644 index 000000000..d13dfe9fd --- /dev/null +++ b/docs/glossary/linked-account-object.mdx @@ -0,0 +1,22 @@ +--- +title: "Linked Account Object" +description: "Understand the linked account object." +icon: "user" +--- + +## The `linked-user` object represents a user entity inside our system. + +```json JSON +{ + "id_linked_user": "6cd057cb-39df-44ce-9be8-ab9d167c3940", + "linked_user_origin_id": "acme-id-be129f-4nce-uh22", + "alias": "acme", + "id_project": "6cd057cb-39df-44ce-9be8-ab9d167c3940" +} +``` + +- `linked_user_origin_id` is the **id** of the user inside your system. +- `alias` is the name of your system/company. It holds information about **user's data** + that exist in your **own product**. + +The idea is to have a deep copy of all your user's information inside our own database. diff --git a/docs/marketing_automation/introduction.mdx b/docs/marketing_automation/introduction.mdx deleted file mode 100644 index 293c5acda..000000000 --- a/docs/marketing_automation/introduction.mdx +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: "Coming Soon" -description: "You're a bit early!" ---- - -## [Click here](https://tally.so/r/3Exrdl?integration_category=marketingautomation) to be notified once this feature is live! diff --git a/docs/mint.json b/docs/mint.json index eb4061497..0672ad313 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -54,10 +54,6 @@ "name": "CRM", "url": "crm" }, - { - "name": "Marketing Automation", - "url": "marketingautomation" - }, { "name": "Ticketing", "url": "ticketing" @@ -113,12 +109,6 @@ } ] }, - { - "group": "Marketing Automation", - "pages": [ - "marketingautomation/introduction" - ] - }, { "group": "Ticketing", "pages": [ @@ -382,19 +372,19 @@ "core-concepts/auth", "core-concepts/magic-links", "core-concepts/custom-fields", - "core-concepts/sync-strategies", - { - "group": "Connections", - "pages": ["connections/overview", "connections/api/list"] - } + "core-concepts/sync-strategies" ] }, + { + "group": "Glossary", + "pages": ["glossary/connection-object", "glossary/linked-account-object"] + }, { "group": "Devtools", "pages": [ { "group": "SDKs", - "pages": ["backend-sdk/typescript", "backend-sdk/python" , "backend-sdk/java"] + "pages": ["backend-sdk/typescript", "backend-sdk/python"] } ] }, @@ -416,7 +406,6 @@ "open-source/contributors" ] }, - { "group": "Support", "pages": [ diff --git a/docs/open-source/contributors.mdx b/docs/open-source/contributors.mdx index a3af4df48..3f9154f41 100644 --- a/docs/open-source/contributors.mdx +++ b/docs/open-source/contributors.mdx @@ -13,215 +13,231 @@ We made a docker file that builds Panora from sources, specifically to help you Execute these from your Panora's repo root folder - - -```bash -cp .env.example .env -``` - - - -1. You don't need Stytch variables if you selfhost, it's only used in cloud version of Panora so you can discard the stytch variables. -2. To provide 3rd party variables you have the option to manage a 3rd party oAuth app by yourself by setting the credentials as such: - -(You must create by hand inside the 3rd party a custom oAuth2 app and paste the credentials using the following form) - - `PROVIDER_VERTICAL_SOFTWAREMODE_ATTRIBUTE` - where - ``` - PROVIDER is any 3rd party name - VERTICAL is for example { CRM, TICKETING, MARKETINGAUTOMATION, ...} - SOFTWAREMODE is { CLOUD, ONPREMISE } - ATTRIBUTE is for example { CLIENT_ID, CLIENT_SECRET, SUBDOMAIN, ... } - ``` - i.e `HUBSPOT_CRM_CLOUD_CLIENT_ID` - - - - - ```bash - rm -rf node_modules .pnpm-store ./packages/api/dist ./packages/api/node_modules ./apps/webapp/node_modules ./apps/frontend_snippet/node_modules - ``` - - - - ```bash - echo -e "node-linker=hoisted\npackage-import-method=clone-or-copy" > .npmrc - ``` - - - - ```bash - docker compose -f docker-compose.dev.yml up - ``` - -That's all! You can find the backend and other services running at their usual location. Editing code locally will immediately reflect. + + ```bash + cp .env.example .env + ``` + + + + You must create manually a custom oAuth2 app inside the 3rd party and copy the + critical values (_client id and client secret_) + + You have the option to manage a custom 3rd party oAuth app. + + **Each custom 3rd party environment variable must be of the form `PROVIDER_VERTICAL_SOFTWAREMODE_ATTRIBUTE` where** + + - `PROVIDER` is any 3rd party name + - `VERTICAL` is for example [CRM, TICKETING, MARKETINGAUTOMATION, ...] + - `SOFTWAREMODE` is [ CLOUD, ONPREMISE ] + - `ATTRIBUTE` is for example [ CLIENT_ID, CLIENT_SECRET, SUBDOMAIN, ... ] + + _Example_ : + + - `HUBSPOT_CRM_CLOUD_CLIENT_ID = client_id_value_pasted_from_hubspot_developer_app` + - `HUBSPOT_CRM_CLOUD_CLIENT_SECRET = client_secret_value_pasted_from_hubspot_developer_app` + + + + ```bash + rm -rf node_modules .pnpm-store ./packages/api/dist ./packages/api/node_modules ./apps/webapp/node_modules ./apps/frontend_snippet/node_modules + ``` + + + ```bash + echo -e "node-linker=hoisted\n package-import-method=clone-or-copy" > .npmrc + ``` + + + ```bash + docker compose -f docker-compose.dev.yml up + ``` + + That's all ! You can find the backend and other services running at their usual location. Editing code locally will **immediately** reflect. ## Adding new Integrations ✨ Make sure you are inside `packages/api/src` where the server lives ! -# You want to add a new 3rd Party not yet supported ? 🧑‍🎤 +### You want to add a new 3rd Party not yet supported ? 🧑‍🎤 _Ie: Slack, Hubspot, Jira, Shopify ..._ First choose wisely which vertical the 3rd party belongs to among these: -- crm -- ticketing -- accounting -- ats -- filestorage -- hris -- marketingautomation +- `crm` +- `ticketing` +- `accounting` +- `ats` +- `filestorage` +- `hris` +- `marketingautomation` + + + For the sake of the guide, now on we'll consider adding a 3rd party belonging + to the `crm` vertical. + -For the sake of the guide, now on we'll consider adding a 3rd party belonging to the `crm` vertical. +# Step 1: Ensure 3rd party metadata is set -## 1. Look into the `packages/shared/src/utils.ts` file and check if the provider you want to build has its metadata set inside the `providersConfig` object. +Look into the `packages/shared/src/utils.ts` file and check if the provider you want to build has its metadata set inside the `providersConfig` object. -It should be available (if not contact Panora team) with `active` field set to `false` meaning the integration has not been built. +It should be available (if not [contact us](https://app.cal.com/rflih/30)) with `active` field set to `false` meaning the integration has not been built. Actually an integration is built in 2 parts : -- the authentication part (oauth, api key, basic etc) which is built by the Panora team -- the service integration where the mapping is created with our unified model which is what you'll build +- the **authentication part** (oauth, api key, basic etc) which is built by the Panora team +- the **service integration** where the mapping is created with our unified model which is what you'll build -## 2. Build your provider service +# Step 2: Build your provider service -# You want to map a common object to your new 3rd Party ? 👩‍🎤 +### You want to map a common object to your new 3rd Party ? 👩‍🎤 _Ie: Contact, Ticket, Deal, Company ..._ For the sake of this guide, let's map the common object `contact` under `crm` vertical to _my3rdParty_ (in reality it would be a real 3rd party name). -### DISCLAIMER: an integration is considered valid when all common objects have been mapped. Then, after the PR is accepted we'll be able to set `active` field to `true` inside `providersConfig`. - -## 1. Add a new service to map your common object to your 3rd party - -Create a new service folder with the name of your 3rd party. Let's call it _my3rdParty_. - -`cd crm/contact/services/my3rdParty` - -You'll now create 3 files. - -`index.ts` \_where your service is created and direct interaction with your 3rd party API is handled - -It must implement the `IContactService` interface. - -```ts -export interface IContactService { - addContact( - contactData: DesunifyReturnType, - linkedUserId: string - ): Promise>; - - syncContacts( - linkedUserId: string - ): Promise>; -} -``` - -```ts -@Injectable() -export class My3rdPartyService implements IContactService { - constructor( - private prisma: PrismaService, - private logger: LoggerService, - private cryptoService: EncryptionService, - private registry: ServiceRegistry, - ) { - this.logger.setContext( - CrmObject.contact.toUpperCase() + ':' + My3rdPartyService.name, - ); - this.registry.registerService('my3rdParty', this); - } - async addContact( - contactData: 3rdPartyContactInput, - linkedUserId: string, - ): Promise> {} - - async syncContacts( - linkedUserId: string, - ): Promise> {} -} -``` - -Check other implementations under `/crm/contacts/services` to fill the core functions. - -The keen readers may have noticed `3rdPartyContactInput` and `3rdPartyContactOutput`. - -This is where `types.ts` comes in: - -Go to the 3rd party API and insert the correct types asked by the API. - -```ts -export interface 3rdPartyContact { - //INSERT THE CORRECT TYPE HERE -} -export type 3rdPartyContactInput = Partial<3rdPartyContact>; -export type 3rdPartyContactOutput = 3rdPartyContactInput; -``` - -Last but not least, inside `mappers.ts` you have to build the mappings between our unified common object `contact` and your third party specific type `3rdPartyContact`. - -It must implement `IContactMapper` interface. - -```ts -export interface IContactMapper { - desunify( - source: UnifiedContactInput, - customFieldMappings?: { - slug: string; - remote_id: string; - }[] - ): DesunifyReturnType; - - unify( - source: OriginalContactOutput | OriginalContactOutput[], - customFieldMappings?: { - slug: string; - remote_id: string; - }[] - ): UnifiedContactOutput | UnifiedContactOutput[]; -} -``` - -```ts -export class My3rdPartyMapper implements IContactMapper { - desunify( - source: UnifiedContactInput, - customFieldMappings?: { - slug: string; - remote_id: string; - }[], - ): 3rdPartyContactInput {} - - unify( - source: 3rdPartyContactOutput | 3rdPartyContactOutput[], - customFieldMappings?: { - slug: string; - remote_id: string; - }[], - ): UnifiedContactOutput | UnifiedContactOutput[] {} -} -``` - -Check other implementations under `/crm/contacts/services` to fill the core functions. - -## 2. Enable your new service - -To make sure the service is enabled, dependencies and imports must be added. -We built a script that does it in seconds. You can execute the given command from the root directory of Panora. - -```bash -cd packages/api && pnpm install && pnpm run validate-connectors --vertical="crm" --objectType="contact" -``` - -The script will automatically scan the `/crm/contact/services` folder and detect any new service folder so all dependencies and imports are updated across the codebase. - -### Congrats Hero ! 🦸‍♀️ - -### You now have built a new integration with Panora - -### NB: The development kit to add integrations out of the blue is coming soon 🎸 + + **An integration is considered valid when all common objects have been mapped. + Then, after the PR is accepted we'll be able to set `active` field to `true` + inside `providersConfig`** + + + + + Create a new service folder with the name of your 3rd party. Let's call it _my3rdParty_. + + ```bash + cd crm/contact/services/my3rdParty + ``` + + You'll now create 3 files : + + - `index.ts` where your service is created and direct interaction with your 3rd party API is handled + - `types.ts` where the 3rd party specific API types are defined + - `mappers.ts` where the mapping between our unified common model and the 3rd party one is handled + + + + It must implement the `IContactService` interface. + ```ts + export interface IContactService { + addContact( + contactData: DesunifyReturnType, + linkedUserId: string + ): Promise>; + + syncContacts( + linkedUserId: string + ): Promise>; + } + ``` + + ```ts + @Injectable() + export class My3rdPartyService implements IContactService { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + private registry: ServiceRegistry, + ) { + this.logger.setContext( + CrmObject.contact.toUpperCase() + ':' + My3rdPartyService.name, + ); + this.registry.registerService('my3rdParty', this); + } + async addContact( + contactData: 3rdPartyContactInput, + linkedUserId: string, + ): Promise> {} + + async syncContacts( + linkedUserId: string, + ): Promise> {} + } + ``` + Check other implementations under `/crm/contacts/services` to fill the core functions. + + + The keen readers may have noticed `3rdPartyContactInput` and `3rdPartyContactOutput`. + This is where `types.ts` comes in:
+ Go to the 3rd party API and insert the correct types asked by the API. + ```ts + export interface 3rdPartyContact { + //INSERT THE CORRECT TYPE HERE + } + export type 3rdPartyContactInput = Partial<3rdPartyContact>; + export type 3rdPartyContactOutput = 3rdPartyContactInput; + ``` +
+ + Last but not least, inside `mappers.ts` you have to build the mappings between our unified common object `contact` and your third party specific type `3rdPartyContact`. + + It must implement `IContactMapper` interface. + + ```ts + export interface IContactMapper { + desunify( + source: UnifiedContactInput, + customFieldMappings?: { + slug: string; + remote_id: string; + }[] + ): DesunifyReturnType; + + unify( + source: OriginalContactOutput | OriginalContactOutput[], + customFieldMappings?: { + slug: string; + remote_id: string; + }[] + ): UnifiedContactOutput | UnifiedContactOutput[]; + } + ``` + + ```ts + export class My3rdPartyMapper implements IContactMapper { + desunify( + source: UnifiedContactInput, + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): 3rdPartyContactInput {} + + unify( + source: 3rdPartyContactOutput | 3rdPartyContactOutput[], + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): UnifiedContactOutput | UnifiedContactOutput[] {} + } + ``` + + Check other implementations under `/crm/contacts/services` to fill the core functions. + +
+ +
+ + + To make sure the service is enabled, dependencies and imports must be added.
+ We built a script that does it in seconds. You can execute the given command from the root directory of Panora. + + ```bash + cd packages/api && pnpm install && pnpm run validate-connectors --vertical="crm" --objectType="contact" + ``` + + The script will automatically scan the `/crm/contact/services` folder and detect any new service folder so all dependencies and imports are updated across the codebase. + +
+
+ +### Congrats, you now have built a new integration with Panora ! 🦸‍♀️ + + + Nb: The development kit to add integrations out of the blue is coming soon 🎸 + diff --git a/docs/open-source/glossary.mdx b/docs/open-source/glossary.mdx deleted file mode 100644 index 866abaf5e..000000000 --- a/docs/open-source/glossary.mdx +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: "Glossary" -description: "We welcome all contributions to Panora; this glossary is meant for people aiming to build core features" -icon: "star" ---- - -## Introduction - -### The source of truth - -The `/packages/shared/src/utils.ts` file contains the most important object of the project which is `providersConfig`. - -```ts -export const providersConfig: ProvidersConfig = { - 'crm': { - 'hubspot': { - scopes: 'crm.objects.contacts.read crm.objects.contacts.write crm.schemas.deals.read crm.schemas.deals.write crm.objects.deals.read crm.objects.deals.write crm.objects.companies.read crm.objects.companies.write crm.objects.owners.read settings.users.read settings.users.write settings.users.teams.read settings.users.teams.write', - authBaseUrl: 'https://app-eu1.hubspot.com/oauth/authorize', - logoPath: "https://assets-global.website-files.com/6421a177cdeeaf3c6791b745/64d61202dd99e63d40d446f6_hubspot%20logo.png", - description: "Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users", - apiUrl: 'https://api.hubapi.com', - customPropertiesUrl: '/properties/v1/contacts/properties', - authStrategy: AuthStrategy.oauth2 - }, - .... - }, - 'ticketing': { - 'zendesk': { - scopes: 'read write', - authBaseUrl: '/oauth/authorizations/new', - logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRNKVceZGVM7PbARp_2bjdOICUxlpS5B29UYlurvh6Z2Q&s', - description: "Sync & Create accounts, tickets, comments, attachments, contacts, tags, teams and users", - apiUrl: '/api/v2', - authStrategy: AuthStrategy.oauth2 - }, - .... - }, - .... -} -``` - -where - -- `authBaseUrl` is the api endpoint to authorize oauth connections if the provider has `authStrategy` == `AuthStrategy.oauth2` -- `logoPath` is the logo address displayed across Panora -- `apiUrl`is the base api endpoint used -- `authStrategy` is the authentication strategy used, it is of type authStrategy - -```ts -export enum AuthStrategy { - oauth2, - api_key, - basic, -} -``` - -DISCLAIMER: it may be updated in the future if other auth methods are figured out. - -### The authentication flow - -By default, we focused the core on building the oAuth2 authentication strategy. -But other strategies exist as well. - -All utils data could be found inside `/packages/shared/src/envConfig.ts` - -The important thing to note is the `type` string variable. - -We handle all connections strategies logic in the `packages/api/src/@core/connections-strategies`. - -One may want to call either - -- `https://${PANORA_API_URL}/connections-strategies/getCredentials` (used to get either custom credentials or default managed panora environment variables as a fallback) - or -- `https://${PANORA_API_URL}/connections-strategies/createConnectionStrategy` (used in the webapp to let clients add custom connections credentials) - -Both endpoints ask for a `type` variable argument which is a `string`. - -## IT IS VERY IMPORTANT TO MAKE SURE THE FORMAT CONVENTION IS AS FOLLOWS IN UPPERCASE: - -`{PROVIDERNAME}_{VERTICALNAME}_{SOFTWAREMODE}_{AUTHMODE}` where -`PROVIDERNAME` is the name of the provider -`VERTICALNAME` is the vertical the provider belongs to -`SOFTWAREMODE` is the software mode the client wants to run the provider on (onpremise, cloud). By default, set it to `CLOUD`. -`AUTHMODE` is the authentication strategy of the provider (For now we have => OAUTH, API, BASIC) - -// i.e HUBSPOT_CRM_CLOUD_OAUTH -// i.e ZENDESK_TICKETING_CLOUD_OAUTH - -You'll find this type in .env files, and in some db tables. - -### The authentication contributor guide - -If you don't see your provider inside the `providersConfig` object within the file `/packages/shared/src/utils.ts` then you may get in touch with Panora team members or build it yourself. - -Here are the steps to do so: - -# 1. Add the provider metadata to `providersConfig` object - -Choose the right vertical and add it given that it has to contain these potential fields: - -```ts -export type ProviderConfig = { - scopes: string; - authBaseUrl: string; - logoPath: string; - description: string; - active?: boolean; - apiUrl: string; - customPropertiesUrl?: string; - authStrategy?: AuthStrategy; -}; -``` - -If `authStrategy` is not `AuthStrategy.oauth2`, set `authBaseUrl` to blank. - -NB: Some providers may use subdomains instead of plain auth api endpoints (i.e https://my_panora_domain/auth) -In this case just write `authBaseUrl: /auth` with a starting `/`. -It is important to start with a `/` as our code use that to detect if subomain is needed across the project. - -# 2. Update the construction of the authentication url (used in the frontend) - -Modify the `/packages/shared/src/authUrl.ts` file. - -Right now we only coded the oAuth2 side so we'll focus on it here. - -Update `handleOAuth2Url` function and switch/case found inside if specific params are needed for your provider. - -# 3. Generate boilerplate and code the service to build the connection - -Now you have to build the connection code inside `/packages/api/@core/src/connections/your_vertical/services` - -We have a script that automates all the code + the import across the app. - -Run `pnpm run prebuild-oauth-connector --vertical="crm" --provider="hubspot"` for instance. - -All imports, dependencies, environment variables are handled. - -All you have to do is to check similar services and finish the code. - -NB: If your provider needs a subdomain, you have to manually add the environment variable inside the docker-compose and .env .env.example files. diff --git a/docs/open-source/self-host-guide.mdx b/docs/open-source/self-host-guide.mdx index fc9682918..12b1d47d0 100644 --- a/docs/open-source/self-host-guide.mdx +++ b/docs/open-source/self-host-guide.mdx @@ -13,11 +13,8 @@ git clone https://github.com/panoratech/Panora.git ``` - - ```bash -cd Panora && cp .env.example .env -``` + ```bash cd Panora && cp .env.example .env ``` @@ -50,7 +47,7 @@ The backend runs on `http://localhost:3000` -Visit our [Quick Start guide, step 2 (Generate your API Keys)](/core-concepts/auth) for more details. +Visit our [guide here](/core-concepts/auth) for more details. diff --git a/docs/quick-start.mdx b/docs/quick-start.mdx index 58ac9cd1c..0c051d055 100644 --- a/docs/quick-start.mdx +++ b/docs/quick-start.mdx @@ -1,87 +1,215 @@ --- -title: 'Quick Start' -description: 'This 5 minutes checklist helps you get all the requirements to start adding integrations to your product. ' -icon: 'star' +title: "Quickstart Guide" +description: "This 5 minutes checklist helps you get all the requirements to start adding integrations to your product. " +icon: "star" --- +## **Prerequisites** + +Before you begin, make sure you have the following: + +- A cloud [account](https://tally.so/r/w5ZoaN?source=docs_welcome) (or see our guide [here](/open-source/self-host-guide) on getting started with the selfhost version) +- An API key, see our guide [here](/core-concepts/auth) +- Node JS v18.17.1 or newer installed on your computer + +## **Step 1: Get access to your users data** + +You either have the option to use a **no-code magic link** or the **embedded frontend snippet** to get access to your user's data. +Choose the one that fits your needs ! + + + Let's send our first magic link so you can ask your customers to grant you access to their tools, without writing code. + + Hero Light + - - - - Move faster thanks to our scalable managed infrastructure - - - Ideal for early-stage companies that want to ship faster - - - - - - Login to your dashboard and go to the API Keys section to generate your keys. - Find more details about the dashboard and authentication on the dedicated page. - - - - - Move faster thanks to our scalable managed infrastructure - - + + Login to your account dashboard + + Go to section _Connections_ and click on button `Create a Magic Link` + + Click `Create a Unique Magic Link` + + You'll be asked for two informations: an `Origin User Email` (of the user + you're creating the link for) and an `Origin User Identifier`. The `Origin + User Identifier` is the id of the user you're inviting, as represented in your + sofwtare. + + Click `Generate`. You can now share the link! + - - - - Ask your customers to grant you access to their tools, without writing code - - - Embed Panora into your product to collect access to use user's data - - + + Embed Panora into your product with our native component to collect access to use user's data. + + You can find the component on NPM + [here](https://www.npmjs.com/package/@panora/embedded-card-react) + + + + + ```shell React + npm i @panora/embedded-card-react + ``` + + - + + + ```javascript React + import "@panora/embedded-card-react/dist/index.css"; + import PanoraProviderCard from "@panora/embedded-card-react"; + ``` + + + + + ```javascript React + + ``` + + + - - - - Write contacts, deals, and more to any platform - - - Opening, closing tickets and more, anywhere - - - - - - - - Test - - - -[Suggest an update](https://tally.so/r/mRD1QQ?feedback_source=home_quick-start) +Once the user successfully completes the granting auth flow, the connection will have a `status` value of `valid`. +We recommend listening to [webhooks](/webhooks/overview) to get notified once a user connects. + +## **Step 2: Send your first unified API requests** + +### _Create a contact in a CRM_ + + + We assume for this tutorial that you have a valid Panora API Key, and a + `connection_token`. Find help [here](/core-concepts/auth). + + + You can find the Typescript SDK on NPM + [here](https://www.npmjs.com/package/@panora/sdk-typescript) + + In this example, we will create a contact in a CRM. Visit other sections of the [documentation](/ticketing/try) to find category-specific examples. + + ```javascript TypeScript + import { PanoraSDK } from '@panora/sdk-typescript'; + + const sdk = new PanoraSDK({ accessToken: "MY_API_KEY" }); + + const input = { + first_name: 'tom', + last_name: 'jedusor', + email_addresses: [ + { + 'email_address': 'tom@jedusor.com', + 'email_address_type': 'PERSONAL' + } + ], + phone_numbers: [ + { + 'phone_number': '+33650438278', + 'phone_type': 'MOBILE' + } + ], + }; + + const result = await sdk.crmContact.addContact(input, 'MY_USER_CONNECTION_TOKEN', { + remoteData: true, + }); + + console.log(result); + ``` + + ```python Python + from panorasdk import PanoraSDK + + sdk = PanoraSDK() + + sdk.set_access_token("MY_API_KEY") + + request_body = { + 'first_name': 'tom', + 'last_name': 'jedusor', + 'email_addresses': [ + { + 'email_address': 'tom@jedusor.com', + 'email_address_type': 'PERSONAL' + } + ], + 'phone_numbers': [ + { + 'phone_number': '+33650438278', + 'phone_type': 'MOBILE' + } + ] + } + + results = sdk.crm_contact.add_contact( + request_input = request_body, + connection_token = 'MY_USER_CONNECTION_TOKEN', + remote_data = True + ) + + print(results) + ``` + + ```shell curl + curl --request POST \ + --url https://api.panora.dev/crm/contacts \ + --header 'Authorization: Bearer ' \ + --header 'Content-Type: application/json' \ + --header 'x-connection-token: ' \ + --data '{ + "first_name": "tom", + "last_name": "jedusor", + "email_addresses": [ + { + "email_address": "tom@jedusor.com", + "email_address_type": "PERSONAL" + } + ], + "phone_numbers": [ + { + "phone_number": "+33650438278", + "phone_type": "MOBILE" + } + ] + }' + ``` + + +Let’s break down what’s happening here: + +- We import the `Panora SDK`, which provides a convenient way to interact with the Panora Unified API. +- We create an instance of the `Panora SDK` client, passing in our API key. +- We call the `sdk.crmContact.addContact` method to add a contact inside a 3rd party. We specify the input we want to use (see [here](/crm/contacts/overview) for reference). +- Finally, we print the response. + +## Next Steps + +Congratulations, you’ve successfully sent your first unified API request with Panora! Here are some next steps to continue your journey. + +### Listen to events using a webhook + +Visit our [webhooks section](/webhooks/overview). + +### API resources + +Drop into our [API documentation](/api-reference/auth/register) for more details on the available endpoints and parameters. + +Check out our [client SDKs](/backend-sdk/typescript) for a set of tools to make it easier for you to build with and integrate Panora into your applications. + +[✏️ Suggest an update](https://tally.so/r/mRD1QQ?feedback_source=home_quick-start) diff --git a/docs/support/get_help.mdx b/docs/support/get_help.mdx index db24a28e4..a87780feb 100644 --- a/docs/support/get_help.mdx +++ b/docs/support/get_help.mdx @@ -1,6 +1,7 @@ --- -title: 'Get Help' +title: "Get Help" +icon: circle-info --- Our team can help you - click [here](https://app.cal.com/rflih/30) to book some time to chat with an integrations expert. -You can also ask the community: just go on our discord \ No newline at end of file +You can also ask the community: just go on our [discord](https://discord.gg/2SCC2jxN) diff --git a/docs/ticketing/try.mdx b/docs/ticketing/try.mdx index 32d95123c..96090cfa4 100644 --- a/docs/ticketing/try.mdx +++ b/docs/ticketing/try.mdx @@ -35,7 +35,7 @@ description: "Learn how to write and read data from your multiple ticketing plat In this example, we will create a ticket in a Provider. Visit other sections of the documentation to find category-specific examples - ```curl curl + ```shell curl curl --request POST \ --url https://api.panora.dev/ticketing/tickets \ --header 'Authorization: Bearer dfsdf' \ diff --git a/docs/webhooks/overview.mdx b/docs/webhooks/overview.mdx index 98d985d4c..6d1419352 100644 --- a/docs/webhooks/overview.mdx +++ b/docs/webhooks/overview.mdx @@ -1,102 +1,7 @@ --- -title: "Webhooks Overview" -description: "Panora can send notifcations to your backend when the state of an object has changed. We use the concept of `events` to represent state changes in any object." +title: "Overview" +description: "Panora can send notifcations through webhooks to your backend when the state of an object has changed. We use the concept of `events` to represent state changes in any object." +icon: hockey-puck --- -`Events` are our way of letting you know when something interesting happens in your projects. When an interesting event occurs, we create a new Event object. For example, when a contact is created in a crm, we create a `crm.contact.created` event, and when a contact is updated, we create an `crm.contact.updated` event. Certain API requests might create multiple events. For example, after we pull data from a CRM plaftorm you may receive both a `crm.contact.pulled` event and some `crm.contact.created` events. - -Events occur when the state of another API resource changes. The event’s data field embeds the resource’s state at the time of the change. For example, a `crm.contact.updated` event contains a `CRM Contact`, as the state of the contact is after the update. - -When creating webhook endpoints to retrieve events from Panora, you have the flexibilty to only retrieve some events, for each endpoint. We also have a separate webhooks system for sending the Event objects directly to an endpoint on your server. You can manage webhooks in your account settings. Learn how to listen for events so that your integration can automatically trigger reactions. - -## The _event_ Object - -The `event` object is used to represent an existing change to an object. -The typical implementation consists in listening for events and triggering worklows in your backend based on the content of the field **type** and data of the webhook. - -### Properties - - -```json JSON -{ - "id_event": "f4e1ff72-e727-409a-8935-a63a63d4891e", - "type": "crm.contact.created", - "data": { - "id_contact": "f4e1ff72-e727-409a-8935-a63a63d4891e", - "first_name": "John", - "last_name": "Doe", - "email_addresses": [{ - "email_address": "johndoe@work.com", - "email_address_type": "work" - },{ - "email_address": "johndoe@personal.com", - "email_address_type": "phone" - } - ], - "phone_numbers": [{ - "phone_number": "01982833", - "phone_type": "primary" - } - ], - "field_mappings": [{ - "hair_color": "black" - } - ], - "remote_data": { - } - } -} - -``` - - - - - - - - Panora Defined UUID for this event - - - - The type of this event. Find list of existing events in the dedicated below. - - - - Expect a unified object in this field. A **crm.contact.created** event would for example contain a [`CRM Contact`](/crm/contacts/overview) object. - - - - - - - -## Securing your webhooks -We use secrets to make sure your endpoints do not receive data from third-parties usurpating Panora. - -## List of Event Types -This is a list of all the types of events we currently send. We may add more at any time, so in developing and maintaining your code, you should not assume that only these types exist. - -You’ll notice that these events follow a pattern: resource.event. Our goal is to design a consistent system that makes things easier to anticipate and code against. - - - - - - Occurs whenever a new contact was created in a CRM. The **data** field is a [`CRM Contact`](/crm/contacts/overview) - - - - Occurs whenever a new contact was updated in a CRM. The **data** field is a [`CRM Contact`](/crm/contacts/overview) - - - - Occurs whenever a new contact was deleted in a CRM. The **data** field is a [`CRM Contact`](/crm/contacts/overview) - - - - Occurs when a new connection was created. The **data** field is a `Connection` object. - - - -``` +## Learn how to create a webhook diff --git a/docs/welcome.mdx b/docs/welcome.mdx index 513616c75..80d858d47 100644 --- a/docs/welcome.mdx +++ b/docs/welcome.mdx @@ -1,41 +1,40 @@ --- -title: 🌼 Welcome to Panora +title: Welcome to Panora description: "Panora is an open-source, unified API for shipping customer-facing integrations" +icon: otter --- - - Learn Panora's main concepts and start building integrations - +{" "} + + Learn Panora's main concepts and start building integrations + ### FAQ + Panora reduces the amount of APIs you will need to interact with. Using a single endpoint, you will be able to read and write data from various CRMs, ticketing platforms. No need to go through endless cycles of documentation exploration, testing and maintaining. - - No! Panora is extensible. We are open-source, and written in TypeScript. - Building new connectors on top of Panora is fun and faster than building them from scratch.

[Read our guide here](https://github.com/panoratech/Panora/blob/main/INTEGRATIONS.md). -
+{" "} -
+ + No! Panora is extensible. We are open-source, and written in TypeScript. + Building new connectors on top of Panora is fun and faster than building them + from scratch.

[Read our guide here](https://github.com/panoratech/Panora/blob/main/INTEGRATIONS.md). +
+ -### 🔮 Core Features +### 🔮 Core Features -| | -|---------------------------| -| **Magic Links:** Let your users grant you access to their data. Without writing code. | -| **Custom Fields:** Reflect in Panora the specific data points that matter to your users | -| **Passthrough Requests:** Interact with other software platforms in their native format. | -| **Flexible Sync Settings:** Businesses that need real-time update can configure Panora accordingly | -| **Webhooks:** Listen to one webhook to receive normalized data from various software platforms | +| | +| ------------------------------------------------------------------------------------------------------------------------------------ | +| **[Magic Links:](/core-concepts/magic-links)** Let your users grant you access to their data. Without writing code. | +| **[Custom Fields:](/core-concepts/custom-fields)** Reflect in Panora the specific data points that matter to your users | +| **[Passthrough Requests:](/core-concepts/passthrough-requests)** Interact with other software platforms in their native format. | +| **[Flexible Sync Settings:](/core-concepts/sync-strategies)** Businesses that need real-time update can configure Panora accordingly | +| **[Webhooks:](/core-concepts/webhooks)** Listen to one webhook to receive normalized data from various software platforms | [✏️ Suggest an update](https://tally.so/r/mRD1QQ?feedback_source=welcome) - -