Skip to main content

Authentication

There are two separate authentication contexts: your app calling Grigora APIs on behalf of users (OAuth access tokens), and you using the Developer Portal (Grigora account login). This page explains both and shows how API calls work with the same examples as the Grigora API v1.

Your app calling Grigora APIs (OAuth)

After you complete the OAuth flow, your backend receives an access token (prefix gri_at_). Every request to the Grigora API that uses OAuth must send this token in the header:

Authorization: Bearer gri_at_xxx...

The API validates the token and attaches the authorized user, scopes, and project IDs to the request. Endpoints that need a specific project require project_id in the request body (see below).

How it works

  • You send the access token in the Authorization: Bearer header to https://api.grigora.co/general/api/v1/.
  • Token-only endpoints (who am I, introspect, list projects) do not require a body; others require project_id in the JSON body because the token can access one or more projects.
  • If the token is missing, invalid, or expired, the API returns 401 with error: "invalid_token" or "unauthorized".

Example: Who is authorized (token only)

GET https://api.grigora.co/general/api/v1/token/authorized_by
No body. Returns the user info for the current OAuth token.

Request:

const response = await fetch('https://api.grigora.co/general/api/v1/token/authorized_by', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
const user = await response.json();

Response (200):

{
"id": "user-uuid-from-cognito",
"email": "user@example.com",
"firstName": "Jane",
"lastName": "Doe"
}

401: Missing or invalid Bearer token.

Example: Token introspect (token only)

GET https://api.grigora.co/general/api/v1/token/introspect
No body. Returns authorization and application info for the current token.

Request:

const response = await fetch('https://api.grigora.co/general/api/v1/token/introspect', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
const info = await response.json();

Response (200):

{
"authorization": {
"id": "123",
"createdOn": "2025-02-20T10:00:00.000Z",
"grantType": "authorization_code",
"scope": "cms:post:read directory:items:read",
"userId": "user-uuid",
"authorizedTo": {
"projectIds": ["proj_abc123", "proj_def456"]
}
},
"application": {
"id": "42",
"description": "My integration",
"homepage": "https://myapp.com",
"displayName": "My App"
}
}

Example: List projects (token only)

GET https://api.grigora.co/general/api/v1/project/list
No body. Returns the list of projects the token can access.

Request:

const response = await fetch('https://api.grigora.co/general/api/v1/project/list', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
const data = await response.json();

Response (200):

{
"projects": [
{ "id": "proj_abc123", "name": "My Site", "domain": "mysite.com", "slug": "my-site" },
{ "id": "proj_def456", "name": "Other Site", "slug": "other-site" }
]
}

Example: Project details (project_id required)

POST https://api.grigora.co/general/api/v1/project/details
Body must include project_id for OAuth. The project_id must be one of the projects authorized for the token.

Request:

const response = await fetch('https://api.grigora.co/general/api/v1/project/details', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ project_id: 'proj_abc123' }),
});
const project = await response.json();

Response (200): Full project details (id, name, domain, slug, and other fields).

400: project_id missing.
403: project_not_authorized — the token does not have access to that project.

Example: CMS post list (project_id required)

POST https://api.grigora.co/general/api/v1/cms/post/list
Body must include project_id for OAuth. Optional: filters, sort, order.

Request:

const response = await fetch('https://api.grigora.co/general/api/v1/cms/post/list', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
project_id: 'proj_abc123',
sort: 'last_update',
order: 'dsc',
}),
});
const data = await response.json();

Response (200): { "success": true, "data": [ ... ] } — array of posts (id, title, slug, status, author, created_on, last_update, category, word_count, etc.).


  • Where the token comes from: Exchange the authorization code at https://api.grigora.co/general/oauth/token (see OAuth). Store access_token and refresh_token on your server.
  • Expiry: Access tokens expire (e.g. 1 hour). Use the refresh token at https://api.grigora.co/general/oauth/token with grant_type=refresh_token to get a new access token.
  • Security: Do not expose the access token or client secret in the browser. Do token exchange and API calls on your backend.

Developer Portal (your login)

The Developer Portal at https://build.grigora.co uses your Grigora account. You sign in there to create and manage apps, view credentials, edit store listings, and submit for review.

  • How it works: You log in with your Grigora credentials. The portal sends your session (Cognito) to https://api.grigora.co for Developer API routes (e.g. /user/developer/apps, /user/review-requests). You do not paste any token in the portal UI.
  • If you’re not logged in: You are redirected to the Grigora login page, then back to the page you were on (using a return query parameter).
  • 401 from the Developer API: The portal redirects you to login with the current URL as the return target.

OAuth credentials (client_id, client_secret, access_token) are for your app to call Grigora APIs on behalf of end users. They are not used to log into the Developer Portal.

Summary

ContextHow to authenticate
Your app calling Grigora APIs (v1: token, project, CMS, directory, scripts)Send the OAuth access_token in the header: Authorization: Bearer plus the token. Token-only endpoints: no body. Other endpoints: include project_id in the JSON body. Base URL: https://api.grigora.co/general/api/v1.
You using the Developer PortalLog in with your Grigora account at https://build.grigora.co. The portal sends your session to the API automatically.