A Java library to convert numbers from digital format to words format in Arabic language.
NxParser is a Java open source, streaming, non-validating parser for the Nx format, where x = Triples, Quads, or any other number.
NxParser is a Java open source, streaming, non-validating parser for the Nx format, where x = Triples, Quads, or any other number.
WebJar for format-number-with-string
pact-jvm-provider-gradle ======================== Gradle plugin for verifying pacts against a provider. The Gradle plugin creates a task `pactVerify` to your build which will verify all configured pacts against your provider. __*Important Note: Any properties that need to be set when using the Gradle plugin need to be provided with `-P` and not `-D` as with the other Pact-JVM modules!*__ ## To Use It ### For Gradle versions prior to 2.1 #### 1.1. Add the pact-jvm-provider-gradle jar file to your build script class path: ```groovy buildscript { repositories { mavenCentral() } dependencies { classpath 'au.com.dius:pact-jvm-provider-gradle:4.0.0' } } ``` #### 1.2. Apply the pact plugin ```groovy apply plugin: 'au.com.dius.pact' ``` ### For Gradle versions 2.1+ ```groovy plugins { id "au.com.dius.pact" version "4.0.0" } ``` ### 2. Define the pacts between your consumers and providers ```groovy pact { serviceProviders { // You can define as many as you need, but each must have a unique name provider1 { // All the provider properties are optional, and have sensible defaults (shown below) protocol = 'http' host = 'localhost' port = 8080 path = '/' // Again, you can define as many consumers for each provider as you need, but each must have a unique name hasPactWith('consumer1') { // currently supports a file path using file() or a URL using url() pactSource = file('path/to/provider1-consumer1-pact.json') } // Or if you have many pact files in a directory hasPactsWith('manyConsumers') { // Will define a consumer for each pact file in the directory. // Consumer name is read from contents of pact file pactFileLocation = file('path/to/pacts') } } } } ``` ### 3. Execute `gradle pactVerify` ## Specifying the provider hostname at runtime If you need to calculate the provider hostname at runtime, you can give a Closure as the provider `host`. ```groovy pact { serviceProviders { provider1 { host = { lookupHostName() } hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` You can also give a Closure as the provider `port`. ## Specifying the pact file or URL at runtime If you need to calculate the pact file or URL at runtime, you can give a Closure as the provider `pactFile`. ```groovy pact { serviceProviders { provider1 { host = 'localhost' hasPactWith('consumer1') { pactFile = { lookupPactFile() } } } } } ``` ## Starting and shutting down your provider If you need to start-up or shutdown your provider, define Gradle tasks for each action and set `startProviderTask` and `terminateProviderTask` properties of each provider. You could use the jetty tasks here if you provider is built as a WAR file. ```groovy // This will be called before the provider task task('startTheApp') { doLast { // start up your provider here } } // This will be called after the provider task task('killTheApp') { doLast { // kill your provider here } } pact { serviceProviders { provider1 { startProviderTask = startTheApp terminateProviderTask = killTheApp hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` Following typical Gradle behaviour, you can set the provider task properties to the actual tasks, or to the task names as a string (for the case when they haven't been defined yet). ## Preventing the chaining of provider verify task to `pactVerify` Normally a gradle task named `pactVerify_${provider.name}` is created and added as a task dependency for `pactVerify`. You can disable this dependency on a provider by setting `isDependencyForPactVerify` to `false` (defaults to `true`). ```groovy pact { serviceProviders { provider1 { isDependencyForPactVerify = false hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` To run this task, you would then have to explicitly name it as in ```gradle pactVerify_provider1```, a normal ```gradle pactVerify``` would skip it. This can be useful when you want to define two providers, one with `startProviderTask`/`terminateProviderTask` and as second without, so you can manually start your provider (to debug it from your IDE, for example) but still want a `pactVerify` to run normally from your CI build. ## Enabling insecure SSL For providers that are running on SSL with self-signed certificates, you need to enable insecure SSL mode by setting `insecure = true` on the provider. ```groovy pact { serviceProviders { provider1 { insecure = true // allow SSL with a self-signed cert hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` ## Specifying a custom trust store For environments that are running their own certificate chains: ```groovy pact { serviceProviders { provider1 { trustStore = new File('relative/path/to/trustStore.jks') trustStorePassword = 'changeit' hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` `trustStore` is either relative to the current working (build) directory. `trustStorePassword` defaults to `changeit`. NOTE: The hostname will still be verified against the certificate. ## Modifying the HTTP Client Used The default HTTP client is used for all requests to providers (created with a call to `HttpClients.createDefault()`). This can be changed by specifying a closure assigned to createClient on the provider that returns a CloseableHttpClient. For example: ```groovy pact { serviceProviders { provider1 { createClient = { provider -> // This will enable the client to accept self-signed certificates HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()) .setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, { x509Certificates, s -> true }) .build()) .build() } hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` ## Modifying the requests before they are sent Sometimes you may need to add things to the requests that can't be persisted in a pact file. Examples of these would be authentication tokens, which have a small life span. The Pact Gradle plugin provides a request filter that can be set to a closure on the provider that will be called before the request is made. This closure will receive the HttpRequest prior to it being executed. ```groovy pact { serviceProviders { provider1 { requestFilter = { req -> // Add an authorization header to each request req.addHeader('Authorization', 'OAUTH eyJhbGciOiJSUzI1NiIsImN0eSI6ImFw...') } hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` __*Important Note:*__ You should only use this feature for things that can not be persisted in the pact file. By modifying the request, you are potentially modifying the contract from the consumer tests! ## Turning off URL decoding of the paths in the pact file By default the paths loaded from the pact file will be decoded before the request is sent to the provider. To turn this behaviour off, set the property `pact.verifier.disableUrlPathDecoding` to `true`. __*Important Note:*__ If you turn off the url path decoding, you need to ensure that the paths in the pact files are correctly encoded. The verifier will not be able to make a request with an invalid encoded path. ## Project Properties The following project properties can be specified with `-Pproperty=value` on the command line: |Property|Description| |--------|-----------| |`pact.showStacktrace`|This turns on stacktrace printing for each request. It can help with diagnosing network errors| |`pact.showFullDiff`|This turns on displaying the full diff of the expected versus actual bodies| |`pact.filter.consumers`|Comma seperated list of consumer names to verify| |`pact.filter.description`|Only verify interactions whose description match the provided regular expression| |`pact.filter.providerState`|Only verify interactions whose provider state match the provided regular expression. An empty string matches interactions that have no state| |`pact.filter.pacturl`|This filter allows just the just the changed pact specified in a webhook to be run. It should be used in conjunction with `pact.filter.consumers` | |`pact.verifier.publishResults`|Publishing of verification results will be skipped unless this property is set to 'true'| |`pact.matching.wildcard`|Enables matching of map values ignoring the keys when this property is set to 'true'| |`pact.verifier.disableUrlPathDecoding`|Disables decoding of request paths| |`pact.pactbroker.httpclient.usePreemptiveAuthentication`|Enables preemptive authentication with the pact broker when set to `true`| |`pact.provider.tag`|Sets the provider tag to push before publishing verification results| ## Provider States For a description of what provider states are, see the pact documentations: http://docs.pact.io/documentation/provider_states.html ### Using a state change URL For each provider you can specify a state change URL to use to switch the state of the provider. This URL will receive the providerState description and all the parameters from the pact file before each interaction via a POST. As for normal requests, a request filter (`stateChangeRequestFilter`) can also be set to manipulate the request before it is sent. ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') stateChangeUrl = url('http://localhost:8001/tasks/pactStateChange') stateChangeUsesBody = false // defaults to true stateChangeRequestFilter = { req -> // Add an authorization header to each request req.addHeader('Authorization', 'OAUTH eyJhbGciOiJSUzI1NiIsImN0eSI6ImFw...') } } // or hasPactsWith('consumers') { pactFileLocation = file('path/to/pacts') stateChangeUrl = url('http://localhost:8001/tasks/pactStateChange') stateChangeUsesBody = false // defaults to true } } } } ``` If the `stateChangeUsesBody` is not specified, or is set to true, then the provider state description and parameters will be sent as JSON in the body of the request : ```json { "state" : "a provider state description", "params": { "a": "1", "b": "2" } } ``` If it is set to false, they will be passed as query parameters. #### Teardown calls for state changes You can enable teardown state change calls by setting the property `stateChangeTeardown = true` on the provider. This will add an `action` parameter to the state change call. The setup call before the test will receive `action=setup`, and then a teardown call will be made afterwards to the state change URL with `action=teardown`. ### Using a Closure You can set a closure to be called before each verification with a defined provider state. The closure will be called with the state description and parameters from the pact file. ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') // Load a fixture file based on the provider state and then setup some database // data. Does not require a state change request so returns false stateChange = { providerState -> // providerState is an instance of ProviderState def fixture = loadFixtuerForProviderState(providerState) setupDatabase(fixture) } } } } } ``` #### Teardown calls for state changes You can enable teardown state change calls by setting the property `stateChangeTeardown = true` on the provider. This will add an `action` parameter to the state change closure call. The setup call before the test will receive `setup`, as the second parameter, and then a teardown call will be made afterwards with `teardown` as the second parameter. ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') // Load a fixture file based on the provider state and then setup some database // data. Does not require a state change request so returns false stateChange = { providerState, action -> if (action == 'setup') { def fixture = loadFixtuerForProviderState(providerState) setupDatabase(fixture) } else { cleanupDatabase() } false } } } } } ``` #### Returning values that can be injected You can have values from the provider state callbacks be injected into most places (paths, query parameters, headers, bodies, etc.). This works by using the V3 spec generators with provider state callbacks that return values. One example of where this would be useful is API calls that require an ID which would be auto-generated by the database on the provider side, so there is no way to know what the ID would be beforehand. There are methods on the consumer DSLs that can provider an expression that contains variables (like '/api/user/${id}' for the path). The provider state callback can then return a map for values, and the `id` attribute from the map will be expanded in the expression. For URL callbacks, the values need to be returned as JSON in the response body. ## Filtering the interactions that are verified You can filter the interactions that are run using three project properties: `pact.filter.consumers`, `pact.filter.description` and `pact.filter.providerState`. Adding `-Ppact.filter.consumers=consumer1,consumer2` to the command line will only run the pact files for those consumers (consumer1 and consumer2). Adding `-Ppact.filter.description=a request for payment.*` will only run those interactions whose descriptions start with 'a request for payment'. `-Ppact.filter.providerState=.*payment` will match any interaction that has a provider state that ends with payment, and `-Ppact.filter.providerState=` will match any interaction that does not have a provider state. ## Verifying pact files from a pact broker You can setup your build to validate against the pacts stored in a pact broker. The pact gradle plugin will query the pact broker for all consumers that have a pact with the provider based on its name. For example: ```groovy pact { serviceProviders { provider1 { // You can get the latest pacts from the broker hasPactsFromPactBroker('http://pact-broker:5000/') // And/or you can get the latest pact with a specific tag hasPactsFromPactBrokerWithTag('http://pact-broker:5000/',"tagname") } } } ``` This will verify all pacts found in the pact broker where the provider name is 'provider1'. If you need to set any values on the consumers from the pact broker, you can add a Closure to configure them. ```groovy pact { serviceProviders { provider1 { hasPactsFromPactBroker('http://pact-broker:5000/') { consumer -> stateChange = { providerState -> /* state change code here */ true } } } } } ``` **NOTE: Currently the pacts are fetched from the broker during the configuration phase of the build. This means that if the broker is not available, you will not be able to run any Gradle tasks.** This should be fixed in a forth coming release. In the mean time, to only load the pacts when running the validate task, you can do something like: ```groovy pact { serviceProviders { provider1 { // Only load the pacts from the broker if the start tasks from the command line include pactVerify if ('pactVerify' in gradle.startParameter.taskNames) { hasPactsFromPactBroker('http://pact-broker:5000/') { consumer -> stateChange = { providerState -> /* state change code here */ true } } } } } } ``` ### Using an authenticated Pact Broker You can add the authentication details for the Pact Broker like so: ```groovy pact { serviceProviders { provider1 { hasPactsFromPactBroker('http://pact-broker:5000/', authentication: ['Basic', pactBrokerUser, pactBrokerPassword]) } } } ``` `pactBrokerUser` and `pactBrokerPassword` can be defined in the gradle properties. Or with a bearer token: ```groovy pact { serviceProviders { provider1 { hasPactsFromPactBroker('http://pact-broker:5000/', authentication: ['Bearer', pactBrokerToken]) } } } ``` Preemptive Authentication can be enabled by setting the `pact.pactbroker.httpclient.usePreemptiveAuthentication` property to `true`. ### Allowing just the changed pact specified in a webhook to be verified [4.0.6+] When a consumer publishes a new version of a pact file, the Pact broker can fire off a webhook with the URL of the changed pact file. To allow only the changed pact file to be verified, you can override the URL by using the `pact.filter.consumers` and `pact.filter.pacturl` project properties. For example, running: ```console gradle pactVerify -Ppact.filter.consumers='Foo Web Client' -Ppact.filter.pacturl=https://test.pact.dius.com.au/pacts/provider/Activity%20Service/consumer/Foo%20Web%20Client/version/1.0.1 ``` will only run the verification for Foo Web Client with the given pact file URL. ## Verifying pact files from a S3 bucket **NOTE:** You will need to add the Amazon S3 SDK jar file to your project. Pact files stored in an S3 bucket can be verified by using an S3 URL to the pact file. I.e., ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = 's3://bucketname/path/to/provider1-consumer1-pact.json' } } } } ``` **NOTE:** you can't use the `url` function with S3 URLs, as the URL and URI classes from the Java SDK don't support URLs with the s3 scheme. # Publishing pact files to a pact broker The pact gradle plugin provides a `pactPublish` task that can publish all pact files in a directory to a pact broker. To use it, you need to add a publish configuration to the pact configuration that defines the directory where the pact files are and the URL to the pact broker. For example: ```groovy pact { publish { pactDirectory = '/pact/dir' // defaults to $buildDir/pacts pactBrokerUrl = 'http://pactbroker:1234' } } ``` You can set any tags that the pacts should be published with by setting the `tags` property. A common use of this is setting the tag to the current source control branch. This supports using pact with feature branches. ```groovy pact { publish { pactDirectory = '/pact/dir' // defaults to $buildDir/pacts pactBrokerUrl = 'http://pactbroker:1234' tags = [project.pactBrokerTag] } } ``` _NOTE:_ The pact broker requires a version for all published pacts. The `pactPublish` task will use the version of the gradle project by default. You can override this with the `providerVersion` property. Make sure you have set one otherwise the broker will reject the pact files. ## Publishing to an authenticated pact broker To publish to a broker protected by basic auth, include the username/password in the `pactBrokerUrl`. For example: ```groovy pact { publish { pactBrokerUrl = 'https://username:password@mypactbroker.com' } } ``` You can add the username and password as properties. ```groovy pact { publish { pactBrokerUrl = 'https://mypactbroker.com' pactBrokerUsername = 'username' pactBrokerPassword = 'password' } } ``` or with a bearer token ```groovy pact { publish { pactBrokerUrl = 'https://mypactbroker.com' pactBrokerToken = 'token' } } ``` ## Excluding pacts from being published You can exclude some of the pact files from being published by providing a list of regular expressions that match against the base names of the pact files. For example: ```groovy pact { publish { pactBrokerUrl = 'https://mypactbroker.com' excludes = [ '.*\\-\\d+$' ] // exclude all pact files that end with a dash followed by a number in the name } } ``` # Verifying a message provider The Gradle plugin has been updated to allow invoking test methods that can return the message contents from a message producer. To use it, set the way to invoke the verification to `ANNOTATED_METHOD`. This will allow the pact verification task to scan for test methods that return the message contents. Add something like the following to your gradle build file: ```groovy pact { serviceProviders { messageProvider { verificationType = 'ANNOTATED_METHOD' packagesToScan = ['au.com.example.messageprovider.*'] // This is optional, but leaving it out will result in the entire // test classpath being scanned hasPactWith('messageConsumer') { pactFile = url('url/to/messagepact.json') } } } } ``` Now when the `pactVerify` task is run, will look for methods annotated with `@PactVerifyProvider` in the test classpath that have a matching description to what is in the pact file. ```groovy class ConfirmationKafkaMessageBuilderTest { @PactVerifyProvider('an order confirmation message') String verifyMessageForOrder() { Order order = new Order() order.setId(10000004) order.setExchange('ASX') order.setSecurityCode('CBA') order.setPrice(BigDecimal.TEN) order.setUnits(15) order.setGst(new BigDecimal('15.0')) order.setFees(BigDecimal.TEN) def message = new ConfirmationKafkaMessageBuilder() .withOrder(order) .build() JsonOutput.toJson(message) } } ``` It will then validate that the returned contents matches the contents for the message in the pact file. ## Publishing to the Gradle Community Portal To publish the plugin to the community portal: $ ./gradlew :pact-jvm-provider-gradle_2.11:publishPlugins # Verification Reports The default behaviour is to display the verification being done to the console, and pass or fail the build via the normal Gradle mechanism. Additional reports can be generated from the verification. ## Enabling additional reports The verification reports can be controlled by adding a reports section to the pact configuration in the gradle build file. For example: ```groovy pact { reports { defaultReports() // adds the standard console output markdown // report in markdown format json // report in json format } } ``` Any report files will be written to "build/reports/pact". ## Additional Reports The following report types are available in addition to console output (which is enabled by default): `markdown`, `json`. # Publishing verification results to a Pact Broker For pacts that are loaded from a Pact Broker, the results of running the verification can be published back to the broker against the URL for the pact. You will be able to see the result on the Pact Broker home screen. To turn on the verification publishing, set the project property `pact.verifier.publishResults` to `true`. By default, the Gradle project version will be used as the provider version. You can override this by setting the `providerVersion` property. ```groovy pact { serviceProviders { provider1 { providerVersion = { branchName() + '-' + abbreviatedId() } hasPactsFromPactBroker('http://pact-broker:5000/', authentication: ['Basic', pactBrokerUser, pactBrokerPassword]) } } } ``` ## Tagging the provider before verification results are published [4.0.1+] You can have a tag pushed against the provider version before the verification results are published. There are two ways to do this with the Gradle plugin. You can provide a closure in a similar way to the provider version, i.e. ```groovy pact { serviceProviders { provider1 { providerVersion = { branchName() + '-' + abbreviatedId() } providerTag = { branchName() } hasPactsFromPactBroker('http://pact-broker:5000/', authentication: ['Basic', pactBrokerUser, pactBrokerPassword]) } } } ``` or you can set the `pact.provider.tag` JVM system property. For example: ```console $ ./gradlew -d pactverify -Ppact.verifier.publishResults=true -Dpact.provider.tag=Test2 ```
pact-jvm-provider-gradle ======================== Gradle plugin for verifying pacts against a provider. The Gradle plugin creates a task `pactVerify` to your build which will verify all configured pacts against your provider. ## To Use It ### For Gradle versions prior to 2.1 #### 1.1. Add the pact-jvm-provider-gradle jar file to your build script class path: ```groovy buildscript { repositories { mavenCentral() } dependencies { classpath 'au.com.dius:pact-jvm-provider-gradle_2.10:3.2.11' } } ``` #### 1.2. Apply the pact plugin ```groovy apply plugin: 'au.com.dius.pact' ``` ### For Gradle versions 2.1+ ```groovy plugins { id "au.com.dius.pact" version "3.2.11" } ``` ### 2. Define the pacts between your consumers and providers ```groovy pact { serviceProviders { // You can define as many as you need, but each must have a unique name provider1 { // All the provider properties are optional, and have sensible defaults (shown below) protocol = 'http' host = 'localhost' port = 8080 path = '/' // Again, you can define as many consumers for each provider as you need, but each must have a unique name hasPactWith('consumer1') { // currently supports a file path using file() or a URL using url() pactSource = file('path/to/provider1-consumer1-pact.json') } // Or if you have many pact files in a directory hasPactsWith('manyConsumers') { // Will define a consumer for each pact file in the directory. // Consumer name is read from contents of pact file pactFileLocation = file('path/to/pacts') } } } } ``` ### 3. Execute `gradle pactVerify` ## Specifying the provider hostname at runtime If you need to calculate the provider hostname at runtime, you can give a Closure as the provider `host`. ```groovy pact { serviceProviders { provider1 { host = { lookupHostName() } hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` _Since version 3.3.2+/2.4.17+_ you can also give a Closure as the provider `port`. ## Specifying the pact file or URL at runtime [versions 3.2.7/2.4.9+] If you need to calculate the pact file or URL at runtime, you can give a Closure as the provider `pactFile`. ```groovy pact { serviceProviders { provider1 { host = 'localhost' hasPactWith('consumer1') { pactFile = { lookupPactFile() } } } } } ``` ## Starting and shutting down your provider If you need to start-up or shutdown your provider, define Gradle tasks for each action and set `startProviderTask` and `terminateProviderTask` properties of each provider. You could use the jetty tasks here if you provider is built as a WAR file. ```groovy // This will be called before the provider task task('startTheApp') { doLast { // start up your provider here } } // This will be called after the provider task task('killTheApp') { doLast { // kill your provider here } } pact { serviceProviders { provider1 { startProviderTask = startTheApp terminateProviderTask = killTheApp hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` Following typical Gradle behaviour, you can set the provider task properties to the actual tasks, or to the task names as a string (for the case when they haven't been defined yet). ## Preventing the chaining of provider verify task to `pactVerify` [version 3.4.1+] Normally a gradle task named `pactVerify_${provider.name}` is created and added as a task dependency for `pactVerify`. You can disable this dependency on a provider by setting `isDependencyForPactVerify` to `false` (defaults to `true`). ```groovy pact { serviceProviders { provider1 { isDependencyForPactVerify = false hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` To run this task, you would then have to explicitly name it as in ```gradle pactVerify_provider1```, a normal ```gradle pactVerify``` would skip it. This can be useful when you want to define two providers, one with `startProviderTask`/`terminateProviderTask` and as second without, so you can manually start your provider (to debug it from your IDE, for example) but still want a `pactVerify` to run normally from your CI build. ## Enabling insecure SSL [version 2.2.8+] For providers that are running on SSL with self-signed certificates, you need to enable insecure SSL mode by setting `insecure = true` on the provider. ```groovy pact { serviceProviders { provider1 { insecure = true // allow SSL with a self-signed cert hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` ## Specifying a custom trust store [version 2.2.8+] For environments that are running their own certificate chains: ```groovy pact { serviceProviders { provider1 { trustStore = new File('relative/path/to/trustStore.jks') trustStorePassword = 'changeit' hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` `trustStore` is either relative to the current working (build) directory. `trustStorePassword` defaults to `changeit`. NOTE: The hostname will still be verified against the certificate. ## Modifying the HTTP Client Used [version 2.2.4+] The default HTTP client is used for all requests to providers (created with a call to `HttpClients.createDefault()`). This can be changed by specifying a closure assigned to createClient on the provider that returns a CloseableHttpClient. For example: ```groovy pact { serviceProviders { provider1 { createClient = { provider -> // This will enable the client to accept self-signed certificates HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()) .setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, { x509Certificates, s -> true }) .build()) .build() } hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` ## Modifying the requests before they are sent **NOTE on breaking change: Version 2.1.8+ uses Apache HttpClient instead of HttpBuilder so the closure will receive a HttpRequest object instead of a request Map.** Sometimes you may need to add things to the requests that can't be persisted in a pact file. Examples of these would be authentication tokens, which have a small life span. The Pact Gradle plugin provides a request filter that can be set to a closure on the provider that will be called before the request is made. This closure will receive the HttpRequest prior to it being executed. ```groovy pact { serviceProviders { provider1 { requestFilter = { req -> // Add an authorization header to each request req.addHeader('Authorization', 'OAUTH eyJhbGciOiJSUzI1NiIsImN0eSI6ImFw...') } hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') } } } } ``` __*Important Note:*__ You should only use this feature for things that can not be persisted in the pact file. By modifying the request, you are potentially modifying the contract from the consumer tests! ## Turning off URL decoding of the paths in the pact file [version 3.3.3+] By default the paths loaded from the pact file will be decoded before the request is sent to the provider. To turn this behaviour off, set the system property `pact.verifier.disableUrlPathDecoding` to `true`. __*Important Note:*__ If you turn off the url path decoding, you need to ensure that the paths in the pact files are correctly encoded. The verifier will not be able to make a request with an invalid encoded path. ## Project Properties The following project properties can be specified with `-Pproperty=value` on the command line: |Property|Description| |--------|-----------| |pact.showStacktrace|This turns on stacktrace printing for each request. It can help with diagnosing network errors| |pact.showFullDiff|This turns on displaying the full diff of the expected versus actual bodies [version 3.3.6+]| |pact.filter.consumers|Comma seperated list of consumer names to verify| |pact.filter.description|Only verify interactions whose description match the provided regular expression| |pact.filter.providerState|Only verify interactions whose provider state match the provided regular expression. An empty string matches interactions that have no state| |pact.verifier.publishResults|Publishing of verification results will be skipped unless this property is set to 'true'| |pact.matching.wildcard|Enables matching of map values ignoring the keys when this property is set to 'true'| |pact.verifier.disableUrlPathDecoding|Disables decoding of request paths| |pact.pactbroker.httpclient.usePreemptiveAuthentication|Enables preemptive authentication with the pact broker when set to `true`| ## Provider States For a description of what provider states are, see the pact documentations: http://docs.pact.io/documentation/provider_states.html ### Using a state change URL For each provider you can specify a state change URL to use to switch the state of the provider. This URL will receive the providerState description and all the parameters from the pact file before each interaction via a POST. As for normal requests, a request filter (`stateChangeRequestFilter`) can also be set to manipulate the request before it is sent. ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') stateChangeUrl = url('http://localhost:8001/tasks/pactStateChange') stateChangeUsesBody = false // defaults to true stateChangeRequestFilter = { req -> // Add an authorization header to each request req.addHeader('Authorization', 'OAUTH eyJhbGciOiJSUzI1NiIsImN0eSI6ImFw...') } } // or hasPactsWith('consumers') { pactFileLocation = file('path/to/pacts') stateChangeUrl = url('http://localhost:8001/tasks/pactStateChange') stateChangeUsesBody = false // defaults to true } } } } ``` If the `stateChangeUsesBody` is not specified, or is set to true, then the provider state description and parameters will be sent as JSON in the body of the request : ```json { "state" : "a provider state description", "params": { "a": "1", "b": "2" } } ``` If it is set to false, they will be passed as query parameters. #### Teardown calls for state changes [version 3.2.5/2.4.7+] You can enable teardown state change calls by setting the property `stateChangeTeardown = true` on the provider. This will add an `action` parameter to the state change call. The setup call before the test will receive `action=setup`, and then a teardown call will be made afterwards to the state change URL with `action=teardown`. ### Using a Closure [version 2.2.2+] You can set a closure to be called before each verification with a defined provider state. The closure will be called with the state description and parameters from the pact file. ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') // Load a fixture file based on the provider state and then setup some database // data. Does not require a state change request so returns false stateChange = { providerState -> // providerState is an instance of ProviderState def fixture = loadFixtuerForProviderState(providerState) setupDatabase(fixture) } } } } } ``` #### Teardown calls for state changes [version 3.2.5/2.4.7+] You can enable teardown state change calls by setting the property `stateChangeTeardown = true` on the provider. This will add an `action` parameter to the state change closure call. The setup call before the test will receive `setup`, as the second parameter, and then a teardown call will be made afterwards with `teardown` as the second parameter. ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = file('path/to/provider1-consumer1-pact.json') // Load a fixture file based on the provider state and then setup some database // data. Does not require a state change request so returns false stateChange = { providerState, action -> if (action == 'setup') { def fixture = loadFixtuerForProviderState(providerState) setupDatabase(fixture) } else { cleanupDatabase() } false } } } } } ``` #### Returning values that can be injected (3.6.11+) You can have values from the provider state callbacks be injected into most places (paths, query parameters, headers, bodies, etc.). This works by using the V3 spec generators with provider state callbacks that return values. One example of where this would be useful is API calls that require an ID which would be auto-generated by the database on the provider side, so there is no way to know what the ID would be beforehand. There are methods on the consumer DSLs that can provider an expression that contains variables (like '/api/user/${id}' for the path). The provider state callback can then return a map for values, and the `id` attribute from the map will be expanded in the expression. For URL callbacks, the values need to be returned as JSON in the response body. ## Filtering the interactions that are verified You can filter the interactions that are run using three project properties: `pact.filter.consumers`, `pact.filter.description` and `pact.filter.providerState`. Adding `-Ppact.filter.consumers=consumer1,consumer2` to the command line will only run the pact files for those consumers (consumer1 and consumer2). Adding `-Ppact.filter.description=a request for payment.*` will only run those interactions whose descriptions start with 'a request for payment'. `-Ppact.filter.providerState=.*payment` will match any interaction that has a provider state that ends with payment, and `-Ppact.filter.providerState=` will match any interaction that does not have a provider state. ## Verifying pact files from a pact broker [version 3.1.1+/2.3.1+] You can setup your build to validate against the pacts stored in a pact broker. The pact gradle plugin will query the pact broker for all consumers that have a pact with the provider based on its name. For example: ```groovy pact { serviceProviders { provider1 { // You can get the latest pacts from the broker hasPactsFromPactBroker('http://pact-broker:5000/') // And/or you can get the latest pact with a specific tag hasPactsFromPactBrokerWithTag('http://pact-broker:5000/',"tagname") } } } ``` This will verify all pacts found in the pact broker where the provider name is 'provider1'. If you need to set any values on the consumers from the pact broker, you can add a Closure to configure them. ```groovy pact { serviceProviders { provider1 { hasPactsFromPactBroker('http://pact-broker:5000/') { consumer -> stateChange = { providerState -> /* state change code here */ true } } } } } ``` **NOTE: Currently the pacts are fetched from the broker during the configuration phase of the build. This means that if the broker is not available, you will not be able to run any Gradle tasks.** This should be fixed in a forth coming release. In the mean time, to only load the pacts when running the validate task, you can do something like: ```groovy pact { serviceProviders { provider1 { // Only load the pacts from the broker if the start tasks from the command line include pactVerify if ('pactVerify' in gradle.startParameter.taskNames) { hasPactsFromPactBroker('http://pact-broker:5000/') { consumer -> stateChange = { providerState -> /* state change code here */ true } } } } } } ``` ### Using an authenticated Pact Broker You can add the authentication details for the Pact Broker like so: ```groovy pact { serviceProviders { provider1 { hasPactsFromPactBroker('http://pact-broker:5000/', authentication: ['Basic', pactBrokerUser, pactBrokerPassword]) } } } ``` `pactBrokerUser` and `pactBrokerPassword` can be defined in the gradle properties. Or with a bearer token: ```groovy pact { serviceProviders { provider1 { hasPactsFromPactBroker('http://pact-broker:5000/', authentication: ['Bearer', pactBrokerToken]) } } } ``` Preemptive Authentication can be enabled by setting the `pact.pactbroker.httpclient.usePreemptiveAuthentication` Java system property to `true`. ## Verifying pact files from a S3 bucket [version 3.3.2+/2.4.17+] Pact files stored in an S3 bucket can be verified by using an S3 URL to the pact file. I.e., ```groovy pact { serviceProviders { provider1 { hasPactWith('consumer1') { pactFile = 's3://bucketname/path/to/provider1-consumer1-pact.json' } } } } ``` **NOTE:** you can't use the `url` function with S3 URLs, as the URL and URI classes from the Java SDK don't support URLs with the s3 scheme. # Publishing pact files to a pact broker [version 2.2.7+] The pact gradle plugin provides a `pactPublish` task that can publish all pact files in a directory to a pact broker. To use it, you need to add a publish configuration to the pact configuration that defines the directory where the pact files are and the URL to the pact broker. For example: ```groovy pact { publish { pactDirectory = '/pact/dir' // defaults to $buildDir/pacts pactBrokerUrl = 'http://pactbroker:1234' } } ``` You can set any tags that the pacts should be published with by setting the `tags` property. A common use of this is setting the tag to the current source control branch. This supports using pact with feature branches. ```groovy pact { publish { pactDirectory = '/pact/dir' // defaults to $buildDir/pacts pactBrokerUrl = 'http://pactbroker:1234' tags = [project.pactBrokerTag] } } ``` _NOTE:_ The pact broker requires a version for all published pacts. The `pactPublish` task will use the version of the gradle project by default. Make sure you have set one otherwise the broker will reject the pact files. _Version 3.2.2/2.4.3+_ you can override the version in the publish block. ## Publishing to an authenticated pact broker To publish to a broker protected by basic auth, include the username/password in the `pactBrokerUrl`. For example: ```groovy pact { publish { pactBrokerUrl = 'https://username:password@mypactbroker.com' } } ``` ### [version 3.3.9+] You can add the username and password as properties since version 3.3.9+ ```groovy pact { publish { pactBrokerUrl = 'https://mypactbroker.com' pactBrokerUsername = 'username' pactBrokerPassword = 'password' } } ``` or with a bearer token ```groovy pact { publish { pactBrokerUrl = 'https://mypactbroker.com' pactBrokerToken = 'token' } } ``` ## Excluding pacts from being published [version 3.5.19+] You can exclude some of the pact files from being published by providing a list of regular expressions that match against the base names of the pact files. For example: ```groovy pact { publish { pactBrokerUrl = 'https://mypactbroker.com' excludes = [ '.*\\-\\d+$' ] // exclude all pact files that end with a dash followed by a number in the name } } ``` # Verifying a message provider [version 2.2.12+] The Gradle plugin has been updated to allow invoking test methods that can return the message contents from a message producer. To use it, set the way to invoke the verification to `ANNOTATED_METHOD`. This will allow the pact verification task to scan for test methods that return the message contents. Add something like the following to your gradle build file: ```groovy pact { serviceProviders { messageProvider { verificationType = 'ANNOTATED_METHOD' packagesToScan = ['au.com.example.messageprovider.*'] // This is optional, but leaving it out will result in the entire // test classpath being scanned hasPactWith('messageConsumer') { pactFile = url('url/to/messagepact.json') } } } } ``` Now when the `pactVerify` task is run, will look for methods annotated with `@PactVerifyProvider` in the test classpath that have a matching description to what is in the pact file. ```groovy class ConfirmationKafkaMessageBuilderTest { @PactVerifyProvider('an order confirmation message') String verifyMessageForOrder() { Order order = new Order() order.setId(10000004) order.setExchange('ASX') order.setSecurityCode('CBA') order.setPrice(BigDecimal.TEN) order.setUnits(15) order.setGst(new BigDecimal('15.0')) order.setFees(BigDecimal.TEN) def message = new ConfirmationKafkaMessageBuilder() .withOrder(order) .build() JsonOutput.toJson(message) } } ``` It will then validate that the returned contents matches the contents for the message in the pact file. ## Publishing to the Gradle Community Portal To publish the plugin to the community portal: $ ./gradlew :pact-jvm-provider-gradle_2.11:publishPlugins # Verification Reports [versions 3.2.7/2.4.9+] The default behaviour is to display the verification being done to the console, and pass or fail the build via the normal Gradle mechanism. From versions 3.2.7/2.4.9+, additional reports can be generated from the verification. ## Enabling additional reports The verification reports can be controlled by adding a reports section to the pact configuration in the gradle build file. For example: ```groovy pact { reports { defaultReports() // adds the standard console output markdown // report in markdown format json // report in json format } } ``` Any report files will be written to "build/reports/pact". ## Additional Reports The following report types are available in addition to console output (which is enabled by default): `markdown`, `json`. # Publishing verification results to a Pact Broker [version 3.5.4+] For pacts that are loaded from a Pact Broker, the results of running the verification can be published back to the broker against the URL for the pact. You will be able to see the result on the Pact Broker home screen. To turn on the verification publishing, set the project property `pact.verifier.publishResults` to `true` [version 3.5.18+].
NxParser is a Java open source, streaming, non-validating parser for the Nx format, where x = Triples, Quads, or any other number.
NxParser is a Java open source, streaming, non-validating parser for the Nx format, where x = Triples, Quads, or any other number.
NxParser is a Java open source, streaming, non-validating parser for the Nx format, where x = Triples, Quads, or any other number.
This is an open source library that allows generating performance indicators easily for java based application. This library is configurable through an xml file (similar to log4j) in order to define the performance object types, dimensions, counters, the output format and statistics generation periodicity. Those statistics can be saved as a file (xml/json) or injected directly in a database. Then they can be correlated and analyzed through any Business Intelligence solution in order to check the application performance and quality: number of transactions, ratio of successful and failure ...
personnummer is a small open-source project that validates, formatting and determine sex and age from swedish personal identity numbers
A library to help you migrate exiting phone number to new phone number format.
If you are using Postman, you can: - Use the **Download** button above to download the m3ter Open API spec JSON file and then import this file as the **m3ter API Collection** into your Workspace. See [Importing the m3ter Open API](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls#importing-the-m3ter-open-api) in our main user Documentation for details. - Copy this link: [m3ter-Template API Collection](https://www.datocms-assets.com/78893/1672846767-m3ter-template-api-collection-postman_collection.json) and use it to import the **m3ter-Template API Collection** into your Workspace. See [Importing the m3ter Template API Collection](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls#importing-the-m3ter-template-api-collection) in our main user Documentation for details. --- # Introduction The m3ter platform supports two HTTP-based REST APIs returning JSON encoded responses: - The **Ingest API**, which you can use for submitting raw data measurements. _(See the [Submit Measurements](https://www.m3ter.com/docs/api#tag/Measurements/operation/SubmitMeasurements) endpoint in these API Reference Docs.)_ - The **Config API**, which you can use for configuration and management. _(All other endpoints in these API Reference Docs.)_ ## Authentication and Authorization Our APIs use an industry-standard authorization protocol known as the OAuth 2.0 specification. OAuth2 supports several grant types, each designed for a specific use case. m3ter uses the following two grant types: - **Authorization Code**: Used for human login access via the m3ter Console. - **Client Credentials**: Used for machine-to-machine communication and API access. Complete the following flow for API access: 1. **Create a Service User and add Permissions**: Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. 2. **Generate Access Keys**: In the Console, open the _Overview_ page for the Service User by clicking on the name. Generate an **Access Key id** and **Api Secret**. Make sure you copy the **Api Secret** because it is only visible at the time of creation. See [Service Authentication](https://www.m3ter.com/docs/guides/authenticating-with-the-platform/service-authentication) for detailed instructions and an example. 3. **Obtain a Bearer Token using Basic Auth**: We implement the OAuth 2.0 Client Credentials Grant authentication flow for Service User Authentication. Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. _See examples below._ 4. **Bearer Token Usage**: Use the HTTP 'Authorization' header with the bearer token to authorise all subsequent API requests. > Warning: The Bearer Token is valid for 18,000 seconds or 5 hours. When the > token has expired, you must obtain a new bearer token. Below are two examples for obtaining a Bearer Token using Basic Auth: the first in cURL and the second as a Python script. ### cURL Example 1. Open your terminal or command prompt. 2. Use the following `cURL` command to obtain a Bearer Token: ```bash curl -X POST https://api.m3ter.com/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u your_access_key_id:your_api_secret \ -d 'grant_type=client_credentials' ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. 3. Run the command, and if successful, it will return a JSON response containing the Bearer Token. The response will look like this: ```json { "access_token": "your_bearer_token", "token_type": "Bearer", "expires_in": 18000 } ``` You can then use the Bearer Token _(the value of `"access_token"`)_ for subsequent API calls to m3ter. ### Python Example 1. Install the `requests` library if you haven't already: ```bash pip install requests ``` 2. Use the following Python script to obtain a Bearer Token: ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. 3. Run the script, and if successful, it will print the Bearer Token. You can then use this Bearer Token for subsequent API calls to m3ter. ## Submitting Personally Identifiable Information (PII) **IMPORTANT!** Under the [Data Processing Agreement](https://www.m3ter.com/docs/legal/dpa), the only fields permissible for use to submit any of your end-customer PII data in m3ter are the `name`, `address`, and `emailAddress` fields on the **Account** entity - see the details for [Create Account](https://www.m3ter.com/docs/api#operation/PostAccount). See also section 4.2 of the [Terms of Service](https://www.m3ter.com/docs/legal/terms-of-service). ## Error Codes The APIs return standard HTTP response codes to indicate request success or failure. - `200` code indicates success. - `4xx` codes are failures due to problems with the request _(client side errors)_. - `5xx` codes indicate valid API requests and the failure is on the server side. See [HTTP Error Codes](https://www.m3ter.com/docs/guides/m3ter-apis/http-error-codes) for examples and more information. ## Rate and Payload Limits ### Config API Request Rate Limits - **Source IP Address.** Individual host machines can send up to 20,000 requests over a rolling 5-minute period. _(An average of 66 requests per second)._ - **m3ter Organization** Each m3ter Organization can send a maximum of 50 requests per second from any number of source IP addresses. If you exceed either of these rate limits, requests are throttled and an HTTP 429 _(Too Many Requests)_ error response is returned: - **Source IP address rate limit** - 429 is returned until the total number of requests in the rolling 5-minute period drops below 20,000. - **m3ter Organization rate limit** - 429 is returned for the remainder of the second in which throttling has occurred. See [Config API Limits](https://www.m3ter.com/docs/guides/m3ter-apis/config-api-limits) for more information. ### Data Explorer API Request Rate Limits As part of the Config API, requests made to the Data Explorer are subject to tighter request rate limits: - **Generally** 1 request per second. - **Burst** 10 requests per second. If you exceed either of these rate limits, requests are throttled and an HTTP 429 (Too Many Requests) error response is returned. **Note: Burst limit for Data Explorer requests?** We allow short bursts of higher TPS to allow us to accommodate occasional spikes. For example, if the sustained rate is 50 TPS, we might set a bucket capacity (N) of 150. This means that you can do up to 150 TPS for 1s (and empty the bucket), but in the next second you'll only be able to do 50 TPS because that is all that has been refilled. If requests drop below 50 TPS for a period of time, the bucket will refill back up to full capacity allowing another spike. This is usually referred to as "burst capacity". ### Ingest API Request Rate and Payload Limits #### Request Rate Limits - **Source IP Address.** Individual host machines can send up to 5,000 requests over a rolling 5-minute period. _(An average of 16 requests per second)_. - **m3ter Organization.** Each m3ter Organization can send a maximum of 50 requests per second from any number of source IP addresses. If you exceed either of these rate limits, requests are throttled and an HTTP 429 _(Too Many Requests)_ error response is returned: - **Source IP address rate limit** - 429 is returned until the total number of requests in the rolling 5-minute period drops below 5,000. - **m3ter Organization rate limit** - 429 is returned for the remainder of the second in which throttling has occurred. #### Payload Limit For the Ingest API, the maximum request payload size allowed is 512KB. If you exceed this request payload limit, then you'll receive a 403 (Forbidden) error response. See [Ingest API Limits](https://www.m3ter.com/docs/guides/m3ter-apis/ingest-api-limits) for more information. ## Pagination **List Endpoints** API endpoints that have a List resources request support cursor-based pagination - for example, the `List Accounts` request. These List calls support pagination by taking the two parameters `pageSize` and `nextToken`. The response of a List API call is a single page list. If the `nextToken` parameter is not supplied, the first page returned contains the newest objects chronologically. Specify a `nextToken` to retrieve the page of older objects that occur immediately after the last object on the previous page. Use `pageSize` to limit the list results per page, typically this allows up to a maximum of 100 or 200 per page. **Search Endpoints** API endpoints that have a Search resources request support cursor-based pagination - for example, the `Search Accounts` request. These Search calls support pagination by taking the two parameters `pageSize` and `fromDocument`. The response of a Search API call is a single page list. If the `fromDocument` parameter is not supplied, the first page returned contains the newest objects chronologically. Specify a `fromDocument` to retrieve the page of older objects that occur immediately after the last object on the previous page. Use `pageSize` to limit the list results per page, typically this allows up to a maximum of 100 or 200 per page. Default is 10. ## Changelog Check out the latest API features, updates, and functionality by looking in the API Updates subsection of the [m3ter Changelog](https://www.m3ter.com/docs/changelog). --- API Quick Start This API Quick Start section provides an entry point to using the m3ter APIs. The example given takes you through the steps of first authenticating with the m3ter platform then going on to retrieve a list of Accounts for your Organization. Code examples are provided in Python, JavaScript, C++, and command line HTTP via `cURL`. See also [Getting Started with API Calls](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls) for more on using our API with examples. ## Step 1: Create a Service User and add Permissions Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. ## Step 2: Generate Access Keys In the Console, open the **Service Users Details** page for the Service User by clicking on the Service User **NAME**. Generate an **Access Key id** and **Api Secret**. Make sure to copy the **Api Secret** as it is only visible at the time of creation. For further guidance on these two steps, see [Creating and Configuring Service Users](https://www.m3ter.com/docs/guides/organization-and-access-management/managing-users/creating-and-configuring-service-users) in our main user Documentation. ## Step 3: Install Dependencies (if applicable) ### Python Install the `requests` library: ```bash pip install requests ``` ### JavaScript Install the `axios` library: ```bash npm install axios ``` ### C++ Install the `libcurl` and `jsoncpp` libraries. For Windows based systems with `vcpkg` package manager installed: ```bash vcpkg install curl[openssl] jsoncpp ``` For Debian based Linux operating systems: ```bash sudo apt-get install libcurl4-openssl-dev libjsoncpp-dev ``` ## Step 4: Obtain a Bearer Token using Basic Auth Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. ### cURL ```bash curl -X POST https://api.m3ter.com/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u your_access_key_id:your_api_secret \ -d 'grant_type=client_credentials' ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the command, and if successful, it will return a JSON response containing the Bearer Token. ### Python ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ### JavaScript ```javascript const axios = require("axios"); const btoa = require("btoa"); const accessKeyId = "your_access_key_id"; const apiSecret = "your_api_secret"; const basicAuth = btoa(`${accessKeyId}:${apiSecret}`); const url = "https://api.m3ter.com/oauth/token"; const options = { method: "POST", url: url, headers: { Authorization: `Basic ${basicAuth}`, "Content-Type": "application/json", }, data: { grant_type: "client_credentials", }, }; axios(options) .then((response) => console.log("Access Token:", response.data.access_token)) .catch((error) => console.error("Error:", error)); ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ### C++ ```C++ #include <iostream> #include <string> #include <curl/curl.h> #include <json/json.h> #include <sstream> #include <cstdlib> #include <base64.h> size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { ((std::string *)userp)->append((char *)contents, size * nmemb); return size * nmemb; } int main() { // Replace these with your Access Key id and Api Secret std::string access_key_id = "your_access_key_id"; std::string api_secret = "your_api_secret"; // Encode the Access Key id and Api Secret in base64 format std::string credentials = base64_encode(reinterpret_cast<const unsigned char*>(access_key_id.append(":").append(api_secret).c_str()), access_key_id.length()); // Set the m3ter token endpoint URL std::string token_url = "https://api.m3ter.com/oauth/token"; // Initialize libcurl curl_global_init(CURL_GLOBAL_DEFAULT); CURL *curl = curl_easy_init(); if (curl) { // Set the headers for the request struct curl_slist *headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); std::string auth_header = "Authorization: Basic " + credentials; headers = curl_slist_append(headers, auth_header.c_str()); // Set the payload for the request std::string payload = "grant_type=client_credentials"; // Prepare the request curl_easy_setopt(curl, CURLOPT_URL, token_url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); // Send the request and store the response std::string response; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); // Check if the request was successful if (res != CURLE_OK || response_code != 200) { std::cerr << "Error: " << response_code << " - " << curl_easy_strerror(res) << std::endl; } else { // Parse the JSON response Json::Value json; std::istringstream(response) >> json; std::string bearer_token = json["access_token"].asString(); std::cout << "Bearer Token: " << bearer_token << std::endl; } // Cleanup curl_easy_cleanup(curl); curl_slist_free_all(headers); } curl_global_cleanup(); return 0; } ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the program, and if successful, it will print the Bearer Token. ## Step 5: Retrieve Organization ID Copy your Organization ID from the m3ter Console by going to **Settings**, **Organization**, then the **Configuration** tab. The Organization ID is displayed on the _Organization Details_ card and you can **Copy** it directly to your clipboard. ## Step 6: Retrieve Accounts List Make a call to the [List Accounts](https://www.m3ter.com/docs/api#tag/Account/operation/ListAccounts) API endpoint using the Organization ID copied in the previous step. Use the Bearer Token to authorize API calls in the HTTP 'Authorization' header. ### cURL ```bash curl -X GET "https://api.m3ter.com/organizations/{orgId}/accounts?pageSize={pageSize}&nextToken={nextToken}" \ -H "Authorization: Bearer {access_token}" ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### Python ```python import requests org_id = 'your_org_id' page_size = 'your_page_size' next_token = 'your_next_token' # Optional, use if needed access_token = 'your_bearer_token' url = f'https://api.m3ter.com/organizations/{org_id}/accounts?pageSize={page_size}&nextToken={next_token}' headers = { 'Authorization': f'Bearer {access_token}' } response = requests.get(url, headers=headers) if response.status_code == 200: accounts = response.json() print(accounts) else: print(f"Error: {response.status_code}") ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### JavaScript ```javascript const axios = require("axios"); const org_id = "your_org_id"; const page_size = "your_page_size"; const next_token = "your_next_token"; // Optional, use if needed const access_token = "your_bearer_token"; const url = `https://api.m3ter.com/organizations/${org_id}/accounts?pageSize=${page_size}&nextToken=${next_token}`; const headers = { Authorization: `Bearer ${access_token}`, }; axios .get(url, { headers }) .then((response) => { if (response.status === 200) { const accounts = response.data; console.log(accounts); } else { console.log(`Error: ${response.status}`); } }) .catch((error) => { console.error(`Error: ${error.response.status}`); }); ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### C++ ```C++ #include <iostream> #include <string> #include <sstream> #include <curl/curl.h> #include <json/json.h> size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; } int main() { std::string org_id = "your_org_id"; std::string page_size = "your_page_size"; std::string next_token = "your_next_token"; // Optional, use if needed std::string access_token = "your_bearer_token"; std::string url = "https://api.m3ter.com/organizations/" + org_id + "/accounts?pageSize=" + page_size + "&nextToken=" + next_token; std::string auth_header = "Authorization: Bearer " + access_token; std::string read_buffer; CURL* curl = curl_easy_init(); if(curl) { struct curl_slist* headers = NULL; headers = curl_slist_append(headers, auth_header.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); CURLcode res = curl_easy_perform(curl); if(res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); if (response_code == 200) { Json::Value jsonData; Json::CharReaderBuilder jsonReader; std::string errs; std::istringstream iss(read_buffer); if (Json::parseFromStream(jsonReader, iss, &jsonData, &errs)) { std::cout << jsonData << std::endl; } } else { std::cout << "Error: " << response_code << std::endl; } } curl_easy_cleanup(curl); curl_slist_free_all(headers); } return 0; } ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. --- # Integrations Webhook API Example A major benefit of using m3ter is that it seamlessly integrates with your current technology stack. You can create webhook destinations to link you integrations using the API, or via the Console: - This section provides a worked example showing you how to set up a Webhook via the API. - See [Creating and Managing Destinations](https://www.m3ter.com/docs/guides/integrations/setting-up-native-integrations/creating-and-managing-destinations) in the m3ter documentation for instructions on using the Console. ## Step 1: Create a Service User and Generate Access Keys 1. **Create a Service User**: Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. 2. **Generate Access Keys**: In the Console, open the **Service User Details** page for the Service User by clicking on the **NAME** hotlink text. Select **Generate Access Key** to generate an **Access Key id** and **Api Secret**. Make sure you copy the **Api Secret** because it is only visible at the time of creation. For further guidance on completing **Step 1**, see [Creating and Configuring Service Users](https://www.m3ter.com/docs/guides/organization-and-access-management/managing-users/creating-and-configuring-service-users) in our main user Documentation. ## Step 2: Obtain a Bearer Token using Basic Auth We implement the OAuth 2.0 Client Credentials Grant authentication flow for Service User Authentication. Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. Here's an example in Python code: ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ## Step 3: Create a Webhook (Destination) After obtaining the Bearer Token, you can use it to authorize your API calls. Here's a Python example of creating a webhook: ```python import requests import json # API endpoint url = "https://api.m3ter.com/organizations/{orgId}/integrationdestinations/webhooks" # replace {orgId} with your organization's UUID # Headers headers = { "Content-Type": "application/json", "Authorization": f"Bearer {bearer_token}" # replace with your actual Bearer Token } # Request body payload = { "url": "https://your-webhook-listener.com", # replace with your actual webhook listener URL "credentials": { "type": "M3TER_SIGNED_REQUEST", "apiKey": access_key_id, # replace with your actual API key "secret": api_secret # replace with your actual secret } } # Make the POST request response = requests.post(url, headers=headers, data=json.dumps(payload)) # Print the response print(response.json()) ``` ## Step 4: Validate Incoming Requests Once your webhook is set up, you'll want to validate incoming requests to ensure they're coming from m3ter. All requests we make to your webhook are signed by us. When you receive a request on your configured endpoint, validate the `X-m3ter-signature` header by preparing a payload string that you sign with your API secret. You must concatenate the following data using a pipe '|' separator to compute the payload: - url - query string - Currently, there's no support for passing in query parameters. For now, you can hard code to this string: '{}' - API Key - provided in the `X-m3ter-apikey` header. - timestamp - provided in the `X-m3ter-timestamp` header. - body - the request body. You can now set up and validate webhooks using the m3ter Console and API. Always refer to the latest [m3ter documentation](https://www.m3ter.com/docs) for accurate and up to date information. --- # Authentication <!-- ReDoc-Inject: <security-definitions> -->
If you are using Postman, you can: - Use the **Download** button above to download the m3ter Open API spec JSON file and then import this file as the **m3ter API Collection** into your Workspace. See [Importing the m3ter Open API](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls#importing-the-m3ter-open-api) in our main user Documentation for details. - Copy this link: [m3ter-Template API Collection](https://www.datocms-assets.com/78893/1672846767-m3ter-template-api-collection-postman_collection.json) and use it to import the **m3ter-Template API Collection** into your Workspace. See [Importing the m3ter Template API Collection](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls#importing-the-m3ter-template-api-collection) in our main user Documentation for details. --- # Introduction The m3ter platform supports two HTTP-based REST APIs returning JSON encoded responses: - The **Ingest API**, which you can use for submitting raw data measurements. _(See the [Submit Measurements](https://www.m3ter.com/docs/api#tag/Measurements/operation/SubmitMeasurements) endpoint in these API Reference Docs.)_ - The **Config API**, which you can use for configuration and management. _(All other endpoints in these API Reference Docs.)_ ## Authentication and Authorization Our APIs use an industry-standard authorization protocol known as the OAuth 2.0 specification. OAuth2 supports several grant types, each designed for a specific use case. m3ter uses the following two grant types: - **Authorization Code**: Used for human login access via the m3ter Console. - **Client Credentials**: Used for machine-to-machine communication and API access. Complete the following flow for API access: 1. **Create a Service User and add Permissions**: Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. 2. **Generate Access Keys**: In the Console, open the _Overview_ page for the Service User by clicking on the name. Generate an **Access Key id** and **Api Secret**. Make sure you copy the **Api Secret** because it is only visible at the time of creation. See [Service Authentication](https://www.m3ter.com/docs/guides/authenticating-with-the-platform/service-authentication) for detailed instructions and an example. 3. **Obtain a Bearer Token using Basic Auth**: We implement the OAuth 2.0 Client Credentials Grant authentication flow for Service User Authentication. Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. _See examples below._ 4. **Bearer Token Usage**: Use the HTTP 'Authorization' header with the bearer token to authorise all subsequent API requests. > Warning: The Bearer Token is valid for 18,000 seconds or 5 hours. When the > token has expired, you must obtain a new bearer token. Below are two examples for obtaining a Bearer Token using Basic Auth: the first in cURL and the second as a Python script. ### cURL Example 1. Open your terminal or command prompt. 2. Use the following `cURL` command to obtain a Bearer Token: ```bash curl -X POST https://api.m3ter.com/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u your_access_key_id:your_api_secret \ -d 'grant_type=client_credentials' ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. 3. Run the command, and if successful, it will return a JSON response containing the Bearer Token. The response will look like this: ```json { "access_token": "your_bearer_token", "token_type": "Bearer", "expires_in": 18000 } ``` You can then use the Bearer Token _(the value of `"access_token"`)_ for subsequent API calls to m3ter. ### Python Example 1. Install the `requests` library if you haven't already: ```bash pip install requests ``` 2. Use the following Python script to obtain a Bearer Token: ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. 3. Run the script, and if successful, it will print the Bearer Token. You can then use this Bearer Token for subsequent API calls to m3ter. ## Submitting Personally Identifiable Information (PII) **IMPORTANT!** Under the [Data Processing Agreement](https://www.m3ter.com/docs/legal/dpa), the only fields permissible for use to submit any of your end-customer PII data in m3ter are the `name`, `address`, and `emailAddress` fields on the **Account** entity - see the details for [Create Account](https://www.m3ter.com/docs/api#operation/PostAccount). See also section 4.2 of the [Terms of Service](https://www.m3ter.com/docs/legal/terms-of-service). ## Error Codes The APIs return standard HTTP response codes to indicate request success or failure. - `200` code indicates success. - `4xx` codes are failures due to problems with the request _(client side errors)_. - `5xx` codes indicate valid API requests and the failure is on the server side. See [HTTP Error Codes](https://www.m3ter.com/docs/guides/m3ter-apis/http-error-codes) for examples and more information. ## Rate and Payload Limits ### Config API Request Rate Limits - **Source IP Address.** Individual host machines can send up to 20,000 requests over a rolling 5-minute period. _(An average of 66 requests per second)._ - **m3ter Organization** Each m3ter Organization can send a maximum of 50 requests per second from any number of source IP addresses. If you exceed either of these rate limits, requests are throttled and an HTTP 429 _(Too Many Requests)_ error response is returned: - **Source IP address rate limit** - 429 is returned until the total number of requests in the rolling 5-minute period drops below 20,000. - **m3ter Organization rate limit** - 429 is returned for the remainder of the second in which throttling has occurred. See [Config API Limits](https://www.m3ter.com/docs/guides/m3ter-apis/config-api-limits) for more information. ### Data Explorer API Request Rate Limits As part of the Config API, requests made to the Data Explorer are subject to tighter request rate limits: - **Generally** 1 request per second. - **Burst** 10 requests per second. If you exceed either of these rate limits, requests are throttled and an HTTP 429 (Too Many Requests) error response is returned. **Note: Burst limit for Data Explorer requests?** We allow short bursts of higher TPS to allow us to accommodate occasional spikes. For example, if the sustained rate is 50 TPS, we might set a bucket capacity (N) of 150. This means that you can do up to 150 TPS for 1s (and empty the bucket), but in the next second you'll only be able to do 50 TPS because that is all that has been refilled. If requests drop below 50 TPS for a period of time, the bucket will refill back up to full capacity allowing another spike. This is usually referred to as "burst capacity". ### Ingest API Request Rate and Payload Limits #### Request Rate Limits - **Source IP Address.** Individual host machines can send up to 5,000 requests over a rolling 5-minute period. _(An average of 16 requests per second)_. - **m3ter Organization.** Each m3ter Organization can send a maximum of 50 requests per second from any number of source IP addresses. If you exceed either of these rate limits, requests are throttled and an HTTP 429 _(Too Many Requests)_ error response is returned: - **Source IP address rate limit** - 429 is returned until the total number of requests in the rolling 5-minute period drops below 5,000. - **m3ter Organization rate limit** - 429 is returned for the remainder of the second in which throttling has occurred. #### Payload Limit For the Ingest API, the maximum request payload size allowed is 512KB. If you exceed this request payload limit, then you'll receive a 403 (Forbidden) error response. See [Ingest API Limits](https://www.m3ter.com/docs/guides/m3ter-apis/ingest-api-limits) for more information. ## Pagination **List Endpoints** API endpoints that have a List resources request support cursor-based pagination - for example, the `List Accounts` request. These List calls support pagination by taking the two parameters `pageSize` and `nextToken`. The response of a List API call is a single page list. If the `nextToken` parameter is not supplied, the first page returned contains the newest objects chronologically. Specify a `nextToken` to retrieve the page of older objects that occur immediately after the last object on the previous page. Use `pageSize` to limit the list results per page, typically this allows up to a maximum of 100 or 200 per page. **Search Endpoints** API endpoints that have a Search resources request support cursor-based pagination - for example, the `Search Accounts` request. These Search calls support pagination by taking the two parameters `pageSize` and `fromDocument`. The response of a Search API call is a single page list. If the `fromDocument` parameter is not supplied, the first page returned contains the newest objects chronologically. Specify a `fromDocument` to retrieve the page of older objects that occur immediately after the last object on the previous page. Use `pageSize` to limit the list results per page, typically this allows up to a maximum of 100 or 200 per page. Default is 10. ## Changelog Check out the latest API features, updates, and functionality by looking in the API Updates subsection of the [m3ter Changelog](https://www.m3ter.com/docs/changelog). --- API Quick Start This API Quick Start section provides an entry point to using the m3ter APIs. The example given takes you through the steps of first authenticating with the m3ter platform then going on to retrieve a list of Accounts for your Organization. Code examples are provided in Python, JavaScript, C++, and command line HTTP via `cURL`. See also [Getting Started with API Calls](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls) for more on using our API with examples. ## Step 1: Create a Service User and add Permissions Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. ## Step 2: Generate Access Keys In the Console, open the **Service Users Details** page for the Service User by clicking on the Service User **NAME**. Generate an **Access Key id** and **Api Secret**. Make sure to copy the **Api Secret** as it is only visible at the time of creation. For further guidance on these two steps, see [Creating and Configuring Service Users](https://www.m3ter.com/docs/guides/organization-and-access-management/managing-users/creating-and-configuring-service-users) in our main user Documentation. ## Step 3: Install Dependencies (if applicable) ### Python Install the `requests` library: ```bash pip install requests ``` ### JavaScript Install the `axios` library: ```bash npm install axios ``` ### C++ Install the `libcurl` and `jsoncpp` libraries. For Windows based systems with `vcpkg` package manager installed: ```bash vcpkg install curl[openssl] jsoncpp ``` For Debian based Linux operating systems: ```bash sudo apt-get install libcurl4-openssl-dev libjsoncpp-dev ``` ## Step 4: Obtain a Bearer Token using Basic Auth Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. ### cURL ```bash curl -X POST https://api.m3ter.com/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u your_access_key_id:your_api_secret \ -d 'grant_type=client_credentials' ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the command, and if successful, it will return a JSON response containing the Bearer Token. ### Python ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ### JavaScript ```javascript const axios = require("axios"); const btoa = require("btoa"); const accessKeyId = "your_access_key_id"; const apiSecret = "your_api_secret"; const basicAuth = btoa(`${accessKeyId}:${apiSecret}`); const url = "https://api.m3ter.com/oauth/token"; const options = { method: "POST", url: url, headers: { Authorization: `Basic ${basicAuth}`, "Content-Type": "application/json", }, data: { grant_type: "client_credentials", }, }; axios(options) .then((response) => console.log("Access Token:", response.data.access_token)) .catch((error) => console.error("Error:", error)); ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ### C++ ```C++ #include <iostream> #include <string> #include <curl/curl.h> #include <json/json.h> #include <sstream> #include <cstdlib> #include <base64.h> size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { ((std::string *)userp)->append((char *)contents, size * nmemb); return size * nmemb; } int main() { // Replace these with your Access Key id and Api Secret std::string access_key_id = "your_access_key_id"; std::string api_secret = "your_api_secret"; // Encode the Access Key id and Api Secret in base64 format std::string credentials = base64_encode(reinterpret_cast<const unsigned char*>(access_key_id.append(":").append(api_secret).c_str()), access_key_id.length()); // Set the m3ter token endpoint URL std::string token_url = "https://api.m3ter.com/oauth/token"; // Initialize libcurl curl_global_init(CURL_GLOBAL_DEFAULT); CURL *curl = curl_easy_init(); if (curl) { // Set the headers for the request struct curl_slist *headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); std::string auth_header = "Authorization: Basic " + credentials; headers = curl_slist_append(headers, auth_header.c_str()); // Set the payload for the request std::string payload = "grant_type=client_credentials"; // Prepare the request curl_easy_setopt(curl, CURLOPT_URL, token_url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); // Send the request and store the response std::string response; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); // Check if the request was successful if (res != CURLE_OK || response_code != 200) { std::cerr << "Error: " << response_code << " - " << curl_easy_strerror(res) << std::endl; } else { // Parse the JSON response Json::Value json; std::istringstream(response) >> json; std::string bearer_token = json["access_token"].asString(); std::cout << "Bearer Token: " << bearer_token << std::endl; } // Cleanup curl_easy_cleanup(curl); curl_slist_free_all(headers); } curl_global_cleanup(); return 0; } ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the program, and if successful, it will print the Bearer Token. ## Step 5: Retrieve Organization ID Copy your Organization ID from the m3ter Console by going to **Settings**, **Organization**, then the **Configuration** tab. The Organization ID is displayed on the _Organization Details_ card and you can **Copy** it directly to your clipboard. ## Step 6: Retrieve Accounts List Make a call to the [List Accounts](https://www.m3ter.com/docs/api#tag/Account/operation/ListAccounts) API endpoint using the Organization ID copied in the previous step. Use the Bearer Token to authorize API calls in the HTTP 'Authorization' header. ### cURL ```bash curl -X GET "https://api.m3ter.com/organizations/{orgId}/accounts?pageSize={pageSize}&nextToken={nextToken}" \ -H "Authorization: Bearer {access_token}" ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### Python ```python import requests org_id = 'your_org_id' page_size = 'your_page_size' next_token = 'your_next_token' # Optional, use if needed access_token = 'your_bearer_token' url = f'https://api.m3ter.com/organizations/{org_id}/accounts?pageSize={page_size}&nextToken={next_token}' headers = { 'Authorization': f'Bearer {access_token}' } response = requests.get(url, headers=headers) if response.status_code == 200: accounts = response.json() print(accounts) else: print(f"Error: {response.status_code}") ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### JavaScript ```javascript const axios = require("axios"); const org_id = "your_org_id"; const page_size = "your_page_size"; const next_token = "your_next_token"; // Optional, use if needed const access_token = "your_bearer_token"; const url = `https://api.m3ter.com/organizations/${org_id}/accounts?pageSize=${page_size}&nextToken=${next_token}`; const headers = { Authorization: `Bearer ${access_token}`, }; axios .get(url, { headers }) .then((response) => { if (response.status === 200) { const accounts = response.data; console.log(accounts); } else { console.log(`Error: ${response.status}`); } }) .catch((error) => { console.error(`Error: ${error.response.status}`); }); ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### C++ ```C++ #include <iostream> #include <string> #include <sstream> #include <curl/curl.h> #include <json/json.h> size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; } int main() { std::string org_id = "your_org_id"; std::string page_size = "your_page_size"; std::string next_token = "your_next_token"; // Optional, use if needed std::string access_token = "your_bearer_token"; std::string url = "https://api.m3ter.com/organizations/" + org_id + "/accounts?pageSize=" + page_size + "&nextToken=" + next_token; std::string auth_header = "Authorization: Bearer " + access_token; std::string read_buffer; CURL* curl = curl_easy_init(); if(curl) { struct curl_slist* headers = NULL; headers = curl_slist_append(headers, auth_header.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); CURLcode res = curl_easy_perform(curl); if(res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); if (response_code == 200) { Json::Value jsonData; Json::CharReaderBuilder jsonReader; std::string errs; std::istringstream iss(read_buffer); if (Json::parseFromStream(jsonReader, iss, &jsonData, &errs)) { std::cout << jsonData << std::endl; } } else { std::cout << "Error: " << response_code << std::endl; } } curl_easy_cleanup(curl); curl_slist_free_all(headers); } return 0; } ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. --- # Integrations Webhook API Example A major benefit of using m3ter is that it seamlessly integrates with your current technology stack. You can create webhook destinations to link you integrations using the API, or via the Console: - This section provides a worked example showing you how to set up a Webhook via the API. - See [Creating and Managing Destinations](https://www.m3ter.com/docs/guides/integrations/setting-up-native-integrations/creating-and-managing-destinations) in the m3ter documentation for instructions on using the Console. ## Step 1: Create a Service User and Generate Access Keys 1. **Create a Service User**: Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. 2. **Generate Access Keys**: In the Console, open the **Service User Details** page for the Service User by clicking on the **NAME** hotlink text. Select **Generate Access Key** to generate an **Access Key id** and **Api Secret**. Make sure you copy the **Api Secret** because it is only visible at the time of creation. For further guidance on completing **Step 1**, see [Creating and Configuring Service Users](https://www.m3ter.com/docs/guides/organization-and-access-management/managing-users/creating-and-configuring-service-users) in our main user Documentation. ## Step 2: Obtain a Bearer Token using Basic Auth We implement the OAuth 2.0 Client Credentials Grant authentication flow for Service User Authentication. Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. Here's an example in Python code: ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ## Step 3: Create a Webhook (Destination) After obtaining the Bearer Token, you can use it to authorize your API calls. Here's a Python example of creating a webhook: ```python import requests import json # API endpoint url = "https://api.m3ter.com/organizations/{orgId}/integrationdestinations/webhooks" # replace {orgId} with your organization's UUID # Headers headers = { "Content-Type": "application/json", "Authorization": f"Bearer {bearer_token}" # replace with your actual Bearer Token } # Request body payload = { "url": "https://your-webhook-listener.com", # replace with your actual webhook listener URL "credentials": { "type": "M3TER_SIGNED_REQUEST", "apiKey": access_key_id, # replace with your actual API key "secret": api_secret # replace with your actual secret } } # Make the POST request response = requests.post(url, headers=headers, data=json.dumps(payload)) # Print the response print(response.json()) ``` ## Step 4: Validate Incoming Requests Once your webhook is set up, you'll want to validate incoming requests to ensure they're coming from m3ter. All requests we make to your webhook are signed by us. When you receive a request on your configured endpoint, validate the `X-m3ter-signature` header by preparing a payload string that you sign with your API secret. You must concatenate the following data using a pipe '|' separator to compute the payload: - url - query string - Currently, there's no support for passing in query parameters. For now, you can hard code to this string: '{}' - API Key - provided in the `X-m3ter-apikey` header. - timestamp - provided in the `X-m3ter-timestamp` header. - body - the request body. You can now set up and validate webhooks using the m3ter Console and API. Always refer to the latest [m3ter documentation](https://www.m3ter.com/docs) for accurate and up to date information. --- # Authentication <!-- ReDoc-Inject: <security-definitions> -->
This tool allows setting the version number of a specified dependency in a given Maven pom.xml file. All original comments and formatting will be kept. Usage example: mvn com.soerensen.maven.plugins:version-edit-plugin:1.0.1:setDependencyVersion -DpomFile="pom.xml" -Dgavtc="commons-io:commons-io:4.8.0" mvn com.soerensen.maven.plugins:version-edit-plugin:0.0.1:setPropertyDependencyVersion -DpropertyFile="test.property" -Dkey="junit_junit" -Dvalue="24.0.0" gavtc -> groupId:artifactId:version:type*:classifier* * optional Extra property: - noBackupFile (default:false), used to ignore the creation of a backup file.
This tool allows setting the version number of a specified dependency in a given Maven pom.xml file. All original comments and formatting will be kept. Usage example: mvn com.soerensen.pomedit:pomedit:1.0.1:setDependencyVersion -DpomFile="pom.xml" -Dgavtc="commons-io:commons-io:4.8.0" gavtc -> groupId:artifactId:version:type*:classifier* * optional Extra property: - noBackupFile (default:false), used to ignore the creation of a backup file.
JSONXML project is library used to parse/format tree-like object structures in most popular text formats: XML and JSON. For parsing it accepts "java.io.Reader" and return java object. For formatting it accepts java object and "java.io.Writer". Object is generally structure that contains Map and/or List elements. Map is ordered set of named items. List is set of unnamed items. Reflection may be used to convert objects into set of maps/lists and vice versa. JSON parser is implemented explicitly. XML parser is based on SAX parser and applies only certain rules for result. Library is designed to allow various entry points for variable decisions depending on end use needs. 1. Formats - formats are used to enable locale-specific parsing/formatting of numbers and dates. 2. ReflectiveBuilder - enables reflection. Default implementation uses getters/setters only. 3. ObjectsRegistry - used to keep track of parsed or formatted objects and allow resolvable references in formatted (text) form.
A kotlin library to parse and format floating-point numbers according to ISO 6093.
Google's common Java library for parsing, formatting, storing and validating international phone numbers. Optimized for running on smartphones.
The MAJ API was written by Richard Cartwright, with the help and support of Guillaume Belrose and Fang Ren. To contact the author, please raise an issue. The software is provided AS IS with no warranty whatsoever. The MAJ API (pronounced madge) is a pure Java API for creating, reading, manipulating and writing MXF (SMPTE ST 377), AAF structured storage and Reg-XML (SMPTE ST 2001) files. MXF files are commonly used as a container for professional media file formats and AAF is supported by a number of professional video editing packages. MXF and Reg-XML are used as part of the Interoperable Mastering Format suite of specifications.
Credit Card Number is a library that can provide details of a bank issued credit card number. All classes are immutable and thread-safe. The standard `toString()` function formats data in a readable form.
Adds version properties to the build in a format that excludes the build number
This validator will confirm if an ABA Routing Transit Number Validator is formatted correctly. This does not guarantee if it's valid, only that it has passed a small series of edits.
Phone Number Format Validate For MTN Numbers
Converts a number to/from a human readable string: `1337` ↔ `1.34kB`
A library that implements a number of different ways for running a program in a different process and communicating with that process by sending data back and forth over standard input/output in various formats (JSON, ObjectStream ...).
A library that implements a number of different ways for running a program in a different process and communicating with that process by sending data back and forth over standard input/output in various formats (JSON, ObjectStream ... ).