Welcome to the Qpien API documentation. This guide will help you understand how to authenticate, manage API keys, and make your first request.#
The process looks like this:#
1
Generate API Keys
In your Qpien App, go to Api Keys and create a new API key.
Your Client ID and Client Secret will be generated.
Configure API scopes and save changes.
Not: Client Secret only visible on creation.
2
Get an Access Token
Use your clientId and clientSecret to request an access token.
Tokens are valid for 1 hour.
You’ll need to refresh or request a new token after it expires.
3
Make Requests
Send requests to our API at:
https://api.qpien.com/api/v1
Include your access token in the Authorization header:
Authorization: Bearer <access_token>
Quick Example#
Step 1 — Get an Access Token#
Step 2 — Call the API (GraphQL Query)#
This page describes the general guidelines and conventions for working with the Qpien API. Developers should review this section before integrating with the modules.
Authentication#
All requests to the API must be authenticated.
Authentication is done using Bearer Token in the Authorization header:
Tokens are provided for each customer and should be stored securely.
Rate Limiting#
To ensure stability and fairness, all requests to the API are rate-limited.Standard Limit: 100 requests / minute
Burst Limit: Short spikes may be tolerated, but exceeding the limit will result in a temporary block.
Headers for Tracking: Each response contains rate-limit headers so you can monitor usage:
| Header | Description |
|---|
X-RateLimit-Limit | Maximum number of requests allowed per minute |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Time (in seconds) until the limit resets |
If you exceed the rate limit, the API will return an error response with a 429 Too Many Requests code.
Status Codes#
Unlike REST APIs, GraphQL APIs usually return 200 OK for all requests (since the transport succeeded), but include success/failure information inside the response body.| Status Code | Description |
|---|
200 OK | Request processed successfully (may still contain errors in GraphQL response body) |
400 Bad Request | Invalid query, malformed input, or validation error |
401 Unauthorized | Missing or invalid authentication token |
403 Forbidden | Insufficient permissions |
404 Not Found | The requested resource (entity) does not exist |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Unexpected server error |
503 Service Unavailable | Temporary downtime or maintenance |
A GraphQL response always follows this structure:{
"data": {
"externalGetMessage": {
"success": true,
"data": { ... },
"code": "200",
"message": "Message retrieved successfully"
}
},
"errors": [
{
"message": "Validation error: messageId is required",
"path": ["externalGetMessage"],
"extensions": {
"code": "BAD_USER_INPUT"
}
}
]
}
data → Contains the successful response (if any).
errors → Contains validation or execution errors.
extensions.code → Provides a machine-readable error type.
Error Handling#
We standardize errors across the API to make them predictable.| Code | Description | Example |
|---|
BAD_USER_INPUT | Input arguments invalid | Missing conversationId |
UNAUTHORIZED | Invalid/missing token | Access denied |
FORBIDDEN | Not enough permissions | User not allowed to delete conversation |
NOT_FOUND | Resource not found | Conversation ID does not exist |
RATE_LIMITED | Too many requests | Exceeded 100 req/min |
INTERNAL_ERROR | Server failure | Unexpected issue |
For list queries (e.g. externalGetConversationList, externalGetMessageList):Pagination is cursor/offset-based depending on the query.
Common fields in paginated responses:
| Field | Description |
|---|
docs | Array of returned entities |
hasNextPage | Boolean flag indicating if there are more results |
totalDocs | Total number of documents matching query |
Example#
Versioning#
The API currently runs on v1.
Breaking changes will be introduced via a new version (e.g., v2) with backward compatibility guarantees.
Non-breaking changes (adding fields, optional arguments) are rolled out continuously.
Best Practices#
Always check for errors in GraphQL responses.
Implement retry logic with exponential backoff for transient errors (500, 503).
Use pagination instead of requesting large datasets in a single call.
Cache repeated queries where possible to reduce API usage.
Modified at 2025-11-28 09:02:31