vPlan API (v1)

vPlan is the easiest way to plan and track your work. Get insight and results. This API is available on: https://api.vplan.com/v1

Additional resources:

Look at the playlist below for technical videos about our API.


This API reference contains the documentation for all supported third-party vPlan objects. There are also undocumented endpoints, that are accessible with the API token, these endpoints are used by the application itself. Undocumented endpoints are unsupported for third-party use. These endpoints are subject to change without prior warning.

For every object a data structure table is given, the field description can end with:

  • for informational purposes only
    • this field is not used by vPlan but can be used freely to store extra information, e.g. for filtering
  • reserved for future use
    • this field is not used by vPlan at this moment but can be limited in possible values in the future
  • internally maintained
    • the value is calculated within vPlan and is read-only, the calculation could be async or triggered by an action

The examples below show default requirements and options. This information applies to all endpoints unless explicitly stated otherwise.


The vPlan API supports pagination via the query parameters limit and offset.

Example: ?limit=50&offset=150

Limit is the maximum number of records given in a resulting dataset.
Default: 0

Offset is the number of records to be skipped for the resulting dataset
Default: 0

If an offset is larger than the possible items that can be returned for the request, an empty data array will be returned.

The count property of a resultset can be used to determine how many calls must be made to retrieve all objects.


Currently there is no default for limit, this will change to 100 with a maximum of 1000


For sorting the resulting dataset use the query parameter sort with the format:


Example: ?sort=updated_at:desc,name

Colon : is the separator between the field and the optional sorting order. Default sorting order is ascending.

Comma , can be used to add multiple fields for sorting the dataset


Will only work on main fields of the object and not on fields from included objects


On the list endpoints it is possible to filter the result set given. To apply a filter use the filter query parameter with the format:


Example: ?filter=created_at:gt:2020-09-26,and,(id:not:starts_with:0000,or,id:contains:FFFF)

Colon : is the separator between the field, operator(s) and value.

Comma , can be used to combine filter statements by using ,and, or ,or,.

Braces (...) can be used to group filter statements.

The following operators are supported

operator description
eq equal to the given value
gt greater than the given value
gte greater than or equal to the given value
lt lesser than the given value
lte lesser than or equal to the given value
not negation of the operator that follows it
contains has occurrence of the given value
starts_with starts with the given value
end_with ends with the given value


Currently the comma , and colon : are not supported within the filter value

Slimmed down result

The query parameters show and hide allow clients to requests a limited set of properties.

In addition to reducing the amount of data transferred, this can be helpful in reducing errors caused by additional features added in a release update.

show specifies which properties the client will receive.
hide specifies which properties will be removed from the reponse.

Both must contain a comma separated list of properties.

For the properties of the main object this is pretty straigth forward. Subobjects added via eager loading come in 2 flavors:

  1. single subobject, e.g. collection or address for an order
    format: related object.property
  2. list of subobjects, e.g. order_rows
    format: related objects.*.property or related objects.item #.property

Please note that * can be used to show or hide all properties of a subobject.


  • v1/order?show=code,type
  • v1/order?hide=created_at,updated_at
  • v1/order?with=collection,order_rows&show=code,type,collection.id,collection.source_type,order_rows.*.id
  • v1/order?with=collection,order_rows&hide=collection.id,collection.source_type,order_rows.*.id
  • v1/order?with=collection,order_rows&show=code,type,collection.id,collection.source_type,order_rows.0.id,order_rows.1.description
  • v1/order?with=collection&show=collection.*&hide=collection.id,collection.source_type
  • v1/order?with=order_rows&show=order_rows.*&hide=order_rows.*.id,order_rows.*.updated_at

As shown in the last example show and hide can be combined this is primarily usefull if you want specific properties from the main object and hide properties from related objects.

Eager loading

When retrieving a List or Single object, the with query parameter allows to eager load and retrieve related objects with one call.

It consists of a comma separated list of objects, using the dot . as separator for subobjects.

Example: ?with=attachments,cards.resources

If this example with was performed on the Collection List, It would retrieve every collection, and with every collection its attachments, it would also retrieve all the cards of every collection, and finally it would return every resource from every card of every collection.

The first layer of possible with options are stated with every object in this documentation.


The vPlan API is constantly improving, which means that today's endpoints and features could be replaced or removed in the future.

Within this documentation endpoints, parameters or fields can be flagged as Deprecated.

Newly created integrations should not use anything marked as deprecated.

Existing integrations that use anything marked as deprecated, should alter that part of the integration in the near future, in order to prevent possible future errors.

For deprecated endpoints the API will send a Deprecated header with a description.

Example: GET v1/collection/detail is deprecated and will be removed in future versions

Integrations are expected to look out for this header, and act accordingly.
Another option is retrieving the API messages.

External Reference

Almost every object relevant for integrations has a property named external_ref.

In principal this is not a field vPlan uses it self. However if it has a value the vPlan frontend will block certain manually changes for a user.

The main goal for this property is to provide integrations with a location to store the unique identifier of the source object.

Unique constraint

The external_ref has the requirement that it must be unique, within that object. If you try to create an object with an already existing external_ref the vPlan API give an error "HTTP 422 Unprocessable entity", with a description stating "Duplicate entry".

For Orders the unique key is external_ref combined with type and sub_type.


Objects that have the archive feature will per default not return archived objects.

Archived objects are not separate from unarchived objects, as such unique constraints still apply, i.e. an "active" or unarchived object cannot have the same value for a unique constraint as an archived object


If in an order type or sub_type is given the value null the unique constraint will not be triggered. Use the value none instead.

Rate Limits

The RateLimit headers are sent in responses to all the Api-Key or OAuth requests, they contain information about the amount of requests that can be made within the specified time window.

Header Description
RateLimit-Limit Maximum number of requests you're permitted to make per time window
RateLimit-Remaining Number of requests remaining in the current rate limit window.
RateLimit-Reset Time at which the current rate limit window resets in seconds.

Tips for optimizing an integration:

  • Use webhooks to be signaled when a certain event is triggered, instead of synchronizing every X minutes
  • Increase the interval between synchronizations, for example every 30 minutes instead of every 10 minutes
  • Create an Order with OrderRows in 1 request instead of separate requests per OrderRow
  • Use Eager loading, for example the Relation or Project info can be included when getting an Order in 1 request
  • Reduce retrieval of data. When an objects needs to be updated or referenced in another call having the information available without having to retrieve it every time can drastically reduce request counts Possible options are:
    • Store vPlan ids
    • Store entire vPlan objects
    • Cache vPlan ids
    • Cache entire vPlan objects


In the event the request results in an error of any kind, the API will respond with an json error. If you receive any other kind of error there must be a connection issue somewhere down the line.

An error will always be in the following format:

string <uuid>

Error reference, used for support requests

Array of objects (Error) [ items ]
  • "reference": "6ad5af82-69bb-4e90-892e-45ec76d34954",
  • "errors": [
    • {

The API will use different HTTP status codes if suitable. The status codes commonly seen within this API, are in the table down below. Please note that this is not a complete list.

HTTP Code Description Example occurrences
400 BAD REQUEST Invalid request given, e.g. limit=-15 as query parameter given
401 UNAUTHORIZED Accesstoken is expired
403 FORBIDDEN Endpoint or action is not permitted
404 NOT FOUND Invalid endpoint, or an object id in request does not exist
405 METHOD NOT ALLOWED Requested method (GET, POST, PUT, DELETE) is not allowed for the the endpoint
422 UNPROCESSABLE ENTITY Validation on the request has failed
429 TOO MANY REQUESTS For more info look at Rate Limits
500 INTERNAL SERVER ERROR An internal error occurred

Look at Service Unavailable for responses given during maintenance.

The HTTP Status code gives an indication of the kind of error. More detailed information is available in the error message. The error message should be enough to correct the request accordingly.

An error message stating Unknown, indicates an error that is currently not forseen within our API.

Empty values in created object

Scenario: you try to create an object and receive a 200 Ok response, but the object values are empty or using the default values.

Solution: your request is probably missing or having an invalid Content-Type header, make sure you provide it accordingly to your request e.g. application/json

Memory exhausted

A request can result in a 10005 Memory exhausted error.

It is likely that this request has worked in the past, but due to a growing amount of data now results in this error. Our API is unable to handle the large dataset resulting from your request.

The best way to prevent this error is ensure you use a combination of paging, filtering or reducing the amount of included data.

Report an issue

Most of our errors should be self explanatory, in the event of an Unknown error you can send a support request.

On creating an support request please provide the following information:

  • value of the errors[].reference from the error response
  • the endpoint of the request
  • the request body
  • the expected result
  • the actual result

Service Unavailable

While most of our maintenance is being performed without any downtime. An integration should take in account the following 2 responses:

Code Description Note
303 See Other vPlan Services are not available
503 Service Unavailable A release or maintenance is being performed


The 303 See Other is a last resort redirect to give a proper unavailable notice page

The location that is given will end up in a HTTP 200 response with normal webpage content instead of json.

An integration should:

  • not follow the redirect
  • view the request as failed
  • and try again later.


Response samples

Content type
  • "errors": [
    • {

Retrieve Api Messages

The vPlan API is constantly improving, which means that today's endpoints and features could be replaced or removed in the future.

Where possible and appropriate, the API adds a deprecated header to the response. The API also offers this endpoint to retrieve any messages or warnings recorded during third party requests.

Integrators are expected to review these messages regularly and act accordingly.

query Parameters
Example: sort=updated_at:desc,id

field(s) for sorting the dataset, see sorting for more info

integer >= 0
Default: 0
Example: limit=50

maximum number of records given, see pagination for more info

integer >= 0
Default: 0

the number of records to be skipped, see pagination for more info

Example: filter=created_at:gt:2020-09-26,and,(id:not:starts_with:0000,or,id:contains:FFFF)

used to filter the dataset, see filtering for more info

Example: show=id,updated_at

limit the response to show only specific properties, see slimmed down result for more info

Example: hide=created_at,updated_at

hide properties from the response, see slimmed down result for more info


Response Headers
string <md5>
Example: "62a232916ac3a2f395791c108c295e8d"

Entity Tag, used for caching

string <uuid>
Example: "05cad843-4214-4537-9010-90a7c3ba91f1"

Reference Tag, used for internal tracing and debugging of the request

Response Schema: application/json
string <uuid> /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[8...

Unique identifier

Enum: "info" "warning" "error"

used method that caused the message


used endpoint that caused the message


used query parameters that caused the message


code to categorize the message


full message with details

string <date-time>

Creation date / time

string <date-time>

Update date / time

Response samples

Content type
  • "id": "68e5bf7b-c525-4865-a50b-ad7654b8fd12",
  • "log_level": "warning",
  • "method": "GET",
  • "endpoint": "v1/order",
  • "query_params": {
    • "limit": 2000,
    • "with": "item,order_rows"
  • "message_code": "RESULT_GT_100",
  • "message": "limit=2000, greater than max (1000), count 610",
  • "created_at": "2020-01-02T11:24:35Z",
  • "updated_at": "2020-01-02T11:24:35Z"


Within vPlan we divide our objects in basically 3 sections:

  • configuration
  • third party data
  • base data

The configuration section are objects that are generaly setup at the start and should not change that often. Integrations will probably create a lot of these objects, or otherwise retrieve these objects to use the id's later on.

The third party data section are objects that are pure informational for the front end users. It exists primarily to facilitate integrations to update their data, and give the front end users the option to change values like the title, without losing the original information on screen. Most integrations use these objects to push there plannable objects to vPlan.

The base data section consists of object used in the normal day to day usage of vPlan: Most integrations use these objects to retreive information about the planning and send it back to the original system.


The vPlan API allows for three means of authentication, JWT Token, oAuth 2 or API Key.

API Keys are great for rapid prototyping and easy access.
For increased security, integrations should strive to use OAuth 2, especially if designed for multiple customers.


An API Key is static and gives unsupervised access to an account, to improve security we recommend to replace API Keys at least every 6 months.

Customers will receive reminders advising to replace their API Key.

As stated OAuth does not have this security risk.

In this document the headers are included in the examples, the credentials that need to be filled in this header are replaced with a placeholder {token}.


A JWT token consists of three parts, a header, a payload and a signature. The signature is created on the server with a specific secret, a user cannot construct a token on its own.

The header contains information about the token (type, signature algorithm). The payload contains information about the user and the validity of the token (username, expiration date, issuer). The signature is a hash created with the defined algorithm in the header, signing the information in the token.

Security Scheme Type HTTP
HTTP Authorization Scheme bearer
Bearer format "JWT"


The Api-Key is to be used in combination with X-Api-Env.

The two headers combined can be used as authentication.

Creating an Api-Key

Perform the following steps:

  • log into vPlan
  • in the menu click on Settings
  • in the menu click on API Keys
  • Click on the ADD KEY button
Security Scheme Type API Key
Header parameter name: X-Api-Key


Api-Env is to be used in combination with Api-Key

Security Scheme Type API Key
Header parameter name: X-Api-Env


Resources on oAuth:


OAuth 2 Role Application
Client Application using this API
Resource Server The vPlan API service
Authorization Server Most Wanted OAuth 2 Authorization Server
Resource Owner The user of the vPlan environment

Creating an app

To create an app, that users can connect to their vPlan environment, go to https://developer.vplan.com/
Registration of the app provides a client id and client secret. This information is specific to the app.
The client secret should never be shared publicly.

Registration requires a redirect URI, this should be the base URI to which all callbacks will be performed, this URI should be publicly accessible.

Security Scheme Type OAuth2
authorizationCode OAuth Flow
Authorization URL: https://developer.mostwanted.io/api/v1/oauth/authorize
Token URL: https://developer.mostwanted.io/api/v1/oauth/token

    Get authorization

    In order to create access tokens for a specific vPlan environment, the Resource Owner has to authorize the app to access their vPlan environment.

    To request authorization, the Resource Owner should be redirected to https://developer.mostwanted.io/api/v1/oauth/authorize

    The Resource Owner will be asked to log in to vPlan and allow this app to access the data in his vPlan environment.

    query Parameters
    Example: client_id=176b8c0c-be44-4b0a-805f-28252932b48e

    Client ID of the app

    Example: redirect_uri=https://example.com/callback

    A valid, TLS secured, redirect URI

    Value: "code"

    Response type for the request

    Example: state=33cab0a8-ea0c-48e4-a090-71e9b95ab831

    Unique state, to prevent man-in-the-middle attacks


    Response samples

    Content type
    • "errors": [
      • {