API Documentation

API Endpoint

Integrations

Integrations

Webhooks

Integration endpoint is used for webhooks. Supported webhooks events are:

  • New invoice, webhook_event_id: 2

  • Updated invoice, webhook_event_id: 14

  • Deleted invoice webhook_event_id: 15

  • New deal, webhook_event_id: 3

  • Updated deal, webhook_event_id: 12

  • Deleted deal webhook_event_id: 13

  • New project, webhook_event_id: 5

  • Updated project, webhook_event_id: 10

  • Deleted project webhook_event_id: 11

  • New time entry, webhook_event_id: 7

  • Updated time entry, webhook_event_id: 8

  • Deleted time entry webhook_event_id: 9

Webhooks Signature

All webhooks are signed with a unique signature in the request header named ‘Productive-Signature’. Productive-Signature contains a timestamp designated with t= and a signature designated with s=.

Example of a signature:

Productive-Signature: t=1568031758, s=e8dddb4e3db0faf0c970943bb53b23e27af4d46eb770cac9312fe29a4034ddb1

A signature can be created from:

  • a token: unique token of the webhook

  • a timestamp: timestamp of current time when a webhook was called

  • a payload: serialised object as JSON

To authenticate a signature, generate one and compare it to the one in the header with the following:

OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), {token}, "{timestamp}.{payload.to_json}")

Webhooks Retry

For all webhook executions which do not respond with status code 2xx, webhook will retry with 25 more executions for the next two days.

GET /api/v2/integrations
Requestsreturns integrations

GET  /api/v2/integrations

Headers
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Content-Type: application/vnd.api+json
Responses200
Headers
Content-Type: application/vnd.api+json; charset=utf-8
Body
{
  "data": [
    {
      "id": "1",
      "type": "integrations",
      "attributes": {
        "name": null,
        "integration_type_id": 2,
        "requested_at": null,
        "request_token": null,
        "request_uri": null,
        "connected_at": null,
        "account_code": null,
        "webhook_event_id": null,
        "deactivated_at": null,
        "options": {},
        "export_number": null,
        "export_attachment": null
      },
      "relationships": {
        "organization": {
          "data": {
            "type": "organizations",
            "id": 305
          }
        },
        "subsidiary": {
          "data": null
        },
        "project": {
          "data": null
        }
      }
    }
  ],
  "links": {
    "first": "http://www.example.com/api/v2/integrations?page%5Bnumber%5D=1&page%5Bsize%5D=30",
    "last": "http://www.example.com/api/v2/integrations?page%5Bnumber%5D=1&page%5Bsize%5D=30"
  },
  "meta": {
    "current_page": 1,
    "total_pages": 1,
    "total_count": 1,
    "page_size": 30,
    "max_page_size": 200,
    "organization_features": {
      "custom_fields": {
        "type": "metered",
        "limit": 15,
        "used": 0
      },
      "custom_fields_per_project": {
        "type": "metered",
        "limit": 10,
        "used": 0
      },
      "public_custom_reports": {
        "type": "metered",
        "limit": 30,
        "used": 0
      },
      "private_custom_reports": {
        "type": "metered",
        "limit": 30,
        "used": 0
      },
      "scheduling_placeholders": {
        "type": "metered",
        "limit": 5,
        "used": 0
      },
      "multigrouping": {
        "type": "switch",
        "available": true
      },
      "client_access_to_budgets": {
        "type": "switch",
        "available": true
      },
      "subsidiaries": {
        "type": "switch",
        "available": true
      },
      "time_approvals": {
        "type": "switch",
        "available": true
      },
      "expenses_approvals": {
        "type": "switch",
        "available": true
      },
      "timeoff_approvals": {
        "type": "switch",
        "available": true
      },
      "autotracking": {
        "type": "switch",
        "available": true
      },
      "forecasting": {
        "type": "switch",
        "available": true
      },
      "webhooks": {
        "type": "switch",
        "available": true
      },
      "table_pivoting": {
        "type": "switch",
        "available": true
      },
      "formula_fields": {
        "type": "switch",
        "available": true
      },
      "single_sign_on": {
        "type": "switch",
        "available": true
      }
    }
  }
}

Get integration
GET/api/v2/integrations


GET /api/v2/integrations/1
Requestsreturns integration

GET  /api/v2/integrations/2

Headers
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Content-Type: application/vnd.api+json
Responses200
Headers
Content-Type: application/vnd.api+json; charset=utf-8
Body
{
  "data": {
    "id": "2",
    "type": "integrations",
    "attributes": {
      "name": null,
      "integration_type_id": 2,
      "requested_at": null,
      "request_token": null,
      "request_uri": null,
      "connected_at": null,
      "account_code": null,
      "webhook_event_id": null,
      "deactivated_at": null,
      "options": {},
      "export_number": null,
      "export_attachment": null
    },
    "relationships": {
      "organization": {
        "data": {
          "type": "organizations",
          "id": 306
        }
      },
      "subsidiary": {
        "data": null
      },
      "project": {
        "data": null
      }
    }
  },
  "meta": {
    "organization_features": {
      "custom_fields": {
        "type": "metered",
        "limit": 15,
        "used": 0
      },
      "custom_fields_per_project": {
        "type": "metered",
        "limit": 10,
        "used": 0
      },
      "public_custom_reports": {
        "type": "metered",
        "limit": 30,
        "used": 0
      },
      "private_custom_reports": {
        "type": "metered",
        "limit": 30,
        "used": 0
      },
      "scheduling_placeholders": {
        "type": "metered",
        "limit": 5,
        "used": 0
      },
      "multigrouping": {
        "type": "switch",
        "available": true
      },
      "client_access_to_budgets": {
        "type": "switch",
        "available": true
      },
      "subsidiaries": {
        "type": "switch",
        "available": true
      },
      "time_approvals": {
        "type": "switch",
        "available": true
      },
      "expenses_approvals": {
        "type": "switch",
        "available": true
      },
      "timeoff_approvals": {
        "type": "switch",
        "available": true
      },
      "autotracking": {
        "type": "switch",
        "available": true
      },
      "forecasting": {
        "type": "switch",
        "available": true
      },
      "webhooks": {
        "type": "switch",
        "available": true
      },
      "table_pivoting": {
        "type": "switch",
        "available": true
      },
      "formula_fields": {
        "type": "switch",
        "available": true
      },
      "single_sign_on": {
        "type": "switch",
        "available": true
      }
    }
  }
}

Gets an integration
GET/api/v2/integrations/{id}

URI Parameters
HideShow
id
number (required) Example: 1

integration id


POST /api/v2/integrations
Requestscreates integrationreturns errorreturns error

POST  /api/v2/integrations

Headers
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Content-Type: application/vnd.api+json
Body
{
  "data": {
    "type": "integrations",
    "attributes": {
      "redirect_uri": "http://app.productive.io.localhost/integrations/quickbooks",
      "integration_type_id": 2
    },
    "relationships": {
      "subsidiary": {
        "data": {
          "type": "subsidiaries",
          "id": "40"
        }
      }
    }
  }
}
Responses201
Headers
Content-Type: application/vnd.api+json; charset=utf-8
Body
{
  "data": {
    "id": "4",
    "type": "integrations",
    "attributes": {
      "name": null,
      "integration_type_id": 2,
      "requested_at": "2020-08-11T01:04:35.000+02:00",
      "request_token": "1abad16c158a31afcb180684",
      "request_uri": "https://appcenter.intuit.com/connect/oauth2?client_id=Q08lq2LdTQpor8vzsmrd0hsOMTJIspIyLFrkMzVnVrumGE4Rq7&redirect_uri=http%3A%2F%2Fapp.productive.io.localhost%2Fintegrations%2Fquickbooks&response_type=code&scope=com.intuit.quickbooks.accounting&state=307%2F4%2F1abad16c158a31afcb180684",
      "connected_at": null,
      "account_code": null,
      "webhook_event_id": null,
      "deactivated_at": null,
      "options": {},
      "export_number": null,
      "export_attachment": null
    },
    "relationships": {
      "organization": {
        "data": {
          "type": "organizations",
          "id": 307
        }
      },
      "subsidiary": {
        "data": {
          "type": "subsidiaries",
          "id": "40"
        }
      },
      "project": {
        "data": null
      }
    }
  },
  "included": [
    {
      "id": "40",
      "type": "subsidiaries",
      "attributes": {
        "name": "Subsidiary40",
        "invoice_number_format": null,
        "deleted_at": null,
        "archived_at": null,
        "export_integration_type_id": null,
        "invoice_logo_url": null
      },
      "relationships": {
        "organization": {
          "data": {
            "type": "organizations",
            "id": 307
          }
        },
        "bill_from": {
          "data": null
        },
        "integration": {
          "data": {
            "type": "integrations",
            "id": "4"
          }
        }
      }
    }
  ],
  "meta": {
    "organization_features": {
      "custom_fields": {
        "type": "metered",
        "limit": 15,
        "used": 0
      },
      "custom_fields_per_project": {
        "type": "metered",
        "limit": 10,
        "used": 0
      },
      "public_custom_reports": {
        "type": "metered",
        "limit": 30,
        "used": 0
      },
      "private_custom_reports": {
        "type": "metered",
        "limit": 30,
        "used": 0
      },
      "scheduling_placeholders": {
        "type": "metered",
        "limit": 5,
        "used": 0
      },
      "multigrouping": {
        "type": "switch",
        "available": true
      },
      "client_access_to_budgets": {
        "type": "switch",
        "available": true
      },
      "subsidiaries": {
        "type": "switch",
        "available": true
      },
      "time_approvals": {
        "type": "switch",
        "available": true
      },
      "expenses_approvals": {
        "type": "switch",
        "available": true
      },
      "timeoff_approvals": {
        "type": "switch",
        "available": true
      },
      "autotracking": {
        "type": "switch",
        "available": true
      },
      "forecasting": {
        "type": "switch",
        "available": true
      },
      "webhooks": {
        "type": "switch",
        "available": true
      },
      "table_pivoting": {
        "type": "switch",
        "available": true
      },
      "formula_fields": {
        "type": "switch",
        "available": true
      },
      "single_sign_on": {
        "type": "switch",
        "available": true
      }
    }
  }
}

POST  /api/v2/integrations

Headers
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Content-Type: application/vnd.api+json
Body
{
  "data": {
    "type": "integrations",
    "attributes": {
      "integration_type_id": ""
    },
    "relationships": {
      "subsidiary": {
        "data": {
          "type": "subsidiaries",
          "id": "41"
        }
      }
    }
  }
}
Responses422
Headers
Content-Type: application/vnd.api+json; charset=utf-8
Body
{
  "errors": [
    {
      "status": "422",
      "code": "invalid_attribute",
      "title": "Invalid Attribute",
      "detail": "can't be blank",
      "source": {
        "pointer": "data/attributes/integration_type"
      }
    }
  ]
}

POST  /api/v2/integrations

Headers
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Content-Type: application/vnd.api+json
Body
{
  "data": {
    "type": "integrations",
    "attributes": {
      "redirect_uri": "http://app.productive.io.localhost/integrations/quickbooks",
      "integration_type_id": 2
    },
    "relationships": {
      "subsidiary": {
        "data": {
          "type": "subsidiaries",
          "id": "42"
        }
      }
    }
  }
}
Responses422
Headers
Content-Type: application/vnd.api+json; charset=utf-8
Body
{
  "errors": [
    {
      "status": "422",
      "code": "invalid_attribute",
      "title": "Invalid Attribute",
      "detail": "subsidiary integration already exists",
      "source": {
        "pointer": "data/attributes/subsidiary"
      }
    }
  ]
}

Create an integration
POST/api/v2/integrations

URI Parameters
HideShow
name
string (optional) Example: Name

name

integration_type_id
number (required) Example: 6

integration type id

webhook_event_id
number (required) Example: 7

webhook event id

target_url
string (required) Example: http%3A%2F%2Fwebhook.com

target url


DELETE /api/v2/integrations/1
Requestsdeletes integration

DELETE  /api/v2/integrations/11

Headers
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Content-Type: application/vnd.api+json
Responses204
This response has no content.

Deletes an integration
DELETE/api/v2/integrations/{id}

URI Parameters
HideShow
id
number (required) Example: 1

integration id


Generated by aglio on 10 Aug 2020