Building a partner integration
Register as a partner, create and publish an application, authenticate with OAuth2 and receive webhooks.
This guide is for partners building an integration with Vectis. The Partner API is GraphQL; every operation is listed in the API reference.
1. Register as a partner
Register your company as a partner developer. This creates a partner account linked to your user.
mutation {
registerPartner(
input: {
companyName: "FuelCo Ltd"
contactEmail: "[email protected]"
website: "https://fuelco.com"
logoUrl: "https://fuelco.com/logo.png"
}
) {
success
partner {
id
companyName
contactEmail
status
}
error
}
}Your partner account starts as Active, so you can create applications straight away.
2. Create an application
Create a Marketplace application under your partner account. Applications start as Draft.
mutation {
createApplication(
input: {
partnerId: "your-partner-id"
name: "FuelCo Fuel Tracker"
description: "Automatically imports fuel transactions from FuelCo fuel cards into Vectis."
shortDescription: "Automatic fuel card transaction imports"
logoUrl: "https://fuelco.com/app-logo.png"
categories: "fuel-management"
homepageUrl: "https://fuelco.com/vectis-integration"
supportUrl: "https://fuelco.com/support"
privacyPolicyUrl: "https://fuelco.com/privacy"
}
) {
success
application {
id
name
status
}
error
}
}Each application automatically receives a unique client_id. The client_secret is generated when the application is approved.
Categories: fuel-management, ruc, telematics, maintenance, insurance, compliance, booking, analytics.
3. Submit a version with scope requests
Before submitting for review, create a version that declares the API scopes your application needs.
mutation {
submitVersion(
input: {
applicationId: "your-app-id"
partnerId: "your-partner-id"
versionNumber: "1.0.0"
changelog: "Initial release: fuel transaction import"
scopeIds: [
"scope-id-for-fuel-read"
"scope-id-for-fuel-write"
"scope-id-for-vehicles-read"
]
}
) {
success
version {
id
versionNumber
status
submittedAt
}
error
}
}To find scope IDs, query the scope list:
query {
apiScopes {
id
code
displayName
description
resourceGroup
isSensitive
}
}4. Submit for review
When your application is ready, submit it for review by the Vectis team.
mutation {
submitApplicationForReview(
applicationId: "your-app-id"
partnerId: "your-partner-id"
) {
success
application {
id
status
}
error
}
}The status changes from Draft to Submitted. The Vectis team approves the application or rejects it with feedback. A rejected application returns to Draft, so you can make changes and resubmit.
5. Publish your application
Once approved, publish the application to make it visible in the Marketplace.
mutation {
publishApplication(
applicationId: "your-app-id"
partnerId: "your-partner-id"
) {
success
application {
id
status
}
error
}
}The application is now visible to all Vectis organisations and can be installed. To stop new installations, deprecate it with deprecateApplication, which takes the same arguments.
6. Manage client credentials
On approval, your application receives a client_secret. Use the client_id and client_secret to authenticate your server-to-server API calls.
Rotate the client secret periodically:
mutation {
rotateClientSecret(
applicationId: "your-app-id"
partnerId: "your-partner-id"
) {
success
clientSecret
error
}
}7. Authenticate with OAuth2
Use your client_id and client_secret to get access tokens with the client credentials grant.
mutation {
oAuthToken(
input: {
clientId: "your-client-id"
clientSecret: "your-client-secret"
grantType: "client_credentials"
}
) {
success
accessToken
refreshToken
expiresAt
tokenType
scopes
error
}
}The response looks like this:
{
"data": {
"oAuthToken": {
"success": true,
"accessToken": "eyJhbGciOi...",
"refreshToken": "dGVzdC1yZWZy...",
"expiresAt": "2026-03-14T14:00:00Z",
"tokenType": "Bearer",
"scopes": "fuel:read,fuel:write,vehicles:read"
}
}
}- Access tokens expire after 1 hour.
- Refresh tokens expire after 30 days.
- Send the access token with each API request:
Authorization: Bearer <accessToken>.
8. Refresh, revoke and inspect tokens
Refresh your access token before it expires. Send your client_secret with every refresh, as for the first token request; a refresh token on its own is refused.
mutation {
oAuthRefreshToken(
refreshToken: "your-refresh-token"
clientId: "your-client-id"
clientSecret: "your-client-secret"
) {
success
accessToken
refreshToken
expiresAt
tokenType
scopes
error
}
}Each refresh rotates the refresh token: the old one stops working and a new one is returned. If a refresh token is reused after rotation, every token in that family is revoked.
Revoke a token you no longer need. Revoking a token that does not exist succeeds silently.
mutation {
oAuthRevokeToken(token: "token-to-revoke", clientId: "your-client-id") {
success
error
}
}Introspect a token to check whether it is valid and see its details:
mutation {
oAuthIntrospect(token: "access-token-to-check") {
active
clientId
partnerId
organisationId
installationId
scopes
expiresAt
}
}9. Receive webhook events
When an organisation installs your application, it can receive event notifications by webhook. The organisation's administrators manage the subscriptions (see Configure webhooks).
Your endpoint receives HTTP POST requests with:
Content-Type: application/jsonX-Vectis-Signature: the HMAC-SHA256 hex digest of the JSON body, signed with the installation's webhook secret.
An example payload:
{
"event": "booking.created",
"data": {
"id": "abc-123",
"vehicleId": "vehicle-456",
"startDate": "2026-03-15T09:00:00Z",
"endDate": "2026-03-15T17:00:00Z"
},
"timestamp": "2026-03-14T12:00:00Z"
}Always verify the signature before processing a payload.
import hmac
import hashlib
def verify_signature(payload_body, secret, received_signature):
expected = hmac.new(
secret.encode('utf-8'),
payload_body.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, received_signature)using System.Security.Cryptography;
using System.Text;
var keyBytes = Encoding.UTF8.GetBytes(webhookSecret);
var payloadBytes = Encoding.UTF8.GetBytes(jsonBody);
var hmac = HMACSHA256.HashData(keyBytes, payloadBytes);
var expectedSignature = Convert.ToHexStringLower(hmac);
var isValid = expectedSignature == receivedSignature;10. View your partner account
See your partner account and its applications:
query {
myPartner {
id
companyName
contactEmail
status
applications {
id
name
status
installCount
currentVersion
}
}
}Or list your applications with partnerApplications(partnerId: "your-partner-id"), which also returns each application's description, featured flag and creation date.