Skip to content
Vectis

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.

graphql
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.

graphql
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.

graphql
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:

graphql
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.

graphql
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.

graphql
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:

graphql
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.

graphql
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:

json
{
  "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.

graphql
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.

graphql
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:

graphql
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/json
  • X-Vectis-Signature: the HMAC-SHA256 hex digest of the JSON body, signed with the installation's webhook secret.

An example payload:

json
{
  "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.

python
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)

10. View your partner account

See your partner account and its applications:

graphql
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.