2915 rest api documentation (#3020)

* Init rest-api page

* Add ugly form to fetch open api schema

* Clean code

* Make the form design more acceptable

* Update doc

* Use local storage

* Update design

* Add isLoading

* Fix typo

* Fix long lines

* Code review returns

* Remove staging and local url from servers
This commit is contained in:
martmull 2023-12-15 18:13:13 +01:00 committed by GitHub
parent 9f6d476351
commit 3ac4102c3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 2474 additions and 81 deletions

View File

@ -1,9 +1,30 @@
---
title: Rest API
title: REST API
sidebar_position: 3
sidebar_class_name: coming-soon
sidebar_custom_props:
icon: TbApi
---
Coming soon!
To use the REST API, you will need an API key.
Connect to your Twenty account and follow the following
[documentation](user-guide/integrations/generating-api-keys.mdx) to generate one
## Using Postman?
You can use [Postman](https://www.postman.com/) to interact with your Twenty objects using the API.
You will need to provide your API key as a Bearer token,
see [Bearer Token Postman Doc](https://learning.postman.com/docs/sending-requests/authorization/authorization-types/#bearer-token)
if needed.
## Programmatic use?
You can call the REST API in your application using this endpoint
[https://api.twenty.com](https://api.twenty.com).
You will need to provide your API key as a Bearer token in
your `headers.Authorization = 'Bearer <YOUR_API_KEY>'`.
## Try the REST API Playground
You can use the browser-based, interactive
[REST API playground documentation](https://docs.twenty.com/rest-api)
to Create, Read, Update or Delete your workspace objects.

View File

@ -17,11 +17,11 @@ Sync Twenty with 3000+ apps using [Zapier](https://zapier.com/), and automate yo
2. Click on `+ Create Zap` in the left sidebar.
3. Choose the application you want to set as the trigger. A trigger refers to an event that starts the automation.
4. Select Twenty as the action. An action is the event performed whenever an application triggers an automation. [Learn more about triggers and actions in Zapier.](https://zapier.com/how-it-works)
5. Once you choose the Twenty account that you want to use for your automation, you'll have to authorize it by adding an API key. You can learn [how to generate your API key here.](generating-api-keys.mdx)
5. Once you choose the Twenty account that you want to use for your automation, you'll have to authorize it by adding an API key. You can learn [how to generate your API key here.](user-guide/integrations/generating-api-keys.mdx)
6. Enter your API key and click on 'Yes, Continue to Twenty.'
<div style={{textAlign: 'center'}}>
<img src="/img/user-guide/connect-zapier.png" alt="Connect Twenty to Zapier" />
</div>
You can now continue creating your automation!
You can now continue creating your automation!

View File

@ -33,6 +33,7 @@ const config = {
defaultLocale: "en",
locales: ["en"],
},
plugins: ['docusaurus-node-polyfills'],
presets: [
[
"classic",

View File

@ -19,7 +19,9 @@
"@docusaurus/core": "^3.0.0",
"@docusaurus/preset-classic": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"@stoplight/elements": "^7.15.4",
"clsx": "^1.2.1",
"docusaurus-node-polyfills": "^1.0.0",
"graphiql": "^2.4.7",
"graphql": "^16.6.0",
"iframe-resizer-react": "^1.1.0",

View File

@ -1,7 +1,6 @@
import { createGraphiQLFetcher } from "@graphiql/toolkit";
import { GraphiQL } from "graphiql";
import React from "react";
import ReactDOM from "react-dom";
import Layout from "@theme/Layout";
import BrowserOnly from "@docusaurus/BrowserOnly";
@ -16,9 +15,7 @@ const GraphiQLComponent = () => {
window.localStorage.setItem("graphiql:theme", "light");
}
const fetcher = createGraphiQLFetcher({
url: "https://api.twenty.com/graphql",
});
const fetcher = createGraphiQLFetcher({url: "https://api.twenty.com/graphql"});
return (
<div className="fullHeightPlayground">
<GraphiQL fetcher={fetcher} />;

View File

@ -0,0 +1,67 @@
.container {
display: flex;
justify-content: center;
align-items: center;
height: 90vh;
}
.form {
text-align: center;
padding: 50px;
}
.link {
color: #16233f;
text-decoration: none;
position: relative;
font-weight: bold;
transition: color 0.3s ease;
}
.input {
padding: 4px;
margin: 20px 0 5px 0;
max-width: 460px;
width: 100%;
box-sizing: border-box;
background-color: #f3f3f3;
border: 1px solid #ddd;
border-radius: 4px;
}
.invalid {
border: 1px solid red;
}
.token-invalid {
color: red;
font-size: 12px;
text-align: left;
}
.not-visible {
visibility: hidden;
}
.loader {
color: #16233f;
font-size: 2rem;
animation: animate 2s infinite;
}
@keyframes animate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(720deg);
}
}
.loader-container {
display: flex;
justify-content: center;
align-items: center;
height: 50px;
}

View File

@ -0,0 +1,114 @@
import Layout from "@theme/Layout";
import BrowserOnly from "@docusaurus/BrowserOnly";
import React, { useEffect, useState } from "react";
import { API } from '@stoplight/elements';
import '@stoplight/elements/styles.min.css';
import './rest-api.css'
import { parseJson } from "nx/src/utils/json";
import { TbLoader2 } from "react-icons/tb";
type TokenFormProps = {
onSubmit: (token: string) => void,
isTokenValid: boolean,
isLoading: boolean,
token: string,
}
const TokenForm = ({onSubmit, isTokenValid, token, isLoading}: TokenFormProps)=> {
const updateToken = (event: React.ChangeEvent<HTMLInputElement>) => {
localStorage.setItem('TryIt_securitySchemeValues', JSON.stringify({bearerAuth: event.target.value}))
onSubmit(event.target.value)
}
return !isTokenValid && (
<div>
<div className='container'>
<form className="form">
<label>
To load your REST API schema, <a className='link' href='https://app.twenty.com/settings/developers/api-keys'>generate an API key</a> and paste it here:
</label>
<p>
<input
className={(token && !isLoading) ? "input invalid" : "input"}
type='text'
disabled={isLoading}
placeholder='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMD...'
defaultValue={token}
onChange={updateToken}
/>
<p className={`token-invalid ${(!token || isLoading )&& 'not-visible'}`}>Token invalid</p>
<div className='loader-container'>
<TbLoader2 className={`loader ${!isLoading && 'not-visible'}`} />
</div>
</p>
</form>
</div>
</div>
)
}
const RestApiComponent = () => {
const [openApiJson, setOpenApiJson] = useState({})
const [isTokenValid, setIsTokenValid] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const storedToken = parseJson(localStorage.getItem('TryIt_securitySchemeValues'))?.bearerAuth ?? ''
const validateToken = (openApiJson) => setIsTokenValid(!!openApiJson.tags)
const getJson = async (token: string ) => {
setIsLoading(true)
return await fetch(
"https://api.twenty.com/open-api",
{headers: {Authorization: `Bearer ${token}`}}
)
.then((res)=> res.json())
.then((result)=> {
validateToken(result)
setIsLoading(false)
return result
})
.catch(() => setIsLoading(false))
}
const submitToken = async (token) => {
if (isLoading) return
const json = await getJson(token)
setOpenApiJson(json)
}
useEffect(()=> {
(async ()=> {
await submitToken(storedToken)
})()
},[])
return isTokenValid !== undefined && (
<>
<TokenForm
onSubmit={submitToken}
isTokenValid={isTokenValid}
isLoading={isLoading}
token={storedToken}
/>
{
isTokenValid && (
<API
apiDescriptionDocument={JSON.stringify(openApiJson)}
router="hash"
/>
)
}
</>
)
}
const restApi = () => (
<Layout
title="REST API Playground"
description="REST API Playground for Twenty"
>
<BrowserOnly>{() => <RestApiComponent />}</BrowserOnly>
</Layout>
);
export default restApi;

View File

@ -2,6 +2,7 @@
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@docusaurus/tsconfig//tsconfig.json",
"compilerOptions": {
"baseUrl": "."
"baseUrl": ".",
"jsx": "react"
}
}

View File

@ -20,22 +20,10 @@ export const baseSchema = (frontBaseUrl: string): OpenAPIV3.Document => {
},
// Testing purposes
servers: [
{
url: 'http://localhost:3000',
description: 'Local Development',
},
{
url: 'https://api-main.twenty.com/',
description: 'Staging Development',
},
{
url: 'https://api.twenty.com/',
description: 'Production Development',
},
{
url: '/',
description: 'Current Host',
},
],
components: {
securitySchemes: {

2320
yarn.lock

File diff suppressed because it is too large Load Diff