Authenticate with Secret Keys
Naqood's GraphQL API uses long-lived bearer secrets that inherit the permissions of a specific organization role. Give every integration or background job its own secret so it can be revoked without interrupting other automation.
When to use API secrets
- Server-side connectors that sync or reconcile data on a schedule
- Back-office scripts that post documents on behalf of a customer
- Internal automation you already manage inside the Naqood workspace
End users should keep signing in with OAuth or email links. Secrets are only for backend, service-to-service calls that can be stored in a secure vault.
Getting a secret
You can create the same type of secret through either option:
- OAuth Authorization Code with PKCE – follow the OAuth guide to request consent from a customer and exchange the authorization code for a
secretKey. - In-app key issuance – open Settings → API while signed in to the organization and create a new key.
Secrets are displayed once. Copy them immediately and store them somewhere secure such as a secrets manager or KMS-backed vault.
Sending authenticated requests
Add the secret to the Authorization header and include the customer slug in each GraphQL request so Naqood can route it to the correct organization.
curl https://app.naqood.ae/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-d '{
"operationName": "SampleQuery",
"query": "query SampleQuery($slug: Slug!) { organization(slug: $slug) { id name } }",
"variables": { "slug": "acme-co" }
}'
Required headers
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer YOUR_SECRET_KEY |
Most mutations and queries expect a slug variable so Naqood knows which organization issued the secret.
Common error messages
| Message | Meaning | Resolution |
|---|---|---|
missing authorization header | Header was omitted or misspelled. | Ensure the header name is Authorization with a capital A. |
not authenticated | The provided credential is invalid or expired. | Copy the secret exactly as issued or create a new key. |
not authorized | The key's role does not allow that resolver. | Request a role with the necessary permissions or call a different organization. |
Operational tips
- Least privilege: create dedicated roles for every integration and grant only what they need.
- Rotation: issue a new secret on a regular cadence, roll it out, then delete the old one.
- Naming: label keys with the integration name and organization so teams know what they power.
- Storage: keep secrets in a managed vault and never commit them to source control or logs.
Quick validation
GraphiQL, Insomnia, Postman, or curl can run a lightweight query to confirm a key works:
query Ping($slug: Slug!) {
organization(slug: $slug) {
id
name
}
}
If the request succeeds, the secret is valid and scoped to that organization. From here, move on to feature-specific guides such as Bank Ingest.