{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"e489efaa-b898-4a6a-a38d-055c34e13f19","name":"Affiliate API","description":"\nThe Affiliate API provides all the tools you need to programmatically:\n - Generate a quote for [Fused Bills](https://fusedbills.co.uk), an all-in-one bills service for students from [One Utility Bill](https://oneutilitybill.co)\n - Submit tenant data to our platform\n\n## Who do I contact about this API?\nTo get in touch with our development team, please email `partnerships-dev@oneutilitybill.co`\n\n## What does the quote include?\nUsing the postcode and bed-size of the property you submit to us, we bundle together gas, electric, water and broadband bills into\none simple monthly payment. As many tenants in the student market split the bills and rent properties on a per person, per week basis,\nwe provide all pricing information on a per person per week, per person per month, as well as a total per month basis.\n\nQuotes are based on:\n - a 12-month fixed term tenancy\n - an unlimited electricity, gas, water and generic broadband service including all fees and taxes. Unless the property is based in Scotland, where water is paid for\ndifferently and therefore, will **not** be included as a service in the quote\n - unlimited energy which means the amount of electric and/or gas used does not affect the price paid by the tenant\n - our Fused product which is aimed at students\n\n **All quotes are representative. The services can be changed by the tenant once they engage with us and create a personalised\nquote.**\n\n## What is the minimum required information to generate a quote?\nCreate a Quote, (`POST /quotes`) by supplying:\n - `postcode` (of the property the quote is for)\n - `bed_size`\n - `tenancy_start_date`\n\n## What is the minimum required information for a lead to be captured?\nCreate a Lead, (`POST /leads`) by supplying:\n - the property information (specifically `address_line_1`, `city` and `postcode`)\n - the tenant's personal details (specifically `first_name`, `last_name`, `email_address`, `phone_number`)\n\nThe following may also be supplied, but are not required:\n - `quote_id` (this is obtained by generating a quote, as detailed above, before submitting the lead. The response will contain a `quote_id`)\n - `tenancy_start_date` (this may be the proposed move in date)\n - `metadata` (this is an array of key-value pairs of additional information about the lead. Allowed keys are `enquiry_id`, `lead_source`, `original_source_agent`, `is_homebuyer`)\n\nThe inclusion of this additional information will help us to provide an improved service to prospective tenants.\n\n## Environments\n\nWe have the following two environments:\n\n### Sandbox\n\nThe sandbox environment is located at [https://partnerships-sandbox.oneutilitybill.co](https://partnerships-sandbox.oneutilitybill.co)\nand the base URL for this is [https://partnerships-sandbox.oneutilitybill.co/api/v1](https://partnerships-sandbox.oneutilitybill.co/api/v1)\n\nThe sandbox environment is a mirror of the production environment, with the following differences:\n - Leads captured will not be passed to One Utility Bill's internal departments and processed\n - Quotes generated do not contain real-world data, i.e. costs are not accurate and descriptions are lorem ipsum\n\nHowever, it would still be prudent not to use any real customer data in this sandbox environment.\n\n### Production\n\nThe production environment is located at [https://partnerships-api.oneutilitybill.co](https://partnerships-api.oneutilitybill.co)\nand the base URL for this is [https://partnerships-api.oneutilitybill.co/api/v1](https://partnerships-api.oneutilitybill.co/api/v1)\n\nAll production data is completely separate to sandbox data, anything done on the production environment will not affect the sandbox\nenvironment and vice versa.\n\n## OpenAPI Specification\n\nAn up-to-date OpenAPI 3.0 specification file can be found [here](https://partnerships-sandbox.oneutilitybill.co/docs), ready to be consumed by your own OpenAPI tooling.\n\n## Getting Started\n\nTo get started using the Affiliate API please get in touch with Amie Henzell at `amie.henzell@oneutilitybill.co` who will take you through the onboarding process.\n\nWhen it is time for you to integrate with our Sandbox Environment, our development team will help get you started. We can always be reached at `partnerships-dev@oneutilitybill.co`.\n\n **We will create for you**:\n\n- The necessary OAuth 2.0 credentials, consisting of a Client ID & Client Secret, which is required to complete the OAuth 2.0 Client Credentials flow.\n\nOnce we are both happy with your integration in the sandbox environment, we will create the necessary production OAuth 2.0 credentials.\n\n## Authentication\n\nThe Affiliate API uses the standard OAuth 2.0 protocol for authentication and authorization.\n\nIt supports the [Client Credentials grant type](https://oauth.net/2/grant-types/client-credentials/).\nYou use a Client ID & Client Secret to acquire a short-lived Access Token.\n\nWe will provide you with the Client ID & Client Secret, which you should store securely.\nWe only support server to server API communication, you **should not** store these in the browser or make calls directly to the Affiliate API from a browser.\n\n **We recommend using [popular maintained OAuth 2.0 libraries](https://oauth.net/code/) to help you complete the authentication process.**\n\n### Scopes\n\nThe Affiliate API currently supports the following [scopes](https://oauth.net/2/scope/) to define what access your Access Token will be granted:\n- `leads` - Read & write access to the Leads resource\n- `quotes` - Read & write access to the Quotes resource\n\n### Authentication (retrieving an Access Token)\n\nTo perform authentication, issue a `POST` request as shown below to the `/oauth/token` endpoint\n\n```\nPOST https://partnerships-sandbox.oneutilitybill.co/oauth/token HTTP/1.1\nContent-Type: application/x-www-form-urlencoded\n...\ngrant_type=client_credentials\n&client_id=xxxxxxxxxxxxxxxxxx\n&client_secret=xxxxxxxxxxxxxx\n&scope=leads+quotes\n```\n\nHere's each request body parameter explained (remember to URL encode them):\n\n- `grant_type=client_credentials` - This tells the token endpoint it is using the Client Credentials flow\n- `client_id` - This is your `client_id`\n- `client_secret` - This is your `client_secret`\n- `scope` - This is a space separated list of scopes you are requesting (see the Scopes section above)\n\nIf everything checks out, you will receive a response like the following:\n```\nHTTP/1.1 200 OK\nContent-Type: application/json\nCache-Control: no-store\nPragma: no-cache\n...\n{\n\"access_token\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n\"token_type\":\"Bearer\",\n\"expires_in\":3600\n}\n```\n\n **Access Tokens issued by the Affiliate API are valid for 3600 seconds (1 hour).**\n\nYou **will not** receive a Refresh Token as part of this response because the Client Credentials grant type does not use Refresh Tokens.\n\n### Access Token Expiry\n\nOnce your Access Token expires, you will begin to receive `401 Unauthorized` errors from your API requests.\n\nTo acquire a new Access Token, simply repeat the same call described above to the `/oauth/token` endpoint to acquire a new Access Token.\n\nAcquiring a new Access Token **does not** revoke previously issued Access Tokens.\n\n### Using your access token\n\nWhen you have an access token, you can use it in the request's HTTP header in the format `Authorization: Bearer <access_token>`, for example: `Authorization: Bearer xxxxxxxxxxxxxxxxxxx`\n\n## Error Structures\n\n## Errors\n\nAll errors returned by the API follow the same structure. We do not list every possible error response for each endpoint.\nInstead, the common error responses are listed below. Fields which will always be present will be `message` and `meta`\ncontaining at least one field named `request_id`.\n\n### 422 Unprocessable Entity\n\nThis error is returned when the request body you have provided contains validation errors.\nIf there are multiple validation errors, an errors object will be returned and keyed by the violating field, and it's value\nbeing a string array of errors relating to that field.\n\n```json\n{\n    \"message\": \"The postcode must be at least 5 characters. (and 3 more errors)\",\n    \"errors\": {\n        \"postcode\": [\n            \"The postcode must be at least 5 characters.\",\n            \"Postcode is malformed.\",\n            \"Postcode is not within England, Scotland or Wales.\"\n        ],\n        \"bed_size\": [\n            \"The bed size must be at least 1.\"\n        ]\n    },\n    \"meta\": {\n        \"request_id\": \"c36460cbd8f5ed91198066a9e870f0c5dfb11e3b\"\n    }\n}\n```\n\n### 401 Unauthorized\n\nThis error is returned when the OAuth 2.0 authorization credentials provided are invalid. This may be due to no\ncredentials being provided, invalid credentials, the wrong header being used, or an invalid / expired access token.\n\n```json\n{\n    \"message\": \"Unauthenticated.\",\n    \"meta\": {\n        \"request_id\": \"61da55be459854e09e8e4dad0574af85fb089239\"\n    }\n}\n```\n\n## Rate Limiting\n\nThe Affiliate API features rate limiting to ensure a quality experience for all consumers of the API.\n\nThe rate limits described below apply to you as a consumer (as identified by a Client ID / Secret).\n\n### Sandbox Rate Limits\n\nTo allow you to more easily encounter and test rate limits when building your integration, we have set the limits to a lower value.\n\nThey are currently: **25 requests per 10 seconds.**\n\nThese are subject to change.\n\n### Production Rate Limits\n\nFor production, we'll never plan to decrease these limits but they could be increased in the future.\n\nThey are currently: **50 requests per 10 seconds.**\n\nThese are subject to change.\n\n### Rate Limiting Headers\n\nThe following headers are present on **every** API response:\n\n- `X-RateLimit-Limit`: This is an integer representing the total limit for the current timeframe\n- `X-RateLimit-Remaining`: This is an integer representing how many requests you have left for the current timeframe\n\nFor example, after making 3 requests in a row on the Sandbox environment you would see:\n\n```\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 57\n```\n\n### Rate Limiting Error Responses\n\nOnce you hit the rate limit you will receive a 429 Too Many Requests error like the following:\n\n```\nHTTP/1.1 429 Too Many Requests\nContent-Type: application/json\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 0\nRetry-After: 5\nX-RateLimit-Reset: 1665523508\n...\n{\n\"message\": \"Too Many Attempts.\"\n}\n```\n\nTwo new headers are included in 429 error responses:\n\n- `Retry-After`: This is an integer representing the total number of seconds you should wait before making another request\n- `X-RateLimit-Reset`: This is an integer representing the Unix time in UTC when the rate limit will reset, and you can make another request\n\n# API Features\n\n## Dates\n\nWe handle both Dates & Timestamps consistently across all of our requests and responses.\n\nDates are accepted & provided in `Y-m-d` format. For example, `2020-05-02`.\n\nTimestamps are returned in [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) Zulu Time format, unless stated otherwise. For example, `2020-05-02T09:52:36Z`.\n\n## Versioning\n\nWe use API wide versioning, specified in the URL. The version number is specified in the base URL, following `/api/` and preceding the resource name.\n\n### Breaking changes\n\nA breaking change refers to any change that would require you to update your application in order to continue working with the Affiliate API as originally intended.\n\nWe consider the following to be breaking changes:\n\n - Renaming an API field or resource\n - Removing an API field or resource\n - Changes to the required fields for an endpoint\n\nIf we are intending to make a breaking change, we will communicate this ahead of time to ensure you are able to make the changes in your integration.\n\nWe may from time to time make additive changes to our API without incrementing the version number.\n\nWe may add new resources and fields to an existing version of the API, and these will not be considered breaking changes. Our API documentation\nexplaining the purpose of the changes will be updated.\n\n **As such, you should design your integration to be flexible enough to not break when new fields are added to resources.**\n\n## UUIDs\n\nFor all of our resource IDs, we use UUIDs following the UUID version 7 format.\n\n","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"12606501","team":1225174,"collectionId":"e489efaa-b898-4a6a-a38d-055c34e13f19","publishedId":"2s8Z76wUiZ","public":true,"publicUrl":"https://affiliate-docs.oneutilitybill.co","privateUrl":"https://go.postman.co/documentation/12606501-e489efaa-b898-4a6a-a38d-055c34e13f19","customColor":{"top-bar":"FFFFFF","right-sidebar":"3D3D3D","highlight":"FE963D"},"documentationLayout":"classic-double-column","customisation":null,"version":"8.10.1","publishDate":"2023-02-02T12:51:11.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{},"logos":{}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/fb2ae7876a0248d6f9a6d492a15e95851a01265e235eef3cb92ffab6dbbf792e","favicon":"https://res.cloudinary.com/postman/image/upload/v1673350475/team/bwvjhexj58ia6tig7qhf.ico"},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://affiliate-docs.oneutilitybill.co/view/metadata/2s8Z76wUiZ"}