diff --git a/plugins/apiv3_example.rb b/plugins/apiv3_example.rb index d6c71474d0..f7456d8038 100644 --- a/plugins/apiv3_example.rb +++ b/plugins/apiv3_example.rb @@ -1,15 +1,43 @@ module Jekyll class ApiV3Example < Liquid::Block def initialize(tag_name, markup, tokens) + attributes = markup.split + @identifier = attributes[0] @request_type = attributes[1] @url = attributes[2] - @data = markup.gsub(attributes[0],"").gsub(attributes[1],"").gsub(attributes[2],"").strip + #clean the original attributes from the original content + markup = markup.gsub(@identifier,"").gsub(@request_type,"").gsub(@url,"") + + #get the data - which is "request data" and "request headers" if they exist + @data, @request_header = markup.scan(/\{(.*?)\}/) + + unless @data.nil? + #hack it back together now + @data = "{"+@data[0].to_s+"}" + markup = markup.gsub("{"+@data[0].to_s+"}", "") + if @data = "{}" + @data = "" + end + end + + unless @request_header.nil? + @request_header = @request_header[0] + markup = markup.gsub("{"+@request_header.to_s+"}", "") + + if @request_header.include? "request_header" + @request_header = @request_header.gsub("request_header","") + else + #this isn't a request header and it's out of order + @data = "{"+@request_header.to_s+"}" + @request_header = "" + end + end - if attributes[4] - @show_livedoc = attributes[4] + if markup.strip.length > 0 + @show_livedoc = markup end super @@ -18,7 +46,6 @@ def initialize(tag_name, markup, tokens) def render(context) output = super - output = < #{output} @@ -32,7 +59,8 @@ def render_all(list, context) context['identifier'] = @identifier context['request_type'] = @request_type context['url'] = @url - context['data'] = @data + context['data'] = @data.to_s + context['request_header'] = @request_header.to_s super end end @@ -53,13 +81,16 @@ def unquote_data(data) def render(context) output = super - + # let's parse the vars before we generate the output to avoid complications identifier = Liquid::Template.parse("{{ identifier }}").render context request_type = Liquid::Template.parse("{{ request_type }}").render context url = Liquid::Template.parse("{{ url }}").render context + request_header = Liquid::Template.parse("{{ request_header }}").render context data = Liquid::Template.parse("{{ data }}").render context + data_block = ''; + if data.include? "=" data = Hash[URI.decode_www_form(data)] data = unquote_data(data) @@ -68,9 +99,15 @@ def render(context) data = data.length > 0 ? JSON.pretty_generate(JSON.parse(data)) : "" end + if request_header.length > 0 + request_header = request_header.gsub('-_-',"") + data_block = "Request Headers
{% codeblock %}#{request_header}{% endcodeblock %}" + end + if data.length > 0 - data_block = "Request Body
{% codeblock lang:json %}#{data}{% endcodeblock %}" - end + data_block += "Request Body
{% codeblock lang:json %}#{data}{% endcodeblock %}" + end + request_url = url output = < HTML - + return Liquid::Template.parse(output).render context end end diff --git a/plugins/converter_apiblueprint.rb b/plugins/converter_apiblueprint.rb index 3da8633169..52aede6965 100644 --- a/plugins/converter_apiblueprint.rb +++ b/plugins/converter_apiblueprint.rb @@ -42,6 +42,7 @@ class BluePrintHTML < Redcarpet::Render::HTML @@path = "" @@request_body = "" @@response_body = "" + @@request_headers = "" #### # set the root url of the API calls @@ -137,8 +138,14 @@ def header(text, level, somethingelse = nil) # get the request method if 3 == level debug "\t--RESET VARS--" - # get the response method from the header - @@method = text.split("[")[1].gsub("]","") + if text.include? "]" + # get the response method from the header + @@method = text.split("[")[1].gsub("]","") + else + debug "HEADER parse error - no HTTP method on " + text + exit + end + debug "\tMETHOD SET: " + @@method end @@ -198,10 +205,14 @@ def list_item(text, list_type) end #handle the request and response headers - if text.include? "Header" - # @todo build this out! - end + # When we have headers that tag along, we need to indicate this + if text.include? "Headers" + debug "HEADERS!! " + text + + return docs_header(text) + + end # next up is an element with Body - we don't know whether it's a request or a response if text.include? "Body" @@ -293,14 +304,35 @@ def do_find_replace(text, index) return text.to_s end + def docs_header(text) + + text = text.gsub("Headers","") + + debug "In docs_header body_block = " + @@body_block + + if "request" == @@body_block + debug "Found a header! " + text + + @@request_headers = text.gsub("\n","").gsub(""",'"') + + end + + if "response" == @@body_block + #@todo build this out + end + + end + # handle the body of the request or response def docs_body(text) debug "\t --docs_body--" text = text.gsub("Body","") + debug "Body Block: " + @@body_block + if "request" == @@body_block - @@request_body = text.gsub("\n","") + @@request_body = text.gsub("\n","").gsub(""",'"') debug "\t REQUEST BODY SET " + text.strip @@ -434,6 +466,27 @@ def docs_liquid_output(text) url += " " + @@request_body.strip end + debug "REQUEST HEADERS: " + @@request_headers + + if @@request_headers.length > 1 + + debug "WE HAVE REQUEST HEADERS" + + #make sure that we have the space there to be parsed + + if @@request_body.length <= 1 + debug "REquest Body is 0" + url += " {}" + end + + debug "adding request headers to URL" + + #add the request headers to the tag + url += " {request_header" + @@request_headers.strip + "}" + + debug "####URL####" + url + end + # output all the tags at once for this endpoint # if/when we want to put params on the URL in the Request area, we can do this append - @@params.gsub("\n","")+ - to the Url # we will need to probably grab params for the URL from the params list, rather than the request body @@ -493,7 +546,7 @@ def docs_liquid_params_block(text) def reset_vars() debug "## RESET EVERYTHING ##" # reset everything, just in case we're about to do another endpoint - path doesn't get reset until another h2, bc we reuse the path - @@body_block, @@group_identifier, @@http_response, @@params, @@request_body, @@response_body = "","","","","","","" + @@body_block, @@group_identifier, @@http_response, @@params, @@request_body, @@response_body, @@request_headers = "","","","","","","","" end end \ No newline at end of file diff --git a/source/API_Reference/Customer_Subuser_API/subusers.md b/source/API_Reference/Customer_Subuser_API/subusers.md index 1fd82ab0ad..d532052bb9 100644 --- a/source/API_Reference/Customer_Subuser_API/subusers.md +++ b/source/API_Reference/Customer_Subuser_API/subusers.md @@ -22,7 +22,7 @@ Create a Subuser {% parameters create %} {% parameter username Yes 'No more than 64 characters' 'New subuser username' %} - {% parameter password Yes 'At least 6 characters' 'New subuser password' %} + {% parameter password Yes 'At least 8 characters' 'New subuser password' %} {% parameter confirm_password Yes 'Match password argument' 'Confirm new password' %} {% parameter email Yes 'Valid email address, no more than 64 characters' 'New subuser email. This is an administrative contact address for SendGrid' %} {% parameter first_name Yes 'No more than 50 characters' 'New subuser profile first name' %} diff --git a/source/API_Reference/Web_API_v3/API_Keys/index.apiblueprint b/source/API_Reference/Web_API_v3/API_Keys/index.apiblueprint new file mode 100644 index 0000000000..d472f3b52d --- /dev/null +++ b/source/API_Reference/Web_API_v3/API_Keys/index.apiblueprint @@ -0,0 +1,198 @@ +--- +layout: page +weight: 755 +title: API Keys +navigation: + show: true +--- + +FORMAT: 1A + +# API Keys +The API Keys feature allows customers to be able to generate an +API Key credential which can be used for authentication with the +SendGrid v3 Web API or Mail API. + +# Group API Keys management + +## API Keys collection [/api_keys] +### List all API Keys belonging to the authenticated user [GET] + ++ Response 200 (application/json) + + + Body + + { + "result": [ + { + "name": "A New Hope", + "api_key_id": "xxxxxxxx" + } + ] + } + +### Generate a new API Key for the authenticated user [POST] +This will create a new random API Key for the user. +A JSON request body containing a "name" property is required. +If number of maximum keys is reached, HTTP 403 will be returned. + ++ Request + + + Body + + { + "name":"My API Key" + } + ++ Response 201 (application/json) + + { + "api_key": "SG.xxxxxxxx.yyyyyyyy", + "api_key_id": "xxxxxxxx" + "name": "My API Key" + } + ++ Response 400 (application/json) + + + Body + + { + "errors": [ + { + "field": "name", + "message": "missing required argument" + } + ] + } + ++ Response 403 (application/json) + + + Body + + { + "errors": [ + { + "field": null, + "message": "Cannot create more than 100 API Keys" + } + ] + } + +## API Key [/api_keys/{api_key}] +### Revoke an existing API Key [DELETE] +Authentications using this API Key will fail +after this request is made, with some small propogation delay. + +If the API Key ID does not exist an HTTP 404 will be returned. + ++ Response 204 (application/json) + ++ Response 404 (application/json) + + + Body + + { + "errors": [ + { + "field": null, + "message": "unable to find API Key for deletion" + } + ] + } + +### Update the name of an existing API Key [PATCH] +A JSON request body with a "name" property is required. + ++ Request + + + Body + + { + "name": "A New Hope" + } + ++ Response 200 (application/json) + + + Body + + { + "api_key_id": "qfTQ6KG0QBiwWdJ0-pCLCA", + "name": "A New Hope" + } + ++ Response 400 (application/json) + + + Body + + { + "errors": [ + { + "field": null, + "message": "expected JSON request body with 'name' property" + } + ] + } + ++ Response 404 (application/json) + + + Body + + { + "errors": [ + { + "field": null, + "message": "unable to find API Key to update" + } + ] + } + +# Group API Key usage +The API Keys feature adds a new "Bearer" scheme for HTTP authentication +for both v3 WebAPI and the mail.send API. + +## Authentication against a /v3 API resource [/resource] +Returns HTTP 401 if authentication fails. + +### Authentication [GET] ++ Request + + + Headers + + Authorization: Bearer SG.xxxxxxxx.yyyyyyyy + ++ Response 200 (application/json) + ++ Response 401 (application/json) + + { + "errors": [ + { + "field": null, + "message": "authorization required" + } + ] + } + + +## Authentication against the mail.send API [/api/mail.send.json] +Returns HTTP 400 if authentication fails. + +### HTTP Authentication [GET] ++ Request + + + Headers + + Authorization: Bearer SG.xxxxxxxx.yyyyyyyy + ++ Response 200 (application/json) + ++ Response 400 (application/json) + + + Body + + { + "message": "error", + "errors": [ + "invalid API Key" + ] + } \ No newline at end of file diff --git a/source/User_Guide/Account/api_keys.md b/source/User_Guide/Account/api_keys.md index 8aa3730d18..cae1f18971 100644 --- a/source/User_Guide/Account/api_keys.md +++ b/source/User_Guide/Account/api_keys.md @@ -26,7 +26,7 @@ Permissions that allow you to define what a given API Key is allowed to do are i Managing API Keys {%endanchor%} -You can [manage your API Keys](https://sendgrid.com/beta/settings/api_keys) from our beta interface. +You can [manage your API Keys](https://sendgrid.com/beta/settings/api_keys) from our beta interface. Additionally, you can [manage your API keys via the API itself]({{root_url}}/API_Reference/Web_API_v3/API_Keys/index.html)). {% anchor h2%} Using API Keys